--- /dev/null	2013-08-22 18:57:26.000000000 -0400
+++ new/usr/src/pkg/manifests/driver-network-sfxge.mf	2013-08-22 18:57:26.840827110 -0400
@@ -0,0 +1,55 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# 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.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
+# Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+#
+
+#
+# The default for payload-bearing actions in this package is to appear in the
+# global zone only.  See the include file for greater detail, as well as
+# information about overriding the defaults.
+#
+<include global_zone_only_component>
+set name=pkg.fmri value=pkg:/driver/network/sfxge@$(PKGVERS)
+set name=pkg.description value="Solarflare 10GbE PCIE NIC Driver"
+set name=pkg.summary value="Solarflare 10GbE PCIE NIC Driver"
+set name=info.classification \
+    value=org.opensolaris.category.2008:Drivers/Networking
+set name=variant.arch value=$(ARCH)
+dir path=kernel group=sys
+dir path=kernel/drv group=sys
+dir path=kernel/drv/$(ARCH64) group=sys
+driver name=sfxge clone_perms="sfxge 0666 root sys" perms="* 0666 root sys" \
+    alias=pciex1924,703 \
+    alias=pciex1924,710 \
+    alias=pciex1924,803 \
+    alias=pciex1924,813
+file path=kernel/drv/$(ARCH64)/sfxge group=sys
+$(i386_ONLY)file path=kernel/drv/sfxge group=sys
+file path=kernel/drv/sfxge.conf group=sys \
+    original_name=SFCsfxge:kernel/drv/sfxge.conf preserve=renamenew
+legacy pkg=SFCsfxge desc="Solarflare 10GbE PCIE NIC Driver" \
+    name="Solarflare 10GbE PCIE NIC Driver"
+license cr_Sun license=cr_Sun
+license lic_CDDL license=lic_CDDL
--- old/usr/src/uts/common/Makefile.files	2013-08-22 18:57:26.921836931 -0400
+++ new/usr/src/uts/common/Makefile.files	2013-08-22 18:57:26.928165839 -0400
@@ -1787,6 +1787,18 @@
 
 RGE_OBJS += rge_main.o rge_chip.o rge_ndd.o rge_kstats.o rge_log.o rge_rxtx.o
 
+SFXGE_OBJS += efx_bootcfg.o efx_ev.o efx_intr.o efx_mac.o efx_mcdi.o efx_mon.o \
+	          efx_nic.o efx_nvram.o efx_phy.o efx_port.o efx_rx.o efx_sram.o efx_tx.o \
+  	          efx_vpd.o efx_wol.o falcon_gmac.o falcon_i2c.o falcon_mac.o falcon_mdio.o \
+	          falcon_nic.o falcon_nvram.o falcon_spi.o falcon_sram.o falcon_vpd.o \
+		  falcon_xmac.o lm87.o max6647.o nullmon.o nullphy.o qt2022c2.o qt2025c.o \
+	          sft9001.o sfx7101.o sfxge_bar.o sfxge_dma.o sfxge_err.o sfxge_ev.o \
+                  sfxge_gld_ndd.o sfxge_gld_v2.o sfxge_gld_v3.o sfxge_intr.o sfxge_mac.o \
+                  sfxge_mcdi.o sfxge_mon.o sfxge_nvram.o sfxge_pci.o sfxge_phy.o sfxge_rx.o \
+                  sfxge_sram.o sfxge_tcp.o sfxge_tx.o sfxge_vpd.o sfxge.o siena_mac.o \
+                  siena_mon.o siena_nic.o siena_nvram.o siena_phy.o siena_sram.o siena_vpd.o \
+                  txc43128.o xphy.o 
+
 URTW_OBJS += urtw.o
 
 ARN_OBJS += arn_hw.o arn_eeprom.o arn_mac.o arn_calib.o arn_ani.o arn_phy.o arn_regd.o arn_beacon.o \
--- old/usr/src/uts/common/Makefile.rules	2013-08-22 18:57:27.150652625 -0400
+++ new/usr/src/uts/common/Makefile.rules	2013-08-22 18:57:27.157305807 -0400
@@ -1348,6 +1348,10 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(UTSBASE)/common/io/sfxge/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 $(OBJS_DIR)/%.o:		$(UTSBASE)/common/ipp/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
@@ -2559,6 +2563,9 @@
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/io/myri10ge/drv/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
+$(LINTS_DIR)/%.ln:		$(UTSBASE)/common/io/sfxge/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/ipp/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
--- /dev/null	2013-08-22 18:57:27.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/compat.h	2013-08-22 18:57:27.424350860 -0400
@@ -0,0 +1,22 @@
+#ifndef _SFXGE_COMPAT_H
+#define _SFXGE_COMPAT_H
+
+/*
+ * Macro available in newer versions of /usr/include/sdt.h
+ */
+#include <sys/sdt.h>
+#include <sys/inline.h>
+
+#ifndef	DTRACE_PROBE5
+#define	DTRACE_PROBE5(name, type1, arg1, type2, arg2, type3, arg3,	\
+	type4, arg4, type5, arg5)					\
+	{								\
+		extern void __dtrace_probe_##name(uintptr_t, uintptr_t,	\
+		    uintptr_t, uintptr_t, uintptr_t);			\
+		__dtrace_probe_##name((uintptr_t)(arg1),		\
+		    (uintptr_t)(arg2), (uintptr_t)(arg3),		\
+		    (uintptr_t)(arg4), (uintptr_t)(arg5));		\
+	}
+#endif	/* DTRACE_PROBE5 */
+
+#endif
--- /dev/null	2013-08-22 18:57:27.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efsys.h	2013-08-22 18:57:27.510024587 -0400
@@ -0,0 +1,691 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_SYS_EFSYS_H
+#define	_SYS_EFSYS_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/cpuvar.h>
+#include <sys/disp.h>
+#include <sys/sdt.h>
+#include <sys/kstat.h>
+#include <sys/crc32.h>
+#include <sys/note.h>
+#include <sys/byteorder.h>
+
+#define	EFSYS_HAS_UINT64 1
+#define	EFSYS_USE_UINT64 0
+#ifdef	_BIG_ENDIAN
+#define	EFSYS_IS_BIG_ENDIAN 1
+#endif
+#ifdef	_LITTLE_ENDIAN
+#define	EFSYS_IS_LITTLE_ENDIAN 1
+#endif
+#include "efx_types.h"
+
+#ifdef _USE_GLD_V3_SOL10
+#include "compat.h"
+#endif
+
+/* Modifiers used for DOS builds */
+#define	__cs
+#define	__far
+
+/* Modifiers used for Windows builds */
+#define	__in
+#define	__in_opt
+#define	__in_ecount(_n)
+#define	__in_ecount_opt(_n)
+#define	__in_bcount(_n)
+#define	__in_bcount_opt(_n)
+
+#define	__out
+#define	__out_opt
+#define	__out_ecount(_n)
+#define	__out_ecount_opt(_n)
+#define	__out_bcount(_n)
+#define	__out_bcount_opt(_n)
+
+#define	__deref_out
+
+#define	__inout
+#define	__inout_opt
+#define	__inout_ecount(_n)
+#define	__inout_ecount_opt(_n)
+#define	__inout_bcount(_n)
+#define	__inout_bcount_opt(_n)
+#define	__inout_bcount_full_opt(_n)
+
+#define	__deref_out_bcount_opt(n)
+
+#define	__checkReturn
+
+#define	__drv_when(_p, _c)
+
+/* Code inclusion options */
+
+
+#define	EFSYS_OPT_NAMES 1
+
+#define	EFSYS_OPT_FALCON 1
+#define	EFSYS_OPT_SIENA 1
+#if DEBUG
+#define	EFSYS_OPT_CHECK_REG 1
+#else
+#define	EFSYS_OPT_CHECK_REG 0
+#endif
+
+#define	EFSYS_OPT_MCDI 1
+
+#define	EFSYS_OPT_MAC_FALCON_GMAC 1
+#define	EFSYS_OPT_MAC_FALCON_XMAC 1
+#define	EFSYS_OPT_MAC_STATS 1
+
+#define	EFSYS_OPT_LOOPBACK 1
+
+#define	EFSYS_OPT_MON_NULL 1
+#define	EFSYS_OPT_MON_LM87 1
+#define	EFSYS_OPT_MON_MAX6647 1
+#define	EFSYS_OPT_MON_SIENA 1
+#define	EFSYS_OPT_MON_STATS 1
+
+#define	EFSYS_OPT_PHY_NULL 1
+#define	EFSYS_OPT_PHY_QT2022C2 1
+#define	EFSYS_OPT_PHY_SFX7101 1
+#define	EFSYS_OPT_PHY_TXC43128 1
+#define	EFSYS_OPT_PHY_PM8358 1
+#define	EFSYS_OPT_PHY_SFT9001 1
+#define	EFSYS_OPT_PHY_QT2025C 1
+#define	EFSYS_OPT_PHY_STATS 1
+#define	EFSYS_OPT_PHY_PROPS 1
+#define	EFSYS_OPT_PHY_BIST 1
+#define	EFSYS_OPT_PHY_LED_CONTROL 1
+
+#define	EFSYS_OPT_VPD 1
+#define	EFSYS_OPT_NVRAM 1
+#define	EFSYS_OPT_NVRAM_FALCON_BOOTROM 1
+#define	EFSYS_OPT_NVRAM_SFT9001	0
+#define	EFSYS_OPT_NVRAM_SFX7101	0
+#define	EFSYS_OPT_BOOTCFG 1
+
+#define	EFSYS_OPT_PCIE_TUNE 1
+#define	EFSYS_OPT_DIAG 1
+#define	EFSYS_OPT_WOL 1
+#define	EFSYS_OPT_RX_SCALE 1
+#define	EFSYS_OPT_QSTATS 1
+
+#define	EFSYS_OPT_EV_PREFETCH 0
+
+#define	EFSYS_OPT_DECODE_INTR_FATAL 1
+
+/* ID */
+
+typedef struct __efsys_identifier_s	efsys_identifier_t;
+
+/* DMA */
+
+typedef uint64_t		efsys_dma_addr_t;
+
+typedef struct efsys_mem_s {
+	ddi_dma_handle_t	esm_dma_handle; /* DMA memory allocate/bind */
+	ddi_acc_handle_t	esm_acc_handle;	/* DMA memory read/write */
+	caddr_t			esm_base;
+	efsys_dma_addr_t	esm_addr;
+	size_t			esm_size;
+} efsys_mem_t;
+
+
+#define	EFSYS_MEM_ZERO(_esmp, _size)					\
+	do {								\
+		(void) memset((_esmp)->esm_base, 0, (_size));		\
+									\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_MEM_READD(_esmp, _offset, _edp)				\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)));	\
+									\
+		addr = (void *)((_esmp)->esm_base + (_offset));		\
+									\
+		(_edp)->ed_u32[0] = ddi_get32((_esmp)->esm_acc_handle,	\
+		    addr);						\
+									\
+		DTRACE_PROBE2(mem_readd, unsigned int, (_offset),	\
+		    uint32_t, (_edp)->ed_u32[0]);			\
+									\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_MEM_READQ(_esmp, _offset, _eqp)				\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)));	\
+									\
+		addr = (void *)((_esmp)->esm_base + (_offset));		\
+									\
+		(_eqp)->eq_u32[0] = ddi_get32((_esmp)->esm_acc_handle,	\
+		    addr++);						\
+		(_eqp)->eq_u32[1] = ddi_get32((_esmp)->esm_acc_handle,	\
+		    addr);						\
+									\
+		DTRACE_PROBE3(mem_readq, unsigned int, (_offset),	\
+		    uint32_t, (_eqp)->eq_u32[1],			\
+		    uint32_t, (_eqp)->eq_u32[0]);			\
+									\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_MEM_READO(_esmp, _offset, _eop)				\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)));	\
+									\
+		addr = (void *)((_esmp)->esm_base + (_offset));		\
+									\
+		(_eop)->eo_u32[0] = ddi_get32((_esmp)->esm_acc_handle,	\
+		    addr++);						\
+		(_eop)->eo_u32[1] = ddi_get32((_esmp)->esm_acc_handle,	\
+		    addr++);						\
+		(_eop)->eo_u32[2] = ddi_get32((_esmp)->esm_acc_handle,	\
+		    addr++);						\
+		(_eop)->eo_u32[3] = ddi_get32((_esmp)->esm_acc_handle,	\
+		    addr);						\
+									\
+		DTRACE_PROBE5(mem_reado, unsigned int, (_offset),	\
+		    uint32_t, (_eop)->eo_u32[3],			\
+		    uint32_t, (_eop)->eo_u32[2],			\
+		    uint32_t, (_eop)->eo_u32[1],			\
+		    uint32_t, (_eop)->eo_u32[0]);			\
+									\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_MEM_WRITED(_esmp, _offset, _edp)				\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)));	\
+									\
+		DTRACE_PROBE2(mem_writed, unsigned int, (_offset),	\
+		    uint32_t, (_edp)->ed_u32[0]);			\
+									\
+		addr = (void *)((_esmp)->esm_base + (_offset));		\
+									\
+		ddi_put32((_esmp)->esm_acc_handle, addr,		\
+		    (_edp)->ed_u32[0]);					\
+									\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp)				\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)));	\
+									\
+		DTRACE_PROBE3(mem_writeq, unsigned int, (_offset),	\
+		    uint32_t, (_eqp)->eq_u32[1],			\
+		    uint32_t, (_eqp)->eq_u32[0]);			\
+									\
+		addr = (void *)((_esmp)->esm_base + (_offset));		\
+									\
+		ddi_put32((_esmp)->esm_acc_handle, addr++,		\
+		    (_eqp)->eq_u32[0]);					\
+		ddi_put32((_esmp)->esm_acc_handle, addr,		\
+		    (_eqp)->eq_u32[1]);					\
+									\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_MEM_WRITEO(_esmp, _offset, _eop)				\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)));	\
+									\
+		DTRACE_PROBE5(mem_writeo, unsigned int, (_offset),	\
+		    uint32_t, (_eop)->eo_u32[3],			\
+		    uint32_t, (_eop)->eo_u32[2],			\
+		    uint32_t, (_eop)->eo_u32[1],			\
+		    uint32_t, (_eop)->eo_u32[0]);			\
+									\
+		addr = (void *)((_esmp)->esm_base + (_offset));		\
+									\
+		ddi_put32((_esmp)->esm_acc_handle, addr++,		\
+		    (_eop)->eo_u32[0]);					\
+		ddi_put32((_esmp)->esm_acc_handle, addr++,		\
+		    (_eop)->eo_u32[1]);					\
+		ddi_put32((_esmp)->esm_acc_handle, addr++,		\
+		    (_eop)->eo_u32[2]);					\
+		ddi_put32((_esmp)->esm_acc_handle, addr,		\
+		    (_eop)->eo_u32[3]);					\
+									\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_MEM_ADDR(_esmp)						\
+	((_esmp)->esm_addr)
+
+/* BAR */
+
+typedef struct efsys_bar_s {
+	kmutex_t		esb_lock;
+	ddi_acc_handle_t	esb_handle;
+	caddr_t			esb_base;
+} efsys_bar_t;
+
+#define	EFSYS_BAR_READD(_esbp, _offset, _edp, _lock)			\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)));	\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		if (_lock)						\
+			mutex_enter(&((_esbp)->esb_lock));		\
+									\
+		addr = (void *)((_esbp)->esb_base + (_offset));		\
+									\
+		(_edp)->ed_u32[0] = ddi_get32((_esbp)->esb_handle,	\
+		    addr);						\
+									\
+		DTRACE_PROBE2(bar_readd, unsigned int, (_offset),	\
+		    uint32_t, (_edp)->ed_u32[0]);			\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		if (_lock)						\
+			mutex_exit(&((_esbp)->esb_lock));		\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_BAR_READQ(_esbp, _offset, _eqp)				\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)));	\
+									\
+		mutex_enter(&((_esbp)->esb_lock));			\
+									\
+		addr = (void *)((_esbp)->esb_base + (_offset));		\
+									\
+		(_eqp)->eq_u32[0] = ddi_get32((_esbp)->esb_handle,	\
+		    addr++);						\
+		(_eqp)->eq_u32[1] = ddi_get32((_esbp)->esb_handle,	\
+		    addr);						\
+									\
+		DTRACE_PROBE3(bar_readq, unsigned int, (_offset),	\
+		    uint32_t, (_eqp)->eq_u32[1],			\
+		    uint32_t, (_eqp)->eq_u32[0]);			\
+									\
+		mutex_exit(&((_esbp)->esb_lock));			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_BAR_READO(_esbp, _offset, _eop, _lock)			\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)));	\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		if (_lock)						\
+			mutex_enter(&((_esbp)->esb_lock));		\
+									\
+		addr = (void *)((_esbp)->esb_base + (_offset));		\
+									\
+		(_eop)->eo_u32[0] = ddi_get32((_esbp)->esb_handle,	\
+		    addr++);						\
+		(_eop)->eo_u32[1] = ddi_get32((_esbp)->esb_handle,	\
+		    addr++);						\
+		(_eop)->eo_u32[2] = ddi_get32((_esbp)->esb_handle,	\
+		    addr++);						\
+		(_eop)->eo_u32[3] = ddi_get32((_esbp)->esb_handle,	\
+		    addr);						\
+									\
+		DTRACE_PROBE5(bar_reado, unsigned int, (_offset),	\
+		    uint32_t, (_eop)->eo_u32[3],			\
+		    uint32_t, (_eop)->eo_u32[2],			\
+		    uint32_t, (_eop)->eo_u32[1],			\
+		    uint32_t, (_eop)->eo_u32[0]);			\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		if (_lock)						\
+			mutex_exit(&((_esbp)->esb_lock));		\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock)			\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_dword_t)));	\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		if (_lock)						\
+			mutex_enter(&((_esbp)->esb_lock));		\
+									\
+		DTRACE_PROBE2(bar_writed, unsigned int, (_offset),	\
+		    uint32_t, (_edp)->ed_u32[0]);			\
+									\
+		addr = (void *)((_esbp)->esb_base + (_offset));		\
+									\
+		ddi_put32((_esbp)->esb_handle, addr,			\
+		    (_edp)->ed_u32[0]);					\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		if (_lock)						\
+			mutex_exit(&((_esbp)->esb_lock));		\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp)				\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)));	\
+									\
+		mutex_enter(&((_esbp)->esb_lock));			\
+									\
+		DTRACE_PROBE3(bar_writeq, unsigned int, (_offset),	\
+		    uint32_t, (_eqp)->eq_u32[1],			\
+		    uint32_t, (_eqp)->eq_u32[0]);			\
+									\
+		addr = (void *)((_esbp)->esb_base + (_offset));		\
+									\
+		ddi_put32((_esbp)->esb_handle, addr++,			\
+		    (_eqp)->eq_u32[0]);					\
+		ddi_put32((_esbp)->esb_handle, addr,			\
+		    (_eqp)->eq_u32[1]);					\
+									\
+		mutex_exit(&((_esbp)->esb_lock));			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock)			\
+	do {								\
+		uint32_t *addr;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		ASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)));	\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		if (_lock)						\
+			mutex_enter(&((_esbp)->esb_lock));		\
+									\
+		DTRACE_PROBE5(bar_writeo, unsigned int, (_offset),	\
+		    uint32_t, (_eop)->eo_u32[3],			\
+		    uint32_t, (_eop)->eo_u32[2],			\
+		    uint32_t, (_eop)->eo_u32[1],			\
+		    uint32_t, (_eop)->eo_u32[0]);			\
+									\
+		addr = (void *)((_esbp)->esb_base + (_offset));		\
+									\
+		ddi_put32((_esbp)->esb_handle, addr++,			\
+		    (_eop)->eo_u32[0]);					\
+		ddi_put32((_esbp)->esb_handle, addr++,			\
+		    (_eop)->eo_u32[1]);					\
+		ddi_put32((_esbp)->esb_handle, addr++,			\
+		    (_eop)->eo_u32[2]);					\
+		ddi_put32((_esbp)->esb_handle, addr,			\
+		    (_eop)->eo_u32[3]);					\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+		if (_lock)						\
+			mutex_exit(&((_esbp)->esb_lock));		\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+/* SPIN */
+
+#define	EFSYS_SPIN(_us)							\
+	do {								\
+		drv_usecwait(_us);					\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_SLEEP	EFSYS_SPIN
+
+/* BARRIERS */
+
+/* Strict ordering guaranteed by devacc.devacc_attr_dataorder */
+#define	EFSYS_MEM_READ_BARRIER()	membar_consumer()
+/* TODO: Is ddi_put32() properly barriered? */
+#define	EFSYS_PIO_WRITE_BARRIER()
+
+/* TIMESTAMP */
+
+typedef	clock_t	efsys_timestamp_t;
+
+#define	EFSYS_TIMESTAMP(_usp)						\
+	do {								\
+		clock_t now;						\
+									\
+		now = ddi_get_lbolt();					\
+		*(_usp) = drv_hztousec(now);				\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+/* KMEM */
+
+#define	EFSYS_KMEM_ALLOC(_esip, _size, _p)				\
+	do {								\
+		(_esip) = (_esip);					\
+		(_p) = kmem_zalloc((_size), KM_NOSLEEP);		\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_KMEM_FREE(_esip, _size, _p)				\
+	do {								\
+		(_esip) = (_esip);					\
+		kmem_free((_p), (_size));				\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+/* LOCK */
+
+typedef kmutex_t	efsys_lock_t;
+
+#define	EFSYS_LOCK_MAGIC	0x000010c4
+
+#define	EFSYS_LOCK(_lockp, _state)					\
+	do {								\
+		mutex_enter(_lockp);					\
+		(_state) = EFSYS_LOCK_MAGIC;				\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_UNLOCK(_lockp, _state)					\
+	do {								\
+		if ((_state) != EFSYS_LOCK_MAGIC)			\
+			ASSERT(B_FALSE);				\
+		mutex_exit(_lockp);					\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+/* PREEMPT */
+
+#define	EFSYS_PREEMPT_DISABLE(_state)					\
+	do {								\
+		(_state) = ddi_enter_critical();			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_PREEMPT_ENABLE(_state)					\
+	do {								\
+		ddi_exit_critical(_state);				\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+/* STAT */
+
+typedef kstat_named_t		efsys_stat_t;
+
+#define	EFSYS_STAT_INCR(_knp, _delta) 					\
+	do {								\
+		((_knp)->value.ui64) += (_delta);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_STAT_DECR(_knp, _delta) 					\
+	do {								\
+		((_knp)->value.ui64) -= (_delta);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_STAT_SET(_knp, _val)					\
+	do {								\
+		((_knp)->value.ui64) = (_val);				\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_STAT_SET_QWORD(_knp, _valp)				\
+	do {								\
+		((_knp)->value.ui64) = LE_64((_valp)->eq_u64[0]);	\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_STAT_SET_DWORD(_knp, _valp)				\
+	do {								\
+		((_knp)->value.ui64) = LE_32((_valp)->ed_u32[0]);	\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_STAT_INCR_QWORD(_knp, _valp)				\
+	do {								\
+		((_knp)->value.ui64) += LE_64((_valp)->eq_u64[0]);	\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFSYS_STAT_SUBR_QWORD(_knp, _valp)				\
+	do {								\
+		((_knp)->value.ui64) -= LE_64((_valp)->eq_u64[0]);	\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+/* ERR */
+
+extern void	sfxge_err(efsys_identifier_t *, unsigned int,
+		    uint32_t, uint32_t);
+
+#if EFSYS_OPT_DECODE_INTR_FATAL
+#define	EFSYS_ERR(_esip, _code, _dword0, _dword1)			\
+	do {								\
+		sfxge_err((_esip), (_code), (_dword0), (_dword1));	\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+#endif
+
+/* PROBE */
+
+#define	EFSYS_PROBE(_name)						\
+	DTRACE_PROBE(_name)
+
+#define	EFSYS_PROBE1(_name, _type1, _arg1)				\
+	DTRACE_PROBE1(_name, _type1, _arg1)
+
+#define	EFSYS_PROBE2(_name, _type1, _arg1, _type2, _arg2)		\
+	DTRACE_PROBE2(_name, _type1, _arg1, _type2, _arg2)
+
+#define	EFSYS_PROBE3(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3)						\
+	DTRACE_PROBE3(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3)
+
+#define	EFSYS_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4)				\
+	DTRACE_PROBE4(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4)
+
+#define	EFSYS_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5)		\
+	DTRACE_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5)
+
+#ifdef DTRACE_PROBE6
+#define	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
+	    _type6, _arg6)						\
+	DTRACE_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
+	    _type6, _arg6)
+#else
+#define	EFSYS_PROBE6(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
+	    _type6, _arg6)						\
+	DTRACE_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5)
+#endif
+
+#ifdef DTRACE_PROBE7
+#define	EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
+	    _type6, _arg6, _type7, _arg7)				\
+	DTRACE_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
+	    _type6, _arg6, _type7, _arg7)
+#else
+#define	EFSYS_PROBE7(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5,		\
+	    _type6, _arg6, _type7, _arg7)				\
+	DTRACE_PROBE5(_name, _type1, _arg1, _type2, _arg2,		\
+	    _type3, _arg3, _type4, _arg4, _type5, _arg5)
+#endif
+
+/* ASSERT */
+
+#define	EFSYS_ASSERT(_exp)		ASSERT(_exp)
+#define	EFSYS_ASSERT3U(_x, _op, _y)	ASSERT3U(_x, _op, _y)
+#define	EFSYS_ASSERT3S(_x, _op, _y)	ASSERT3S(_x, _op, _y)
+#define	EFSYS_ASSERT3P(_x, _op, _y)	ASSERT3P(_x, _op, _y)
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_EFSYS_H */
--- /dev/null	2013-08-22 18:57:27.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx.h	2013-08-22 18:57:27.600441504 -0400
@@ -0,0 +1,1906 @@
+/*-
+ * Copyright 2006-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_EFX_H
+#define	_SYS_EFX_H
+
+#include "efsys.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	EFX_STATIC_ASSERT(_cond) ((void)sizeof(char[(_cond) ? 1 : -1]))
+
+#define	EFX_ARRAY_SIZE(_array) (sizeof(_array) / sizeof((_array)[0]))
+
+#ifndef EFSYS_MEM_IS_NULL
+#define	EFSYS_MEM_IS_NULL(_esmp) ((_esmp)->esm_base == NULL)
+#endif
+
+typedef enum efx_family_e {
+	EFX_FAMILY_INVALID,
+	EFX_FAMILY_FALCON,
+	EFX_FAMILY_SIENA,
+	EFX_FAMILY_NTYPES
+} efx_family_t;
+
+extern	__checkReturn	int
+efx_family(
+	__in		uint16_t venid,
+	__in		uint16_t devid,
+	__out		efx_family_t *efp);
+
+extern	__checkReturn	int
+efx_infer_family(
+	__in		efsys_bar_t *esbp,
+	__out		efx_family_t *efp);
+
+#define	EFX_PCI_VENID_SFC		0x1924
+#define	EFX_PCI_DEVID_FALCON		0x0710
+#define	EFX_PCI_DEVID_BETHPAGE		0x0803
+#define	EFX_PCI_DEVID_SIENA		0x0813
+#define	EFX_PCI_DEVID_SIENA_F1_UNINIT	0x0810
+
+#define	EFX_MEM_BAR	2
+
+/* Error codes */
+
+enum {
+	EFX_ERR_INVALID,
+	EFX_ERR_SRAM_OOB,
+	EFX_ERR_BUFID_DC_OOB,
+	EFX_ERR_MEM_PERR,
+	EFX_ERR_RBUF_OWN,
+	EFX_ERR_TBUF_OWN,
+	EFX_ERR_RDESQ_OWN,
+	EFX_ERR_TDESQ_OWN,
+	EFX_ERR_EVQ_OWN,
+	EFX_ERR_EVFF_OFLO,
+	EFX_ERR_ILL_ADDR,
+	EFX_ERR_SRAM_PERR,
+	EFX_ERR_NCODES
+};
+
+/* NIC */
+
+typedef struct efx_nic_s	efx_nic_t;
+
+extern	__checkReturn	int
+efx_nic_create(
+	__in		efx_family_t family,
+	__in		efsys_identifier_t *esip,
+	__in		efsys_bar_t *esbp,
+	__in		efsys_lock_t *eslp,
+	__deref_out	efx_nic_t **enpp);
+
+extern	__checkReturn	int
+efx_nic_probe(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_PCIE_TUNE
+
+extern	__checkReturn	int
+efx_nic_pcie_tune(
+	__in		efx_nic_t *enp,
+	unsigned int	nlanes);
+
+extern	__checkReturn	int
+efx_nic_pcie_extended_sync(
+	__in		efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_PCIE_TUNE */
+
+extern 	__checkReturn	int
+efx_nic_init(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+efx_nic_reset(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_DIAG
+
+extern	__checkReturn	int
+efx_nic_register_test(
+	__in		efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+extern		void
+efx_nic_fini(
+	__in		efx_nic_t *enp);
+
+extern		void
+efx_nic_unprobe(
+	__in		efx_nic_t *enp);
+
+extern 		void
+efx_nic_destroy(
+	__in	efx_nic_t *enp);
+
+#if EFSYS_OPT_MCDI
+
+typedef struct efx_mcdi_req_s efx_mcdi_req_t;
+
+typedef enum efx_mcdi_exception_e {
+	EFX_MCDI_EXCEPTION_MC_REBOOT,
+	EFX_MCDI_EXCEPTION_MC_BADASSERT,
+} efx_mcdi_exception_t;
+
+typedef struct efx_mcdi_transport_s {
+	void		*emt_context;
+	void		(*emt_execute)(void *, efx_mcdi_req_t *);
+	void		(*emt_ev_cpl)(void *);
+	void		(*emt_exception)(void *, efx_mcdi_exception_t);
+} efx_mcdi_transport_t;
+
+extern	__checkReturn	int
+efx_mcdi_init(
+	__in		efx_nic_t *enp,
+	__in		const efx_mcdi_transport_t *mtp);
+
+extern	__checkReturn	int
+efx_mcdi_reboot(
+	__in		efx_nic_t *enp);
+
+extern			void
+efx_mcdi_request_start(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp,
+	__in		boolean_t ev_cpl);
+
+extern	__checkReturn	boolean_t
+efx_mcdi_request_poll(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	boolean_t
+efx_mcdi_request_abort(
+	__in		efx_nic_t *enp);
+
+extern			void
+efx_mcdi_fini(
+	__in		efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_MCDI */
+
+/* INTR */
+
+#define	EFX_NINTR_FALCON 64
+#define	EFX_NINTR_SIENA 1024
+
+typedef enum efx_intr_type_e {
+	EFX_INTR_INVALID = 0,
+	EFX_INTR_LINE,
+	EFX_INTR_MESSAGE,
+	EFX_INTR_NTYPES
+} efx_intr_type_t;
+
+#define	EFX_INTR_SIZE	(sizeof (efx_oword_t))
+
+extern	__checkReturn	int
+efx_intr_init(
+	__in		efx_nic_t *enp,
+	__in		efx_intr_type_t type,
+	__in		efsys_mem_t *esmp);
+
+extern 			void
+efx_intr_enable(
+	__in		efx_nic_t *enp);
+
+extern 			void
+efx_intr_disable(
+	__in		efx_nic_t *enp);
+
+extern 			void
+efx_intr_disable_unlocked(
+	__in		efx_nic_t *enp);
+
+#define	EFX_INTR_NEVQS	32
+
+extern __checkReturn	int
+efx_intr_trigger(
+	__in		efx_nic_t *enp,
+	__in		unsigned int level);
+
+extern			void
+efx_intr_status_line(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *fatalp,
+	__out		uint32_t *maskp);
+
+extern			void
+efx_intr_status_message(
+	__in		efx_nic_t *enp,
+	__in		unsigned int message,
+	__out		boolean_t *fatalp);
+
+extern			void
+efx_intr_fatal(
+	__in		efx_nic_t *enp);
+
+extern			void
+efx_intr_fini(
+	__in		efx_nic_t *enp);
+
+/* MAC */
+
+#if EFSYS_OPT_MAC_STATS
+
+/* START MKCONFIG GENERATED EfxHeaderMacBlock bb8d39428b6fdcf5 */
+typedef enum efx_mac_stat_e {
+	EFX_MAC_RX_OCTETS,
+	EFX_MAC_RX_PKTS,
+	EFX_MAC_RX_UNICST_PKTS,
+	EFX_MAC_RX_MULTICST_PKTS,
+	EFX_MAC_RX_BRDCST_PKTS,
+	EFX_MAC_RX_PAUSE_PKTS,
+	EFX_MAC_RX_LE_64_PKTS,
+	EFX_MAC_RX_65_TO_127_PKTS,
+	EFX_MAC_RX_128_TO_255_PKTS,
+	EFX_MAC_RX_256_TO_511_PKTS,
+	EFX_MAC_RX_512_TO_1023_PKTS,
+	EFX_MAC_RX_1024_TO_15XX_PKTS,
+	EFX_MAC_RX_GE_15XX_PKTS,
+	EFX_MAC_RX_ERRORS,
+	EFX_MAC_RX_FCS_ERRORS,
+	EFX_MAC_RX_DROP_EVENTS,
+	EFX_MAC_RX_FALSE_CARRIER_ERRORS,
+	EFX_MAC_RX_SYMBOL_ERRORS,
+	EFX_MAC_RX_ALIGN_ERRORS,
+	EFX_MAC_RX_INTERNAL_ERRORS,
+	EFX_MAC_RX_JABBER_PKTS,
+	EFX_MAC_RX_LANE0_CHAR_ERR,
+	EFX_MAC_RX_LANE1_CHAR_ERR,
+	EFX_MAC_RX_LANE2_CHAR_ERR,
+	EFX_MAC_RX_LANE3_CHAR_ERR,
+	EFX_MAC_RX_LANE0_DISP_ERR,
+	EFX_MAC_RX_LANE1_DISP_ERR,
+	EFX_MAC_RX_LANE2_DISP_ERR,
+	EFX_MAC_RX_LANE3_DISP_ERR,
+	EFX_MAC_RX_MATCH_FAULT,
+	EFX_MAC_RX_NODESC_DROP_CNT,
+	EFX_MAC_TX_OCTETS,
+	EFX_MAC_TX_PKTS,
+	EFX_MAC_TX_UNICST_PKTS,
+	EFX_MAC_TX_MULTICST_PKTS,
+	EFX_MAC_TX_BRDCST_PKTS,
+	EFX_MAC_TX_PAUSE_PKTS,
+	EFX_MAC_TX_LE_64_PKTS,
+	EFX_MAC_TX_65_TO_127_PKTS,
+	EFX_MAC_TX_128_TO_255_PKTS,
+	EFX_MAC_TX_256_TO_511_PKTS,
+	EFX_MAC_TX_512_TO_1023_PKTS,
+	EFX_MAC_TX_1024_TO_15XX_PKTS,
+	EFX_MAC_TX_GE_15XX_PKTS,
+	EFX_MAC_TX_ERRORS,
+	EFX_MAC_TX_SGL_COL_PKTS,
+	EFX_MAC_TX_MULT_COL_PKTS,
+	EFX_MAC_TX_EX_COL_PKTS,
+	EFX_MAC_TX_LATE_COL_PKTS,
+	EFX_MAC_TX_DEF_PKTS,
+	EFX_MAC_TX_EX_DEF_PKTS,
+	EFX_MAC_NSTATS
+} efx_mac_stat_t;
+
+/* END MKCONFIG GENERATED EfxHeaderMacBlock */
+
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+typedef enum efx_link_mode_e {
+	EFX_LINK_UNKNOWN = 0,
+	EFX_LINK_DOWN,
+	EFX_LINK_10HDX,
+	EFX_LINK_10FDX,
+	EFX_LINK_100HDX,
+	EFX_LINK_100FDX,
+	EFX_LINK_1000HDX,
+	EFX_LINK_1000FDX,
+	EFX_LINK_10000FDX,
+	EFX_LINK_NMODES
+} efx_link_mode_t;
+
+#define	EFX_MAC_SDU_MAX	9202
+
+#define	EFX_MAC_PDU(_sdu) 				\
+	P2ROUNDUP(((_sdu)				\
+		    + /* EtherII */ 14			\
+		    + /* VLAN */ 4			\
+		    + /* CRC */ 4			\
+		    + /* bug16011 */ 16),		\
+		    (1 << 3))
+
+#define	EFX_MAC_PDU_MIN	60
+#define	EFX_MAC_PDU_MAX	EFX_MAC_PDU(EFX_MAC_SDU_MAX)
+
+extern	__checkReturn	int
+efx_mac_pdu_set(
+	__in		efx_nic_t *enp,
+	__in		size_t pdu);
+
+extern	__checkReturn	int
+efx_mac_addr_set(
+	__in		efx_nic_t *enp,
+	__in		uint8_t *addr);
+
+extern	__checkReturn	int
+efx_mac_filter_set(
+	__in		efx_nic_t *enp,
+	__in		boolean_t unicst,
+	__in		boolean_t brdcst);
+
+extern	__checkReturn	int
+efx_mac_drain(
+	__in		efx_nic_t *enp,
+	__in		boolean_t enabled);
+
+extern	__checkReturn	int
+efx_mac_up(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *mac_upp);
+
+#define	EFX_FCNTL_RESPOND	0x00000001
+#define	EFX_FCNTL_GENERATE	0x00000002
+
+extern	__checkReturn	int
+efx_mac_fcntl_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int fcntl,
+	__in		boolean_t autoneg);
+
+extern			void
+efx_mac_fcntl_get(
+	__in		efx_nic_t *enp,
+	__out		unsigned int *fcntl_wantedp,
+	__out		unsigned int *fcntl_linkp);
+
+#define	EFX_MAC_HASH_BITS	(1 << 8)
+
+extern	__checkReturn			int
+efx_mac_hash_set(
+	__in				efx_nic_t *enp,
+	__in_ecount(EFX_MAC_HASH_BITS)	unsigned int const *bucket);
+
+#if EFSYS_OPT_MAC_STATS
+
+#if EFSYS_OPT_NAMES
+
+extern	__checkReturn			const char __cs *
+efx_mac_stat_name(
+	__in				efx_nic_t *enp,
+	__in				unsigned int id);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+#define	EFX_MAC_STATS_SIZE 0x400
+
+/*
+ * Upload mac statistics supported by the hardware into the given buffer.
+ *
+ * The reference buffer must be at least %EFX_MAC_STATS_SIZE bytes,
+ * and page aligned.
+ *
+ * The hardware will only DMA statistics that it understands (of course).
+ * Drivers should not make any assumptions about which statistics are
+ * supported, especially when the statistics are generated by firmware.
+ *
+ * Thus, drivers should zero this buffer before use, so that not-understood
+ * statistics read back as zero.
+ */
+extern	__checkReturn			int
+efx_mac_stats_upload(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp);
+
+extern	__checkReturn			int
+efx_mac_stats_periodic(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__in				uint16_t period_ms,
+	__in				boolean_t events);
+
+extern	__checkReturn			int
+efx_mac_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *stat,
+	__out_opt			uint32_t *generationp);
+
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+/* MON */
+
+typedef enum efx_mon_type_e {
+	EFX_MON_INVALID = 0,
+	EFX_MON_NULL,
+	EFX_MON_LM87,
+	EFX_MON_MAX6647,
+	EFX_MON_SFC90X0,
+	EFX_MON_NTYPES
+} efx_mon_type_t;
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+efx_mon_name(
+	__in	efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+extern	__checkReturn	int
+efx_mon_init(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_MON_STATS
+
+#define	EFX_MON_STATS_SIZE 0x100
+
+/* START MKCONFIG GENERATED MonitorHeaderStatsBlock 2a60d293f55d0285 */
+typedef enum efx_mon_stat_e {
+	EFX_MON_STAT_2_5V,
+	EFX_MON_STAT_VCCP1,
+	EFX_MON_STAT_VCC,
+	EFX_MON_STAT_5V,
+	EFX_MON_STAT_12V,
+	EFX_MON_STAT_VCCP2,
+	EFX_MON_STAT_EXT_TEMP,
+	EFX_MON_STAT_INT_TEMP,
+	EFX_MON_STAT_AIN1,
+	EFX_MON_STAT_AIN2,
+	EFX_MON_STAT_INT_COOLING,
+	EFX_MON_STAT_EXT_COOLING,
+	EFX_MON_STAT_1V,
+	EFX_MON_STAT_1_2V,
+	EFX_MON_STAT_1_8V,
+	EFX_MON_STAT_3_3V,
+	EFX_MON_STAT_1_2VA,
+	EFX_MON_STAT_VREF,
+	EFX_MON_NSTATS
+} efx_mon_stat_t;
+
+/* END MKCONFIG GENERATED MonitorHeaderStatsBlock */
+
+typedef enum efx_mon_stat_state_e {
+	EFX_MON_STAT_STATE_OK = 0,
+	EFX_MON_STAT_STATE_WARNING = 1,
+	EFX_MON_STAT_STATE_FATAL = 2,
+	EFX_MON_STAT_STATE_BROKEN = 3,
+} efx_mon_stat_state_t;
+
+typedef struct efx_mon_stat_value_t {
+	uint16_t	emsv_value;
+	uint16_t	emsv_state;
+} efx_mon_stat_value_t;
+
+#if EFSYS_OPT_NAMES
+
+extern					const char __cs *
+efx_mon_stat_name(
+	__in				efx_nic_t *enp,
+	__in				efx_mon_stat_t id);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+extern	__checkReturn			int
+efx_mon_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values);
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+extern		void
+efx_mon_fini(
+	__in	efx_nic_t *enp);
+
+/* PHY */
+
+#define	PMA_PMD_MMD	1
+#define	PCS_MMD		3
+#define	PHY_XS_MMD	4
+#define	DTE_XS_MMD	5
+#define	AN_MMD		7
+#define	CL22EXT_MMD	29
+
+#define	MAXMMD		((1 << 5) - 1)
+
+/* PHY types */
+#define	EFX_PHY_NULL		0x0
+#define	EFX_PHY_TXC43128	0x1
+#define	EFX_PHY_SFX7101		0x3
+#define	EFX_PHY_QT2022C2	0x4
+#define	EFX_PHY_SFT9001A	0x8
+#define	EFX_PHY_QT2025C		0x9
+#define	EFX_PHY_SFT9001B	0xa
+#define	EFX_PHY_QLX111V		0xc
+
+extern	__checkReturn	int
+efx_phy_verify(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_PHY_LED_CONTROL
+
+typedef enum efx_phy_led_mode_e {
+	EFX_PHY_LED_DEFAULT = 0,
+	EFX_PHY_LED_OFF,
+	EFX_PHY_LED_ON,
+	EFX_PHY_LED_FLASH,
+	EFX_PHY_LED_NMODES
+} efx_phy_led_mode_t;
+
+extern	__checkReturn	int
+efx_phy_led_set(
+	__in	efx_nic_t *enp,
+	__in	efx_phy_led_mode_t mode);
+
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+extern	__checkReturn	int
+efx_port_init(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_LOOPBACK
+
+typedef enum efx_loopback_type_e {
+	EFX_LOOPBACK_OFF = 0,
+	EFX_LOOPBACK_DATA = 1,
+	EFX_LOOPBACK_GMAC = 2,
+	EFX_LOOPBACK_XGMII = 3,
+	EFX_LOOPBACK_XGXS = 4,
+	EFX_LOOPBACK_XAUI = 5,
+	EFX_LOOPBACK_GMII = 6,
+	EFX_LOOPBACK_SGMII = 7,
+	EFX_LOOPBACK_XGBR = 8,
+	EFX_LOOPBACK_XFI = 9,
+	EFX_LOOPBACK_XAUI_FAR = 10,
+	EFX_LOOPBACK_GMII_FAR = 11,
+	EFX_LOOPBACK_SGMII_FAR = 12,
+	EFX_LOOPBACK_XFI_FAR = 13,
+	EFX_LOOPBACK_GPHY = 14,
+	EFX_LOOPBACK_PHY_XS = 15,
+	EFX_LOOPBACK_PCS = 16,
+	EFX_LOOPBACK_PMA_PMD = 17,
+	EFX_LOOPBACK_NTYPES
+} efx_loopback_type_t;
+
+#define	EFX_LOOPBACK_MAC_MASK			\
+	((1 << EFX_LOOPBACK_DATA) |		\
+	    (1 << EFX_LOOPBACK_GMAC) | 		\
+	    (1 << EFX_LOOPBACK_XGMII) | 	\
+	    (1 << EFX_LOOPBACK_XGXS) | 		\
+	    (1 << EFX_LOOPBACK_XAUI) |		\
+	    (1 << EFX_LOOPBACK_GMII) |		\
+	    (1 << EFX_LOOPBACK_SGMII) |		\
+	    (1 << EFX_LOOPBACK_XGBR) |		\
+	    (1 << EFX_LOOPBACK_XFI) |		\
+	    (1 << EFX_LOOPBACK_XAUI_FAR) |	\
+	    (1 << EFX_LOOPBACK_GMII_FAR) |	\
+	    (1 << EFX_LOOPBACK_SGMII_FAR) |	\
+	    (1 << EFX_LOOPBACK_XFI_FAR))
+
+#define EFX_LOOPBACK_MASK			\
+	((1 << EFX_LOOPBACK_NTYPES) - 1)
+
+extern	__checkReturn	int
+efx_port_loopback_set(
+	__in	efx_nic_t *enp,
+	__in	efx_link_mode_t link_mode,
+	__in	efx_loopback_type_t type);
+
+#if EFSYS_OPT_NAMES
+
+extern	__checkReturn	const char __cs *
+efx_loopback_type_name(
+	__in		efx_nic_t *enp,
+	__in		efx_loopback_type_t type);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+extern	__checkReturn	int
+efx_port_poll(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t	*link_modep);
+
+extern 		void
+efx_port_fini(
+	__in	efx_nic_t *enp);
+
+typedef enum efx_phy_cap_type_e {
+	EFX_PHY_CAP_INVALID = 0,
+	EFX_PHY_CAP_10HDX,
+	EFX_PHY_CAP_10FDX,
+	EFX_PHY_CAP_100HDX,
+	EFX_PHY_CAP_100FDX,
+	EFX_PHY_CAP_1000HDX,
+	EFX_PHY_CAP_1000FDX,
+	EFX_PHY_CAP_10000FDX,
+	EFX_PHY_CAP_PAUSE,
+	EFX_PHY_CAP_ASYM,
+	EFX_PHY_CAP_AN,
+	EFX_PHY_CAP_NTYPES
+} efx_phy_cap_type_t;
+
+
+#define	EFX_PHY_CAP_CURRENT	0x00000000
+#define	EFX_PHY_CAP_DEFAULT	0x00000001
+#define	EFX_PHY_CAP_PERM	0x00000002
+
+extern		void
+efx_phy_adv_cap_get(
+	__in		efx_nic_t *enp,
+	__in            uint32_t flag,
+	__out		uint32_t *maskp);
+
+extern	__checkReturn	int
+efx_phy_adv_cap_set(
+	__in		efx_nic_t *enp,
+	__in		uint32_t mask);
+
+extern			void
+efx_phy_lp_cap_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *maskp);
+
+extern	__checkReturn	int
+efx_phy_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip);
+
+typedef enum efx_phy_media_type_e {
+	EFX_PHY_MEDIA_INVALID = 0,
+	EFX_PHY_MEDIA_XAUI,
+	EFX_PHY_MEDIA_CX4,
+	EFX_PHY_MEDIA_KX4,
+	EFX_PHY_MEDIA_XFP,
+	EFX_PHY_MEDIA_SFP_PLUS,
+	EFX_PHY_MEDIA_BASE_T,
+	EFX_PHY_MEDIA_NTYPES
+} efx_phy_media_type_t;
+
+/* Get the type of medium currently used.  If the board has ports for
+ * modules, a module is present, and we recognise the media type of
+ * the module, then this will be the media type of the module.
+ * Otherwise it will be the media type of the port.
+ */
+extern			void
+efx_phy_media_type_get(
+	__in		efx_nic_t *enp,
+	__out		efx_phy_media_type_t *typep);
+
+#if EFSYS_OPT_PHY_STATS
+
+/* START MKCONFIG GENERATED PhyHeaderStatsBlock 30ed56ad501f8e36 */
+typedef enum efx_phy_stat_e {
+	EFX_PHY_STAT_OUI,
+	EFX_PHY_STAT_PMA_PMD_LINK_UP,
+	EFX_PHY_STAT_PMA_PMD_RX_FAULT,
+	EFX_PHY_STAT_PMA_PMD_TX_FAULT,
+	EFX_PHY_STAT_PMA_PMD_REV_A,
+	EFX_PHY_STAT_PMA_PMD_REV_B,
+	EFX_PHY_STAT_PMA_PMD_REV_C,
+	EFX_PHY_STAT_PMA_PMD_REV_D,
+	EFX_PHY_STAT_PCS_LINK_UP,
+	EFX_PHY_STAT_PCS_RX_FAULT,
+	EFX_PHY_STAT_PCS_TX_FAULT,
+	EFX_PHY_STAT_PCS_BER,
+	EFX_PHY_STAT_PCS_BLOCK_ERRORS,
+	EFX_PHY_STAT_PHY_XS_LINK_UP,
+	EFX_PHY_STAT_PHY_XS_RX_FAULT,
+	EFX_PHY_STAT_PHY_XS_TX_FAULT,
+	EFX_PHY_STAT_PHY_XS_ALIGN,
+	EFX_PHY_STAT_PHY_XS_SYNC_A,
+	EFX_PHY_STAT_PHY_XS_SYNC_B,
+	EFX_PHY_STAT_PHY_XS_SYNC_C,
+	EFX_PHY_STAT_PHY_XS_SYNC_D,
+	EFX_PHY_STAT_AN_LINK_UP,
+	EFX_PHY_STAT_AN_MASTER,
+	EFX_PHY_STAT_AN_LOCAL_RX_OK,
+	EFX_PHY_STAT_AN_REMOTE_RX_OK,
+	EFX_PHY_STAT_CL22EXT_LINK_UP,
+	EFX_PHY_STAT_SNR_A,
+	EFX_PHY_STAT_SNR_B,
+	EFX_PHY_STAT_SNR_C,
+	EFX_PHY_STAT_SNR_D,
+	EFX_PHY_STAT_PMA_PMD_SIGNAL_A,
+	EFX_PHY_STAT_PMA_PMD_SIGNAL_B,
+	EFX_PHY_STAT_PMA_PMD_SIGNAL_C,
+	EFX_PHY_STAT_PMA_PMD_SIGNAL_D,
+	EFX_PHY_STAT_AN_COMPLETE,
+	EFX_PHY_STAT_PMA_PMD_REV_MAJOR,
+	EFX_PHY_STAT_PMA_PMD_REV_MINOR,
+	EFX_PHY_STAT_PMA_PMD_REV_MICRO,
+	EFX_PHY_STAT_PCS_FW_VERSION_0,
+	EFX_PHY_STAT_PCS_FW_VERSION_1,
+	EFX_PHY_STAT_PCS_FW_VERSION_2,
+	EFX_PHY_STAT_PCS_FW_VERSION_3,
+	EFX_PHY_STAT_PCS_FW_BUILD_YY,
+	EFX_PHY_STAT_PCS_FW_BUILD_MM,
+	EFX_PHY_STAT_PCS_FW_BUILD_DD,
+	EFX_PHY_STAT_PCS_OP_MODE,
+	EFX_PHY_NSTATS
+} efx_phy_stat_t;
+
+/* END MKCONFIG GENERATED PhyHeaderStatsBlock */
+
+#if EFSYS_OPT_NAMES
+
+extern					const char __cs *
+efx_phy_stat_name(
+	__in				efx_nic_t *enp,
+	__in				efx_phy_stat_t stat);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+#define	EFX_PHY_STATS_SIZE 0x100
+
+extern	__checkReturn			int
+efx_phy_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat);
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+efx_phy_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+#define	EFX_PHY_PROP_DEFAULT	0x00000001
+
+extern	__checkReturn	int
+efx_phy_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp);
+
+extern	__checkReturn	int
+efx_phy_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val);
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#if EFSYS_OPT_PHY_BIST
+
+typedef enum efx_phy_bist_type_e {
+	EFX_PHY_BIST_TYPE_UNKNOWN,
+	EFX_PHY_BIST_TYPE_NORMAL,
+	EFX_PHY_BIST_TYPE_CABLE_SHORT,
+	EFX_PHY_BIST_TYPE_CABLE_LONG,
+	EFX_PHY_BIST_TYPE_NTYPES,
+} efx_phy_bist_type_t;
+
+typedef enum efx_phy_bist_result_e {
+	EFX_PHY_BIST_RESULT_UNKNOWN,
+	EFX_PHY_BIST_RESULT_RUNNING,
+	EFX_PHY_BIST_RESULT_PASSED,
+	EFX_PHY_BIST_RESULT_FAILED,
+} efx_phy_bist_result_t;
+
+typedef enum efx_phy_cable_status_e {
+	EFX_PHY_CABLE_STATUS_OK,
+	EFX_PHY_CABLE_STATUS_INVALID,
+	EFX_PHY_CABLE_STATUS_OPEN,
+	EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT,
+	EFX_PHY_CABLE_STATUS_INTERPAIRSHORT,
+	EFX_PHY_CABLE_STATUS_BUSY,
+} efx_phy_cable_status_t;
+
+typedef enum efx_phy_bist_value_e {
+	EFX_PHY_BIST_CABLE_LENGTH_A,
+	EFX_PHY_BIST_CABLE_LENGTH_B,
+	EFX_PHY_BIST_CABLE_LENGTH_C,
+	EFX_PHY_BIST_CABLE_LENGTH_D,
+	EFX_PHY_BIST_CABLE_STATUS_A,
+	EFX_PHY_BIST_CABLE_STATUS_B,
+	EFX_PHY_BIST_CABLE_STATUS_C,
+	EFX_PHY_BIST_CABLE_STATUS_D,
+	EFX_PHY_BIST_FAULT_CODE,
+	EFX_PHY_BIST_NVALUES,
+} efx_phy_bist_value_t;
+
+extern	__checkReturn		int
+efx_phy_bist_start(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type);
+
+extern	__checkReturn		int
+efx_phy_bist_poll(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type,
+	__out			efx_phy_bist_result_t *resultp,
+	__out_opt		uint32_t *value_maskp,
+	__out_ecount_opt(count)	unsigned long *valuesp,
+	__in			size_t count);
+
+extern				void
+efx_phy_bist_stop(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type);
+
+#endif	/* EFSYS_OPT_PHY_BIST */
+
+#define	EFX_FEATURE_IPV6		0x00000001
+#define	EFX_FEATURE_LFSR_HASH_INSERT	0x00000002
+#define	EFX_FEATURE_LINK_EVENTS		0x00000004
+#define	EFX_FEATURE_PERIODIC_MAC_STATS	0x00000008
+#define	EFX_FEATURE_WOL			0x00000010
+#define	EFX_FEATURE_MCDI		0x00000020
+#define	EFX_FEATURE_LOOKAHEAD_SPLIT	0x00000040
+#define	EFX_FEATURE_MAC_HEADER_FILTERS	0x00000080
+#define	EFX_FEATURE_TURBO		0x00000100
+
+typedef struct efx_nic_cfg_s {
+	uint32_t		enc_board_type;
+	uint32_t		enc_phy_type;
+#if EFSYS_OPT_NAMES
+	char			enc_phy_name[21];
+#endif
+	char			enc_phy_revision[21];
+	efx_mon_type_t		enc_mon_type;
+#if EFSYS_OPT_MON_STATS
+	uint32_t		enc_mon_stat_mask;
+#endif
+	unsigned int		enc_features;
+	uint8_t			enc_mac_addr[6];
+	uint8_t			enc_port;
+	uint32_t		enc_evq_limit;
+	uint32_t		enc_txq_limit;
+	uint32_t		enc_rxq_limit;
+	uint32_t		enc_buftbl_limit;
+	uint32_t		enc_evq_timer_quantum_ns;
+	uint32_t		enc_evq_timer_max_us;
+	uint32_t		enc_clk_mult;
+#if EFSYS_OPT_LOOPBACK
+	uint32_t		enc_loopback_types[EFX_LINK_NMODES];
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_PHY_FLAGS
+	uint32_t		enc_phy_flags_mask;
+#endif	/* EFSYS_OPT_PHY_FLAGS */
+#if EFSYS_OPT_PHY_LED_CONTROL
+	uint32_t		enc_led_mask;
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+#if EFSYS_OPT_PHY_STATS
+	uint64_t		enc_phy_stat_mask;
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+	unsigned int		enc_phy_nprops;
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_SIENA
+	uint8_t			enc_siena_channel;
+#if EFSYS_OPT_PHY_STATS
+	uint32_t		enc_siena_phy_stat_mask;
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_MON_STATS
+	uint32_t		enc_siena_mon_stat_mask;
+#endif	/* EFSYS_OPT_MON_STATS */
+#endif	/* EFSYS_OPT_SIENA */
+#if EFSYS_OPT_PHY_BIST
+	uint32_t		enc_bist_mask;
+#endif	/* EFSYS_OPT_PHY_BIST */
+} efx_nic_cfg_t;
+
+extern			const efx_nic_cfg_t *
+efx_nic_cfg_get(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_VPD
+
+typedef enum efx_vpd_tag_e {
+	EFX_VPD_ID = 0x02,
+	EFX_VPD_END = 0x0f,
+	EFX_VPD_RO = 0x10,
+	EFX_VPD_RW = 0x11,
+} efx_vpd_tag_t;
+
+typedef uint16_t efx_vpd_keyword_t;
+
+typedef struct efx_vpd_value_s {
+	efx_vpd_tag_t		evv_tag;
+	efx_vpd_keyword_t	evv_keyword;
+	uint8_t			evv_length;
+	uint8_t			evv_value[0x100];
+} efx_vpd_value_t;
+
+
+#define	EFX_VPD_KEYWORD(x, y) ((x) | ((y) << 8))
+
+extern	__checkReturn		int
+efx_vpd_init(
+	__in			efx_nic_t *enp);
+
+extern	__checkReturn		int
+efx_vpd_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep);
+
+extern	__checkReturn		int
+efx_vpd_read(
+	__in			efx_nic_t *enp,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+efx_vpd_verify(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern  __checkReturn		int
+efx_vpd_reinit(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+efx_vpd_get(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__inout			efx_vpd_value_t *evvp);
+
+extern	__checkReturn		int
+efx_vpd_set(
+	__in			efx_nic_t *enp,
+	__inout_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_value_t *evvp);
+
+extern	__checkReturn		int
+efx_vpd_next(
+	__in			efx_nic_t *enp,
+	__inout_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out			efx_vpd_value_t *evvp,
+	__inout			unsigned int *contp);
+
+extern __checkReturn		int
+efx_vpd_write(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern				void
+efx_vpd_fini(
+	__in			efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_VPD */
+
+/* NVRAM */
+
+#if EFSYS_OPT_NVRAM
+
+typedef enum efx_nvram_type_e {
+	EFX_NVRAM_INVALID = 0,
+	EFX_NVRAM_BOOTROM,
+	EFX_NVRAM_BOOTROM_CFG,
+	EFX_NVRAM_MC_FIRMWARE,
+	EFX_NVRAM_MC_GOLDEN,
+	EFX_NVRAM_PHY,
+	EFX_NVRAM_NULLPHY,
+	EFX_NVRAM_FPGA,
+	EFX_NVRAM_NTYPES,
+} efx_nvram_type_t;
+
+extern	__checkReturn		int
+efx_nvram_init(
+	__in			efx_nic_t *enp);
+
+#if EFSYS_OPT_DIAG
+
+extern	__checkReturn		int
+efx_nvram_test(
+	__in			efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+extern	__checkReturn		int
+efx_nvram_size(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *sizep);
+
+extern	__checkReturn		int
+efx_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out_opt		size_t *pref_chunkp);
+
+extern				void
+efx_nvram_rw_finish(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type);
+
+extern	__checkReturn		int
+efx_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4]);
+
+extern	__checkReturn		int
+efx_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+efx_nvram_set_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint16_t version[4]);
+
+extern	 __checkReturn		int
+efx_nvram_erase(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type);
+
+extern	__checkReturn		int
+efx_nvram_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern				void
+efx_nvram_fini(
+	__in			efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_NVRAM */
+
+#if EFSYS_OPT_BOOTCFG
+
+extern				int
+efx_bootcfg_read(
+	__in			efx_nic_t *enp,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern				int
+efx_bootcfg_write(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+#endif	/* EFSYS_OPT_BOOTCFG */
+
+#if EFSYS_OPT_WOL
+
+typedef enum efx_wol_type_e {
+	EFX_WOL_TYPE_INVALID,
+	EFX_WOL_TYPE_MAGIC,
+	EFX_WOL_TYPE_BITMAP,
+	EFX_WOL_TYPE_LINK,
+	EFX_WOL_NTYPES,
+} efx_wol_type_t;
+
+typedef enum efx_lightsout_offload_type_e {
+	EFX_LIGHTSOUT_OFFLOAD_TYPE_INVALID,
+	EFX_LIGHTSOUT_OFFLOAD_TYPE_ARP,
+	EFX_LIGHTSOUT_OFFLOAD_TYPE_NS,
+} efx_lightsout_offload_type_t;
+
+#define	EFX_WOL_BITMAP_MASK_SIZE    (48)
+#define	EFX_WOL_BITMAP_VALUE_SIZE   (128)
+
+typedef union efx_wol_param_u {
+	struct {
+		uint8_t mac_addr[6];
+	} ewp_magic;
+	struct {
+		uint8_t mask[EFX_WOL_BITMAP_MASK_SIZE];   /* 1 bit per byte */
+		uint8_t value[EFX_WOL_BITMAP_VALUE_SIZE]; /* value to match */
+		uint8_t value_len;
+	} ewp_bitmap;
+} efx_wol_param_t;
+
+typedef union efx_lightsout_offload_param_u {
+	struct {
+		uint8_t mac_addr[6];
+		uint32_t ip;
+	} elop_arp;
+	struct {
+		uint8_t mac_addr[6];
+		uint32_t solicited_node[4];
+		uint32_t ip[4];
+	} elop_ns;
+} efx_lightsout_offload_param_t;
+
+extern	__checkReturn	int
+efx_wol_init(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+efx_wol_filter_clear(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+efx_wol_filter_add(
+	__in		efx_nic_t *enp,
+	__in		efx_wol_type_t type,
+	__in		efx_wol_param_t *paramp,
+	__out		uint32_t *filter_idp);
+
+extern	__checkReturn	int
+efx_wol_filter_remove(
+	__in		efx_nic_t *enp,
+	__in		uint32_t filter_id);
+
+extern	__checkReturn	int
+efx_lightsout_offload_add(
+	__in		efx_nic_t *enp,
+	__in		efx_lightsout_offload_type_t type,
+	__in		efx_lightsout_offload_param_t *paramp,
+	__out		uint32_t *filter_idp);
+
+extern	__checkReturn	int
+efx_lightsout_offload_remove(
+	__in		efx_nic_t *enp,
+	__in		efx_lightsout_offload_type_t type,
+	__in		uint32_t filter_id);
+
+extern			void
+efx_wol_fini(
+	__in		efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_WOL */
+
+#if EFSYS_OPT_DIAG
+
+typedef enum efx_pattern_type_t {
+	EFX_PATTERN_BYTE_INCREMENT = 0,
+	EFX_PATTERN_ALL_THE_SAME,
+	EFX_PATTERN_BIT_ALTERNATE,
+	EFX_PATTERN_BYTE_ALTERNATE,
+	EFX_PATTERN_BYTE_CHANGING,
+	EFX_PATTERN_BIT_SWEEP,
+	EFX_PATTERN_NTYPES
+} efx_pattern_type_t;
+
+typedef 		void
+(*efx_sram_pattern_fn_t)(
+	__in		size_t row,
+	__in		boolean_t negate,
+	__out		efx_qword_t *eqp);
+
+extern	__checkReturn	int
+efx_sram_test(
+	__in		efx_nic_t *enp,
+	__in		efx_pattern_type_t type);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+extern	__checkReturn	int
+efx_sram_buf_tbl_set(
+	__in		efx_nic_t *enp,
+	__in		uint32_t id,
+	__in		efsys_mem_t *esmp,
+	__in		size_t n);
+
+extern		void
+efx_sram_buf_tbl_clear(
+	__in	efx_nic_t *enp,
+	__in	uint32_t id,
+	__in	size_t n);
+
+#define	EFX_BUF_TBL_SIZE	0x20000
+
+#define	EFX_BUF_SIZE		4096
+
+/* EV */
+
+typedef struct efx_evq_s	efx_evq_t;
+
+#if EFSYS_OPT_QSTATS
+
+/* START MKCONFIG GENERATED EfxHeaderEventQueueBlock d5614a5d669c8ca3 */
+typedef enum efx_ev_qstat_e {
+	EV_ALL,
+	EV_RX,
+	EV_RX_OK,
+	EV_RX_RECOVERY,
+	EV_RX_FRM_TRUNC,
+	EV_RX_TOBE_DISC,
+	EV_RX_PAUSE_FRM_ERR,
+	EV_RX_BUF_OWNER_ID_ERR,
+	EV_RX_IPV4_HDR_CHKSUM_ERR,
+	EV_RX_TCP_UDP_CHKSUM_ERR,
+	EV_RX_ETH_CRC_ERR,
+	EV_RX_IP_FRAG_ERR,
+	EV_RX_MCAST_PKT,
+	EV_RX_MCAST_HASH_MATCH,
+	EV_RX_TCP_IPV4,
+	EV_RX_TCP_IPV6,
+	EV_RX_UDP_IPV4,
+	EV_RX_UDP_IPV6,
+	EV_RX_OTHER_IPV4,
+	EV_RX_OTHER_IPV6,
+	EV_RX_NON_IP,
+	EV_RX_OVERRUN,
+	EV_TX,
+	EV_TX_WQ_FF_FULL,
+	EV_TX_PKT_ERR,
+	EV_TX_PKT_TOO_BIG,
+	EV_TX_UNEXPECTED,
+	EV_GLOBAL,
+	EV_GLOBAL_PHY,
+	EV_GLOBAL_MNT,
+	EV_GLOBAL_RX_RECOVERY,
+	EV_DRIVER,
+	EV_DRIVER_SRM_UPD_DONE,
+	EV_DRIVER_TX_DESCQ_FLS_DONE,
+	EV_DRIVER_RX_DESCQ_FLS_DONE,
+	EV_DRIVER_RX_DESCQ_FLS_FAILED,
+	EV_DRIVER_RX_DSC_ERROR,
+	EV_DRIVER_TX_DSC_ERROR,
+	EV_DRV_GEN,
+	EV_MCDI_RESPONSE,
+	EV_NQSTATS
+} efx_ev_qstat_t;
+
+/* END MKCONFIG GENERATED EfxHeaderEventQueueBlock */
+
+#endif	/* EFSYS_OPT_QSTATS */
+
+extern	__checkReturn	int
+efx_ev_init(
+	__in		efx_nic_t *enp);
+
+extern		void
+efx_ev_fini(
+	__in		efx_nic_t *enp);
+
+#define	EFX_MASK(_max, _min)	(-((_max) << 1) ^ -(_min))
+
+#define	EFX_EVQ_MAXNEVS		32768
+#define	EFX_EVQ_MINNEVS		512
+
+#define	EFX_EVQ_NEVS_MASK	EFX_MASK(EFX_EVQ_MAXNEVS, EFX_EVQ_MINNEVS)
+
+#define	EFX_EVQ_SIZE(_nevs)	((_nevs) * sizeof (efx_qword_t))
+#define	EFX_EVQ_NBUFS(_nevs)	(EFX_EVQ_SIZE(_nevs) / EFX_BUF_SIZE)
+
+extern	__checkReturn	int
+efx_ev_qcreate(
+	__in		efx_nic_t *enp,
+	__in		unsigned int index,
+	__in		efsys_mem_t *esmp,
+	__in		size_t n,
+	__in		uint32_t id,
+	__deref_out	efx_evq_t **eepp);
+
+extern		void
+efx_ev_qpost(
+	__in		efx_evq_t *eep,
+	__in		uint16_t data);
+
+typedef __checkReturn	boolean_t
+(*efx_initialized_ev_t)(
+	__in_opt	void *arg);
+
+#define	EFX_PKT_UNICAST		0x0004
+#define	EFX_PKT_START		0x0008
+
+#define	EFX_PKT_VLAN_TAGGED	0x0010
+#define	EFX_CKSUM_TCPUDP	0x0020
+#define	EFX_CKSUM_IPV4		0x0040
+#define	EFX_PKT_CONT		0x0080
+
+#define	EFX_CHECK_VLAN		0x0100
+#define	EFX_PKT_TCP		0x0200
+#define	EFX_PKT_UDP		0x0400
+#define	EFX_PKT_IPV4		0x0800
+
+#define	EFX_PKT_IPV6		0x1000
+#define	EFX_ADDR_MISMATCH	0x4000
+#define	EFX_DISCARD		0x8000
+
+#define	EFX_EV_RX_NLABELS	32
+#define	EFX_EV_TX_NLABELS	32
+
+typedef	__checkReturn	boolean_t
+(*efx_rx_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t label,
+	__in		uint32_t id,
+	__in		uint32_t size,
+	__in		uint16_t flags);
+
+typedef	__checkReturn	boolean_t
+(*efx_tx_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t label,
+	__in		uint32_t id);
+
+#define	EFX_EXCEPTION_RX_RECOVERY	0x00000001
+#define	EFX_EXCEPTION_RX_DSC_ERROR	0x00000002
+#define	EFX_EXCEPTION_TX_DSC_ERROR	0x00000003
+#define	EFX_EXCEPTION_UNKNOWN_SENSOREVT	0x00000004
+#define	EFX_EXCEPTION_FWALERT_SRAM	0x00000005
+#define	EFX_EXCEPTION_UNKNOWN_FWALERT	0x00000006
+
+typedef	__checkReturn	boolean_t
+(*efx_exception_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t label,
+	__in		uint32_t data);
+
+typedef	__checkReturn	boolean_t
+(*efx_rxq_flush_done_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t label);
+
+typedef	__checkReturn	boolean_t
+(*efx_rxq_flush_failed_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t label);
+
+typedef	__checkReturn	boolean_t
+(*efx_txq_flush_done_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t label);
+
+typedef	__checkReturn	boolean_t
+(*efx_software_ev_t)(
+	__in_opt	void *arg,
+	__in		uint16_t magic);
+
+typedef	__checkReturn	boolean_t
+(*efx_sram_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t code);
+
+#define	EFX_SRAM_CLEAR		0
+#define	EFX_SRAM_UPDATE		1
+#define	EFX_SRAM_ILLEGAL_CLEAR	2
+
+typedef	__checkReturn	boolean_t
+(*efx_wake_up_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t label);
+
+typedef	__checkReturn	boolean_t
+(*efx_timer_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t label);
+
+typedef __checkReturn	boolean_t
+(*efx_link_change_ev_t)(
+	__in_opt	void *arg,
+	__in		efx_link_mode_t	link_mode);
+
+#if EFSYS_OPT_MON_STATS
+
+typedef __checkReturn	boolean_t
+(*efx_monitor_ev_t)(
+	__in_opt	void *arg,
+	__in		efx_mon_stat_t id,
+	__in		efx_mon_stat_value_t value);
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+#if EFSYS_OPT_MAC_STATS
+
+typedef __checkReturn	boolean_t
+(*efx_mac_stats_ev_t)(
+	__in_opt	void *arg,
+	__in		uint32_t generation
+	);
+
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+typedef struct efx_ev_callbacks_s {
+	efx_initialized_ev_t		eec_initialized;
+	efx_rx_ev_t			eec_rx;
+	efx_tx_ev_t			eec_tx;
+	efx_exception_ev_t		eec_exception;
+	efx_rxq_flush_done_ev_t		eec_rxq_flush_done;
+	efx_rxq_flush_failed_ev_t	eec_rxq_flush_failed;
+	efx_txq_flush_done_ev_t		eec_txq_flush_done;
+	efx_software_ev_t		eec_software;
+	efx_sram_ev_t			eec_sram;
+	efx_wake_up_ev_t		eec_wake_up;
+	efx_timer_ev_t			eec_timer;
+	efx_link_change_ev_t		eec_link_change;
+#if EFSYS_OPT_MON_STATS
+	efx_monitor_ev_t		eec_monitor;
+#endif	/* EFSYS_OPT_MON_STATS */
+#if EFSYS_OPT_MAC_STATS
+	efx_mac_stats_ev_t		eec_mac_stats;
+#endif	/* EFSYS_OPT_MON_STATS */
+} efx_ev_callbacks_t;
+
+extern	__checkReturn	boolean_t
+efx_ev_qpending(
+	__in		efx_evq_t *eep,
+	__in		unsigned int count);
+
+#if EFSYS_OPT_EV_PREFETCH
+
+extern			void
+efx_ev_qprefetch(
+	__in		efx_evq_t *eep,
+	__in		unsigned int count);
+
+#endif	/* EFSYS_OPT_EV_PREFETCH */
+
+extern			void
+efx_ev_qpoll(
+	__in		efx_evq_t *eep,
+	__inout		unsigned int *countp,
+	__in		const efx_ev_callbacks_t *eecp,
+	__in_opt	void *arg);
+
+extern	__checkReturn	int
+efx_ev_qmoderate(
+	__in		efx_evq_t *eep,
+	__in		unsigned int us);
+
+extern	__checkReturn	int
+efx_ev_qprime(
+	__in		efx_evq_t *eep,
+	__in		unsigned int count);
+
+#if EFSYS_OPT_QSTATS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+efx_ev_qstat_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+extern					void
+efx_ev_qstats_update(
+	__in				efx_evq_t *eep,
+	__inout_ecount(EV_NQSTATS)	efsys_stat_t *stat);
+
+#endif	/* EFSYS_OPT_QSTATS */
+
+extern		void
+efx_ev_qdestroy(
+	__in	efx_evq_t *eep);
+
+/* RX */
+
+typedef struct efx_rxq_s	efx_rxq_t;
+
+extern	__checkReturn	int
+efx_rx_init(
+	__in		efx_nic_t *enp);
+
+extern		void
+efx_rx_fini(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_RX_HDR_SPLIT
+	__checkReturn	int
+efx_rx_hdr_split_enable(
+	__in		efx_nic_t *enp,
+	__in		unsigned int hdr_buf_size,
+	__in		unsigned int pld_buf_size);
+
+#endif	/* EFSYS_OPT_RX_HDR_SPLIT */
+
+#if EFSYS_OPT_RX_SCATTER
+	__checkReturn	int
+efx_rx_scatter_enable(
+	__in		efx_nic_t *enp,
+	__in		unsigned int buf_size);
+#endif	/* EFSYS_OPT_RX_SCATTER */
+
+#if EFSYS_OPT_RX_SCALE
+
+typedef enum efx_rx_hash_alg_e {
+	EFX_RX_HASHALG_LFSR = 0,
+	EFX_RX_HASHALG_TOEPLITZ
+} efx_rx_hash_alg_t;
+
+typedef enum efx_rx_hash_type_e {
+	EFX_RX_HASH_IPV4 = 0,
+	EFX_RX_HASH_TCPIPV4,
+	EFX_RX_HASH_IPV6,
+	EFX_RX_HASH_TCPIPV6,
+} efx_rx_hash_type_t;
+
+#define	EFX_RSS_TBL_SIZE	128	/* Rows in RX indirection table */
+#define	EFX_MAXRSS	    	64	/* RX indirection entry range */
+#define	EFX_MAXRSS_LEGACY   	16 	/* See bug16611 and bug17213 */
+
+extern	__checkReturn	int
+efx_rx_scale_mode_set(
+	__in	efx_nic_t *enp,
+	__in	efx_rx_hash_alg_t alg,
+	__in	efx_rx_hash_type_t type,
+	__in	boolean_t insert);
+
+extern	__checkReturn	int
+efx_rx_scale_tbl_set(
+	__in		efx_nic_t *enp,
+	__in_ecount(n)	unsigned int *table,
+	__in		size_t n);
+
+extern	__checkReturn	int
+efx_rx_scale_toeplitz_ipv4_key_set(
+	__in		efx_nic_t *enp,
+	__in_ecount(n)	uint8_t *key,
+	__in		size_t n);
+
+extern	__checkReturn	int
+efx_rx_scale_toeplitz_ipv6_key_set(
+	__in		efx_nic_t *enp,
+	__in_ecount(n)	uint8_t *key,
+	__in		size_t n);
+
+/*
+ * The prefix is a byte array of one of the forms:
+ *
+ *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+ * XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.TT.TT.TT.TT
+ * XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.XX.LL.LL
+ *
+ * where:
+ *
+ * TT.TT.TT.TT is a 32-bit Toeplitz hash
+ * LL.LL is a 16-bit LFSR hash
+ *
+ * Hash values are in network (big-endian) byte order.
+ */
+
+#define	EFX_RX_PREFIX_SIZE	16
+
+#define	EFX_RX_HASH_VALUE(_func, _buffer)				\
+	(((_func) == EFX_RX_HASHALG_LFSR) ?				\
+		((uint16_t)(((_buffer)[14] << 8) | (_buffer)[15])) :	\
+		((uint32_t)(((_buffer)[12] << 24) |			\
+		    ((_buffer)[13] << 16) |				\
+		    ((_buffer)[14] << 8) |				\
+		    (_buffer)[15])))
+
+#define	EFX_RX_HASH_SIZE(_func)						\
+	(((_func) == EFX_RX_HASHALG_LFSR) ?				\
+		sizeof (uint16_t) : 					\
+		sizeof (uint32_t))
+
+#endif	/* EFSYS_OPT_RX_SCALE */
+
+#define	EFX_RXQ_MAXNDESCS		4096
+#define	EFX_RXQ_MINNDESCS		512
+
+#define	EFX_RXQ_NDESCS_MASK		EFX_MASK(EFX_RXQ_MAXNDESCS, EFX_RXQ_MINNDESCS)
+
+#define	EFX_RXQ_SIZE(_ndescs)		((_ndescs) * sizeof (efx_qword_t))
+#define	EFX_RXQ_NBUFS(_ndescs)		(EFX_RXQ_SIZE(_ndescs) / EFX_BUF_SIZE)
+#define	EFX_RXQ_LIMIT(_ndescs)		((_ndescs) - 16)
+#define	EFX_RXQ_DC_NDESCS(_dcsize)	(8 << _dcsize)
+
+typedef enum efx_rxq_type_e {
+	EFX_RXQ_TYPE_DEFAULT,
+	EFX_RXQ_TYPE_SPLIT_HEADER,
+	EFX_RXQ_TYPE_SPLIT_PAYLOAD,
+	EFX_RXQ_TYPE_SCATTER,
+	EFX_RXQ_NTYPES
+} efx_rxq_type_t;
+
+extern	__checkReturn	int
+efx_rx_qcreate(
+	__in		efx_nic_t *enp,
+	__in		unsigned int index,
+	__in		unsigned int label,
+	__in		efx_rxq_type_t type,
+	__in		efsys_mem_t *esmp,
+	__in		size_t n,
+	__in		uint32_t id,
+	__in		efx_evq_t *eep,
+	__deref_out	efx_rxq_t **erpp);
+
+typedef struct efx_buffer_s {
+	efsys_dma_addr_t	eb_addr;
+	size_t			eb_size;
+	boolean_t		eb_eop;
+} efx_buffer_t;
+
+extern			void
+efx_rx_qpost(
+	__in		efx_rxq_t *erp,
+	__in_ecount(n)	efsys_dma_addr_t *addrp,
+	__in		size_t size,
+	__in		unsigned int n,
+	__in		unsigned int completed,
+	__in		unsigned int added);
+
+extern		void
+efx_rx_qpush(
+	__in	efx_rxq_t *erp,
+	__in	unsigned int added);
+
+extern		void
+efx_rx_qflush(
+	__in	efx_rxq_t *erp);
+
+extern		void
+efx_rx_qenable(
+	__in	efx_rxq_t *erp);
+
+extern		void
+efx_rx_qdestroy(
+	__in	efx_rxq_t *erp);
+
+/* TX */
+
+typedef struct efx_txq_s	efx_txq_t;
+
+#if EFSYS_OPT_QSTATS
+
+/* START MKCONFIG GENERATED EfxHeaderTransmitQueueBlock 536c5fa5014944bf */
+typedef enum efx_tx_qstat_e {
+	TX_POST,
+	TX_UNALIGNED_SPLIT,
+	TX_NQSTATS
+} efx_tx_qstat_t;
+
+/* END MKCONFIG GENERATED EfxHeaderTransmitQueueBlock */
+
+#endif	/* EFSYS_OPT_QSTATS */
+
+extern	__checkReturn	int
+efx_tx_init(
+	__in		efx_nic_t *enp);
+
+extern		void
+efx_tx_fini(
+	__in	efx_nic_t *enp);
+
+#define	EFX_TXQ_MAXNDESCS		4096
+#define	EFX_TXQ_MINNDESCS		512
+
+#define	EFX_TXQ_NDESCS_MASK		EFX_MASK(EFX_TXQ_MAXNDESCS, EFX_TXQ_MINNDESCS)
+
+#define	EFX_TXQ_SIZE(_ndescs)		((_ndescs) * sizeof (efx_qword_t))
+#define	EFX_TXQ_NBUFS(_ndescs)		(EFX_TXQ_SIZE(_ndescs) / EFX_BUF_SIZE)
+#define	EFX_TXQ_LIMIT(_ndescs)		((_ndescs) - 16)
+#define	EFX_TXQ_DC_NDESCS(_dcsize)	(8 << _dcsize)
+
+extern	__checkReturn	int
+efx_tx_qcreate(
+	__in		efx_nic_t *enp,
+	__in		unsigned int index,
+	__in		unsigned int label,
+	__in		efsys_mem_t *esmp,
+	__in		size_t n,
+	__in		uint32_t id,
+	__in		uint16_t flags,
+	__in		efx_evq_t *eep,
+	__deref_out	efx_txq_t **etpp);
+
+extern	__checkReturn	int
+efx_tx_qpost(
+	__in		efx_txq_t *etp,
+	__in_ecount(n)	efx_buffer_t *eb,
+	__in		unsigned int n,
+	__in		unsigned int completed,
+	__inout		unsigned int *addedp);
+
+extern	__checkReturn	int
+efx_tx_qpace(
+	__in		efx_txq_t *etp,
+	__in		unsigned int ns);
+
+extern		void
+efx_tx_qpush(
+	__in	efx_txq_t *etp,
+	__in	unsigned int added);
+
+extern		void
+efx_tx_qflush(
+	__in	efx_txq_t *etp);
+
+extern		void
+efx_tx_qenable(
+	__in	efx_txq_t *etp);
+
+#if EFSYS_OPT_QSTATS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+efx_tx_qstat_name(
+	__in	efx_nic_t *etp,
+	__in	unsigned int id);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+extern					void
+efx_tx_qstats_update(
+	__in				efx_txq_t *etp,
+	__inout_ecount(TX_NQSTATS)	efsys_stat_t *stat);
+
+#endif	/* EFSYS_OPT_QSTATS */
+
+extern		void
+efx_tx_qdestroy(
+	__in	efx_txq_t *etp);
+
+
+/* FILTER */
+
+#if EFSYS_OPT_FILTER
+
+typedef enum efx_filter_flag_e {
+	EFX_FILTER_FLAG_RX_RSS = 0x01,		/* use RSS to spread across
+						 * multiple queues */
+	EFX_FILTER_FLAG_RX_SCATTER = 0x02,	/* enable RX scatter */
+	EFX_FILTER_FLAG_RX_OVERRIDE_IP = 0x04,	/* MAC filter overrides
+						 * any matching IP filter */
+} efx_filter_flag_t;
+
+typedef struct efx_filter_spec_s {
+	uint8_t		efs_type;
+	uint8_t		efs_flags;
+	uint16_t	efs_dmaq_id;
+	uint32_t	efs_dword[3];
+} efx_filter_spec_t;
+
+extern	__checkReturn	int
+efx_filter_init(
+	__in		efx_nic_t *enp);
+
+extern			void
+efx_filter_fini(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+efx_rx_filter_insert(
+	__in		efx_rxq_t *erp,
+	__inout		efx_filter_spec_t *spec);
+
+extern	__checkReturn	int
+efx_rx_filter_remove(
+	__in		efx_rxq_t *erp,
+	__inout		efx_filter_spec_t *spec);
+
+			void
+efx_filter_restore(
+	__in		efx_nic_t *enp);
+
+extern			void
+efx_filter_spec_rx_ipv4_tcp_full(
+	__inout		efx_filter_spec_t *spec,
+	__in		unsigned int flags,
+	__in		uint32_t src_ip,
+	__in		uint16_t src_tcp,
+	__in		uint32_t dest_ip,
+	__in		uint16_t dest_tcp);
+
+extern			void
+efx_filter_spec_rx_ipv4_tcp_wild(
+	__inout		efx_filter_spec_t *spec,
+	__in		unsigned int flags,
+	__in		uint32_t dest_ip,
+	__in		uint16_t dest_tcp);
+
+extern			void
+efx_filter_spec_rx_ipv4_udp_full(
+	__inout		efx_filter_spec_t *spec,
+	__in		unsigned int flags,
+	__in		uint32_t src_ip,
+	__in		uint16_t src_udp,
+	__in		uint32_t dest_ip,
+	__in		uint16_t dest_udp);
+
+extern			void
+efx_filter_spec_rx_ipv4_udp_wild(
+	__inout		efx_filter_spec_t *spec,
+	__in		unsigned int flags,
+	__in		uint32_t dest_ip,
+	__in		uint16_t dest_udp);
+
+extern			void
+efx_filter_spec_rx_mac_full(
+	__inout		efx_filter_spec_t *spec,
+	__in		unsigned int flags,
+	__in		uint16_t vlan_id,
+	__in		uint8_t *dest_mac);
+
+extern			void
+efx_filter_spec_rx_mac_wild(
+	__inout		efx_filter_spec_t *spec,
+	__in		unsigned int flags,
+	__in		uint8_t *dest_mac);
+
+
+extern	__checkReturn	int
+efx_tx_filter_insert(
+	__in		efx_txq_t *etp,
+	__inout		efx_filter_spec_t *spec);
+
+extern	__checkReturn	int
+efx_tx_filter_remove(
+	__in		efx_txq_t *etp,
+	__inout		efx_filter_spec_t *spec);
+
+extern			void
+efx_filter_spec_tx_ipv4_tcp_full(
+	__inout		efx_filter_spec_t *spec,
+	__in		uint32_t src_ip,
+	__in		uint16_t src_tcp,
+	__in		uint32_t dest_ip,
+	__in		uint16_t dest_tcp);
+
+extern			void
+efx_filter_spec_tx_ipv4_tcp_wild(
+	__inout		efx_filter_spec_t *spec,
+	__in		uint32_t src_ip,
+	__in		uint16_t src_tcp);
+
+extern			void
+efx_filter_spec_tx_ipv4_udp_full(
+	__inout		efx_filter_spec_t *spec,
+	__in		uint32_t src_ip,
+	__in		uint16_t src_udp,
+	__in		uint32_t dest_ip,
+	__in		uint16_t dest_udp);
+
+extern			void
+efx_filter_spec_tx_ipv4_udp_wild(
+	__inout		efx_filter_spec_t *spec,
+	__in		uint32_t src_ip,
+	__in		uint16_t src_udp);
+
+extern			void
+efx_filter_spec_tx_mac_full(
+	__inout		efx_filter_spec_t *spec,
+	__in		uint16_t vlan_id,
+	__in		uint8_t *src_mac);
+
+extern			void
+efx_filter_spec_tx_mac_wild(
+	__inout		efx_filter_spec_t *spec,
+	__in		uint8_t *src_mac);
+
+#endif	/* EFSYS_OPT_FILTER */
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_EFX_H */
--- /dev/null	2013-08-22 18:57:27.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_bootcfg.c	2013-08-22 18:57:27.701403733 -0400
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_BOOTCFG
+
+/*
+ * Maximum size of BOOTCFG block across all nics as understood by SFCgPXE.
+ * A multiple of 0x100 so trailing 0xff characters don't contrinbute to the
+ * checksum.
+ */
+#define	BOOTCFG_MAX_SIZE 0x1000
+
+#define	DHCP_END (uint8_t)0xff
+#define	DHCP_PAD (uint8_t)0
+
+static	__checkReturn		uint8_t
+efx_bootcfg_csum(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	_NOTE(ARGUNUSED(enp))
+
+	unsigned int pos;
+	uint8_t checksum = 0;
+
+	for (pos = 0; pos < size; pos++)
+		checksum += data[pos];
+	return (checksum);
+}
+
+static	__checkReturn		int
+efx_bootcfg_verify(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out			size_t *usedp)
+{
+	size_t offset = 0;
+	size_t used = 0;
+	int rc;
+
+	/* Start parsing tags immediatly after the checksum */
+	for (offset = 1; offset < size; ) {
+		uint8_t tag;
+		uint8_t length;
+
+		/* Consume tag */
+		tag = data[offset];
+		if (tag == DHCP_END) {
+			offset++;
+			used = offset;
+			break;
+		}
+		if (tag == DHCP_PAD) {
+			offset++;
+			continue;
+		}
+
+		/* Consume length */
+		if (offset + 1 >= size) {
+			rc = ENOSPC;
+			goto fail1;
+		}
+		length = data[offset + 1];
+
+		/* Consume *length */
+		if (offset + 1 + length >= size) {
+			rc = ENOSPC;
+			goto fail2;
+		}
+
+		offset += 2 + length;
+		used = offset;
+	}
+
+	/* Checksum the entire sector, including bytes after any DHCP_END */
+	if (efx_bootcfg_csum(enp, data, size) != 0) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	if (usedp != NULL)
+		*usedp = used;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+				int
+efx_bootcfg_read(
+	__in			efx_nic_t *enp,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	uint8_t *payload = NULL;
+	size_t used_bytes;
+	size_t sector_length;
+	int rc;
+
+	rc = efx_nvram_size(enp, EFX_NVRAM_BOOTROM_CFG, &sector_length);
+	if (rc != 0)
+		goto fail1;
+
+	/*
+	 * We need to read the entire BOOTCFG area to ensure we read all the
+	 * tags, because legacy bootcfg sectors are not guaranteed to end with
+	 * a DHCP_END character. If the user hasn't supplied a sufficiently
+	 * large buffer then use our own buffer.
+	 */
+	if (sector_length > BOOTCFG_MAX_SIZE)
+		sector_length = BOOTCFG_MAX_SIZE;
+	if (sector_length > size) {
+		EFSYS_KMEM_ALLOC(enp->en_esip, sector_length, payload);
+		if (payload == NULL) {
+			rc = ENOMEM;
+			goto fail2;
+		}
+	} else
+		payload = (uint8_t *)data;
+
+	if ((rc = efx_nvram_rw_start(enp, EFX_NVRAM_BOOTROM_CFG, NULL)) != 0)
+		goto fail3;
+
+	rc = efx_nvram_read_chunk(enp, EFX_NVRAM_BOOTROM_CFG, 0,
+				    (caddr_t)payload, sector_length);
+
+	efx_nvram_rw_finish(enp, EFX_NVRAM_BOOTROM_CFG);
+
+	if (rc != 0)
+		goto fail4;
+
+	/* Verify that the area is correctly formatted and checksummed */
+	rc = efx_bootcfg_verify(enp, (caddr_t)payload, sector_length,
+				    &used_bytes);
+	if (rc != 0 || used_bytes == 0) {
+		payload[0] = (uint8_t)~DHCP_END;
+		payload[1] = DHCP_END;
+		used_bytes = 2;
+	}
+
+	EFSYS_ASSERT(used_bytes >= 2);	/* checksum and DHCP_END */
+	EFSYS_ASSERT(used_bytes <= sector_length);
+
+	/*
+	 * Legacy bootcfg sectors don't terminate with a DHCP_END character.
+	 * Modify the returned payload so it does. BOOTCFG_MAX_SIZE is by
+	 * definition large enough for any valid (per-port) bootcfg sector,
+	 * so reinitialise the sector if there isn't room for the character.
+	 */
+	if (payload[used_bytes - 1] != DHCP_END) {
+		if (used_bytes + 1 > sector_length) {
+			payload[0] = 0;
+			used_bytes = 1;
+		}
+
+		payload[used_bytes] = DHCP_END;
+		++used_bytes;
+	}
+
+	/*
+	 * Verify that the user supplied buffer is large enough for the
+	 * entire used bootcfg area, then copy into the user supplied buffer.
+	 */
+	if (used_bytes > size) {
+		rc = ENOSPC;
+		goto fail5;
+	}
+	if (sector_length > size) {
+		memcpy(data, payload, used_bytes);
+		EFSYS_KMEM_FREE(enp->en_esip, sector_length, payload);
+	}
+
+	/* Zero out the unused portion of the user buffer */
+	if (used_bytes < size)
+		(void) memset(data + used_bytes, 0, size - used_bytes);
+
+	/*
+	 * The checksum includes trailing data after any DHCP_END character,
+	 * which we've just modified (by truncation or appending DHCP_END).
+	 */
+	data[0] -= efx_bootcfg_csum(enp, data, size);
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+
+	if (sector_length > size)
+		EFSYS_KMEM_FREE(enp->en_esip, sector_length, payload);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+				int
+efx_bootcfg_write(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	uint8_t *chunk;
+	uint8_t checksum;
+	size_t sector_length;
+	size_t chunk_length;
+	size_t used_bytes;
+	size_t offset;
+	size_t remaining;
+	int rc;
+
+	rc = efx_nvram_size(enp, EFX_NVRAM_BOOTROM_CFG, &sector_length);
+	if (rc != 0)
+		goto fail1;
+
+	if (sector_length > BOOTCFG_MAX_SIZE)
+		sector_length = BOOTCFG_MAX_SIZE;
+
+	if ((rc = efx_bootcfg_verify(enp, data, size, &used_bytes)) != 0)
+		goto fail2;
+
+	/* The caller *must* terminate their block with a DHCP_END character */
+	EFSYS_ASSERT(used_bytes >= 2);		/* checksum and DHCP_END */
+	if ((uint8_t)data[used_bytes - 1] != DHCP_END) {
+		rc = ENOENT;
+		goto fail3;
+	}
+
+	/* Check that the hardware has support for this much data */
+	if (used_bytes > MIN(sector_length, BOOTCFG_MAX_SIZE)) {
+		rc = ENOSPC;
+		goto fail4;
+	}
+
+	rc = efx_nvram_rw_start(enp, EFX_NVRAM_BOOTROM_CFG, &chunk_length);
+	if (rc != 0)
+		goto fail5;
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, chunk_length, chunk);
+	if (chunk == NULL) {
+		rc = ENOMEM;
+		goto fail6;
+	}
+
+	if ((rc = efx_nvram_erase(enp, EFX_NVRAM_BOOTROM_CFG)) != 0)
+		goto fail7;
+
+	/*
+	 * Write the entire sector_length bytes of data in chunks. Zero out
+	 * all data following the DHCP_END, and adjust the checksum
+	 */
+	checksum = efx_bootcfg_csum(enp, data, used_bytes);
+	for (offset = 0; offset < sector_length; offset += remaining) {
+		remaining = MIN(chunk_length, sector_length - offset);
+
+		/* Fill chunk */
+		(void) memset(chunk, 0x0, chunk_length);
+		if (offset < used_bytes)
+			memcpy(chunk, data + offset,
+			    MIN(remaining, used_bytes - offset));
+
+		/* Adjust checksum */
+		if (offset == 0)
+			chunk[0] -= checksum;
+
+		if ((rc = efx_nvram_write_chunk(enp, EFX_NVRAM_BOOTROM_CFG,
+			    offset, (caddr_t)chunk, remaining)) != 0)
+			goto fail8;
+	}
+
+	efx_nvram_rw_finish(enp, EFX_NVRAM_BOOTROM_CFG);
+
+	EFSYS_KMEM_FREE(enp->en_esip, chunk_length, chunk);
+
+	return (0);
+
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+
+	EFSYS_KMEM_FREE(enp->en_esip, chunk_length, chunk);
+fail6:
+	EFSYS_PROBE(fail6);
+
+	efx_nvram_rw_finish(enp, EFX_NVRAM_BOOTROM_CFG);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_BOOTCFG */
--- /dev/null	2013-08-22 18:57:27.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_ev.c	2013-08-22 18:57:27.787132681 -0400
@@ -0,0 +1,1120 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_QSTATS
+#define	EFX_EV_QSTAT_INCR(_eep, _stat)					\
+	do {								\
+		(_eep)->ee_stat[_stat]++;				\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+#else
+#define	EFX_EV_QSTAT_INCR(_eep, _stat)
+#endif
+
+	__checkReturn	int
+efx_ev_init(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+
+	if (enp->en_mod_flags & EFX_MOD_EV) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	EFSYS_ASSERT3U(enp->en_ev_qcount, ==, 0);
+
+	/*
+	 * Program the event queue for receive and transmit queue
+	 * flush events.
+	 */
+	EFX_BAR_READO(enp, FR_AZ_DP_CTRL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_FLS_EVQ_ID, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_DP_CTRL_REG, &oword);
+
+	enp->en_mod_flags |= EFX_MOD_EV;
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static  __checkReturn   boolean_t
+efx_ev_rx_not_ok(
+	__in		efx_evq_t *eep,
+	__in		efx_qword_t *eqp,
+	__in		uint32_t label,
+	__in		uint32_t id,
+	__inout		uint16_t *flagsp)
+{
+	boolean_t ignore = B_FALSE;
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_TOBE_DISC) != 0) {
+		EFX_EV_QSTAT_INCR(eep, EV_RX_TOBE_DISC);
+		EFSYS_PROBE(tobe_disc);
+		/*
+		 * Assume this is a unicast address mismatch, unless below
+		 * we find either FSF_AZ_RX_EV_ETH_CRC_ERR or
+		 * EV_RX_PAUSE_FRM_ERR is set.
+		 */
+		(*flagsp) |= EFX_ADDR_MISMATCH;
+	}
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_FRM_TRUNC) != 0) {
+		EFSYS_PROBE2(frm_trunc, uint32_t, label, uint32_t, id);
+		EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC);
+		(*flagsp) |= EFX_DISCARD;
+
+#if (EFSYS_OPT_RX_HDR_SPLIT || EFSYS_OPT_RX_SCATTER)
+		/*
+		 * Lookout for payload queue ran dry errors and ignore them.
+		 *
+		 * Sadly for the header/data split cases, the descriptor
+		 * pointer in this event refers to the header queue and
+		 * therefore cannot be easily detected as duplicate.
+		 * So we drop these and rely on the receive processing seeing
+		 * a subsequent packet with FSF_AZ_RX_EV_SOP set to discard
+		 * the partially received packet.
+		 */
+		if ((EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) == 0) &&
+		    (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) == 0) &&
+		    (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BYTE_CNT) == 0))
+			ignore = B_TRUE;
+#endif	/* EFSYS_OPT_RX_HDR_SPLIT || EFSYS_OPT_RX_SCATTER */
+	}
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_ETH_CRC_ERR) != 0) {
+		EFX_EV_QSTAT_INCR(eep, EV_RX_ETH_CRC_ERR);
+		EFSYS_PROBE(crc_err);
+		(*flagsp) &= ~EFX_ADDR_MISMATCH;
+		(*flagsp) |= EFX_DISCARD;
+	}
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PAUSE_FRM_ERR) != 0) {
+		EFX_EV_QSTAT_INCR(eep, EV_RX_PAUSE_FRM_ERR);
+		EFSYS_PROBE(pause_frm_err);
+		(*flagsp) &= ~EFX_ADDR_MISMATCH;
+		(*flagsp) |= EFX_DISCARD;
+	}
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BUF_OWNER_ID_ERR) != 0) {
+		EFX_EV_QSTAT_INCR(eep, EV_RX_BUF_OWNER_ID_ERR);
+		EFSYS_PROBE(owner_id_err);
+		(*flagsp) |= EFX_DISCARD;
+	}
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR) != 0) {
+		EFX_EV_QSTAT_INCR(eep, EV_RX_IPV4_HDR_CHKSUM_ERR);
+		EFSYS_PROBE(ipv4_err);
+		(*flagsp) &= ~EFX_CKSUM_IPV4;
+	}
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR) != 0) {
+		EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_UDP_CHKSUM_ERR);
+		EFSYS_PROBE(udp_chk_err);
+		(*flagsp) &= ~EFX_CKSUM_TCPUDP;
+	}
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_IP_FRAG_ERR) != 0) {
+		EFX_EV_QSTAT_INCR(eep, EV_RX_IP_FRAG_ERR);
+
+		/*
+		 * If IP is fragmented FSF_AZ_RX_EV_IP_FRAG_ERR is set. This
+		 * causes FSF_AZ_RX_EV_PKT_OK to be clear. This is not an error
+		 * condition.
+		 */
+		(*flagsp) &= ~(EFX_PKT_TCP | EFX_PKT_UDP | EFX_CKSUM_TCPUDP);
+	}
+
+	return (ignore);
+}
+
+static	__checkReturn	boolean_t
+efx_ev_rx(
+	__in		efx_evq_t *eep,
+	__in		efx_qword_t *eqp,
+	__in		const efx_ev_callbacks_t *eecp,
+	__in_opt	void *arg)
+{
+	efx_nic_t *enp = eep->ee_enp;
+	uint32_t id;
+	uint32_t size;
+	uint32_t label;
+	boolean_t ok;
+#if (EFSYS_OPT_RX_HDR_SPLIT || EFSYS_OPT_RX_SCATTER)
+	boolean_t sop;
+	boolean_t jumbo_cont;
+#endif	/* EFSYS_OPT_RX_HDR_SPLIT || EFSYS_OPT_RX_SCATTER */
+	uint32_t hdr_type;
+	boolean_t is_v6;
+	uint16_t flags;
+	boolean_t ignore;
+	boolean_t should_abort;
+
+	EFX_EV_QSTAT_INCR(eep, EV_RX);
+
+	/* Basic packet information */
+	id = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_DESC_PTR);
+	size = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BYTE_CNT);
+	label = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_Q_LABEL);
+	ok = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PKT_OK) != 0);
+
+#if (EFSYS_OPT_RX_HDR_SPLIT || EFSYS_OPT_RX_SCATTER)
+	sop = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) != 0);
+	jumbo_cont = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) != 0);
+#endif	/* EFSYS_OPT_RX_HDR_SPLIT || EFSYS_OPT_RX_SCATTER */
+
+	hdr_type = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_HDR_TYPE);
+
+	is_v6 = (enp->en_family != EFX_FAMILY_FALCON &&
+		    EFX_QWORD_FIELD(*eqp, FSF_CZ_RX_EV_IPV6_PKT) != 0);
+
+	/*
+	 * If packet is marked as OK and packet type is TCP/IP or
+	 * UDP/IP or other IP, then we can rely on the hardware checksums.
+	 */
+	switch (hdr_type) {
+	case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_TCP:
+		flags = EFX_PKT_TCP | EFX_CKSUM_TCPUDP;
+		if (is_v6) {
+			EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV6);
+			flags |= EFX_PKT_IPV6;
+		} else {
+			EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV4);
+			flags |= EFX_PKT_IPV4 | EFX_CKSUM_IPV4;
+		}
+		break;
+
+	case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_UDP:
+		flags = EFX_PKT_UDP | EFX_CKSUM_TCPUDP;
+		if (is_v6) {
+			EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV6);
+			flags |= EFX_PKT_IPV6;
+		} else {
+			EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV4);
+			flags |= EFX_PKT_IPV4 | EFX_CKSUM_IPV4;
+		}
+		break;
+
+	case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_OTHER:
+		if (is_v6) {
+			EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV6);
+			flags = EFX_PKT_IPV6;
+		} else {
+			EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV4);
+			flags = EFX_PKT_IPV4 | EFX_CKSUM_IPV4;
+		}
+		break;
+
+	case FSE_AZ_RX_EV_HDR_TYPE_OTHER:
+		EFX_EV_QSTAT_INCR(eep, EV_RX_NON_IP);
+		flags = 0;
+		break;
+
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		flags = 0;
+		break;
+	}
+
+#if EFSYS_OPT_RX_SCATTER || EFSYS_OPT_RX_HDR_SPLIT
+	/* Report scatter and header/lookahead split buffer flags */
+	if (sop)
+		flags |= EFX_PKT_START;
+	if (jumbo_cont)
+		flags |= EFX_PKT_CONT;
+#endif	/* EFSYS_OPT_RX_SCATTER || EFSYS_OPT_RX_HDR_SPLIT */
+
+	/* Detect errors included in the FSF_AZ_RX_EV_PKT_OK indication */
+	if (!ok) {
+		ignore = efx_ev_rx_not_ok(eep, eqp, label, id, &flags);
+		if (ignore) {
+			EFSYS_PROBE4(rx_complete, uint32_t, label, uint32_t, id,
+			    uint32_t, size, uint16_t, flags);
+
+			return (B_FALSE);
+		}
+	}
+
+	/* If we're not discarding the packet then it is ok */
+	if (~flags & EFX_DISCARD)
+		EFX_EV_QSTAT_INCR(eep, EV_RX_OK);
+
+	/* Detect multicast packets that didn't match the filter */
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_MCAST_PKT) != 0) {
+		EFX_EV_QSTAT_INCR(eep, EV_RX_MCAST_PKT);
+
+		if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_MCAST_HASH_MATCH) != 0) {
+			EFX_EV_QSTAT_INCR(eep, EV_RX_MCAST_HASH_MATCH);
+		} else {
+			EFSYS_PROBE(mcast_mismatch);
+			flags |= EFX_ADDR_MISMATCH;
+		}
+	} else {
+		flags |= EFX_PKT_UNICAST;
+	}
+
+	/*
+	 * The packet parser in Siena can abort parsing packets under
+	 * certain error conditions, setting the PKT_NOT_PARSED bit
+	 * (which clears PKT_OK). If this is set, then don't trust
+	 * the PKT_TYPE field.
+	 */
+	if (enp->en_family != EFX_FAMILY_FALCON && !ok) {
+		uint32_t parse_err;
+
+		parse_err = EFX_QWORD_FIELD(*eqp, FSF_CZ_RX_EV_PKT_NOT_PARSED);
+		if (parse_err != 0)
+			flags |= EFX_CHECK_VLAN;
+	}
+
+	if (~flags & EFX_CHECK_VLAN) {
+		uint32_t pkt_type;
+
+		pkt_type = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PKT_TYPE);
+		if (pkt_type >= FSE_AZ_RX_EV_PKT_TYPE_VLAN)
+			flags |= EFX_PKT_VLAN_TAGGED;
+	}
+
+	EFSYS_PROBE4(rx_complete, uint32_t, label, uint32_t, id,
+	    uint32_t, size, uint16_t, flags);
+
+	EFSYS_ASSERT(eecp->eec_rx != NULL);
+	should_abort = eecp->eec_rx(arg, label, id, size, flags);
+
+	return (should_abort);
+}
+
+static	__checkReturn	boolean_t
+efx_ev_tx(
+	__in		efx_evq_t *eep,
+	__in		efx_qword_t *eqp,
+	__in		const efx_ev_callbacks_t *eecp,
+	__in_opt	void *arg)
+{
+	uint32_t id;
+	uint32_t label;
+	boolean_t should_abort;
+
+	EFX_EV_QSTAT_INCR(eep, EV_TX);
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_COMP) != 0 &&
+	    EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_ERR) == 0 &&
+	    EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_TOO_BIG) == 0 &&
+	    EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_WQ_FF_FULL) == 0) {
+
+		id = EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_DESC_PTR);
+		label = EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_Q_LABEL);
+
+		EFSYS_PROBE2(tx_complete, uint32_t, label, uint32_t, id);
+
+		EFSYS_ASSERT(eecp->eec_tx != NULL);
+		should_abort = eecp->eec_tx(arg, label, id);
+
+		return (should_abort);
+	}
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_COMP) != 0)
+		EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index,
+			    uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1),
+			    uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0));
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_ERR) != 0)
+		EFX_EV_QSTAT_INCR(eep, EV_TX_PKT_ERR);
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_TOO_BIG) != 0)
+		EFX_EV_QSTAT_INCR(eep, EV_TX_PKT_TOO_BIG);
+
+	if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_WQ_FF_FULL) != 0)
+		EFX_EV_QSTAT_INCR(eep, EV_TX_WQ_FF_FULL);
+
+	EFX_EV_QSTAT_INCR(eep, EV_TX_UNEXPECTED);
+	return (B_FALSE);
+}
+
+static	__checkReturn	boolean_t
+efx_ev_global(
+	__in		efx_evq_t *eep,
+	__in		efx_qword_t *eqp,
+	__in		const efx_ev_callbacks_t *eecp,
+	__in_opt	void *arg)
+{
+	efx_nic_t *enp = eep->ee_enp;
+	efx_port_t *epp = &(enp->en_port);
+	boolean_t should_abort;
+
+	EFX_EV_QSTAT_INCR(eep, EV_GLOBAL);
+	should_abort = B_FALSE;
+
+	/* Check for a link management event */
+	if (EFX_QWORD_FIELD(*eqp, FSF_BZ_GLB_EV_XG_MNT_INTR) != 0) {
+		EFX_EV_QSTAT_INCR(eep, EV_GLOBAL_MNT);
+
+		EFSYS_PROBE(xg_mgt);
+
+		epp->ep_mac_poll_needed = B_TRUE;
+	}
+
+	return (should_abort);
+}
+
+static	__checkReturn	boolean_t
+efx_ev_driver(
+	__in		efx_evq_t *eep,
+	__in		efx_qword_t *eqp,
+	__in		const efx_ev_callbacks_t *eecp,
+	__in_opt	void *arg)
+{
+	boolean_t should_abort;
+
+	EFX_EV_QSTAT_INCR(eep, EV_DRIVER);
+	should_abort = B_FALSE;
+
+	switch (EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBCODE)) {
+	case FSE_AZ_TX_DESCQ_FLS_DONE_EV: {
+		uint32_t label;
+
+		EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DESCQ_FLS_DONE);
+
+		label = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA);
+
+		EFSYS_PROBE1(tx_descq_fls_done, uint32_t, label);
+
+		EFSYS_ASSERT(eecp->eec_txq_flush_done != NULL);
+		should_abort = eecp->eec_txq_flush_done(arg, label);
+
+		break;
+	}
+	case FSE_AZ_RX_DESCQ_FLS_DONE_EV: {
+		uint32_t label;
+		uint32_t failed;
+
+		label = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_DESCQ_ID);
+		failed = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
+
+		EFSYS_ASSERT(eecp->eec_rxq_flush_done != NULL);
+		EFSYS_ASSERT(eecp->eec_rxq_flush_failed != NULL);
+
+		if (failed) {
+			EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_FAILED);
+
+			EFSYS_PROBE1(rx_descq_fls_failed, uint32_t, label);
+
+			should_abort = eecp->eec_rxq_flush_failed(arg, label);
+		} else {
+			EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_DONE);
+
+			EFSYS_PROBE1(rx_descq_fls_done, uint32_t, label);
+
+			should_abort = eecp->eec_rxq_flush_done(arg, label);
+		}
+
+		break;
+	}
+	case FSE_AZ_EVQ_INIT_DONE_EV:
+		EFSYS_ASSERT(eecp->eec_initialized != NULL);
+		should_abort = eecp->eec_initialized(arg);
+
+		break;
+
+	case FSE_AZ_EVQ_NOT_EN_EV:
+		EFSYS_PROBE(evq_not_en);
+		break;
+
+	case FSE_AZ_SRM_UPD_DONE_EV: {
+		uint32_t code;
+
+		EFX_EV_QSTAT_INCR(eep, EV_DRIVER_SRM_UPD_DONE);
+
+		code = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA);
+
+		EFSYS_ASSERT(eecp->eec_sram != NULL);
+		should_abort = eecp->eec_sram(arg, code);
+
+		break;
+	}
+	case FSE_AZ_WAKE_UP_EV: {
+		uint32_t id;
+
+		id = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA);
+
+		EFSYS_ASSERT(eecp->eec_wake_up != NULL);
+		should_abort = eecp->eec_wake_up(arg, id);
+
+		break;
+	}
+	case FSE_AZ_TX_PKT_NON_TCP_UDP:
+		EFSYS_PROBE(tx_pkt_non_tcp_udp);
+		break;
+
+	case FSE_AZ_TIMER_EV: {
+		uint32_t id;
+
+		id = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA);
+
+		EFSYS_ASSERT(eecp->eec_timer != NULL);
+		should_abort = eecp->eec_timer(arg, id);
+
+		break;
+	}
+	case FSE_AZ_RX_DSC_ERROR_EV:
+		EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DSC_ERROR);
+
+		EFSYS_PROBE(rx_dsc_error);
+
+		EFSYS_ASSERT(eecp->eec_exception != NULL);
+		should_abort = eecp->eec_exception(arg,
+			EFX_EXCEPTION_RX_DSC_ERROR, 0);
+
+		break;
+
+	case FSE_AZ_TX_DSC_ERROR_EV:
+		EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DSC_ERROR);
+
+		EFSYS_PROBE(tx_dsc_error);
+
+		EFSYS_ASSERT(eecp->eec_exception != NULL);
+		should_abort = eecp->eec_exception(arg,
+			EFX_EXCEPTION_TX_DSC_ERROR, 0);
+
+		break;
+
+	default:
+		break;
+	}
+
+	return (should_abort);
+}
+
+static	__checkReturn	boolean_t
+efx_ev_drv_gen(
+	__in		efx_evq_t *eep,
+	__in		efx_qword_t *eqp,
+	__in		const efx_ev_callbacks_t *eecp,
+	__in_opt	void *arg)
+{
+	uint32_t data;
+	boolean_t should_abort;
+
+	EFX_EV_QSTAT_INCR(eep, EV_DRV_GEN);
+
+	data = EFX_QWORD_FIELD(*eqp, FSF_AZ_EV_DATA_DW0);
+	if (data >= ((uint32_t)1 << 16)) {
+		EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index,
+			    uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1),
+			    uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0));
+		return (B_TRUE);
+	}
+
+	EFSYS_ASSERT(eecp->eec_software != NULL);
+	should_abort = eecp->eec_software(arg, (uint16_t)data);
+
+	return (should_abort);
+}
+
+#if EFSYS_OPT_MCDI
+
+static	__checkReturn	boolean_t
+efx_ev_mcdi(
+	__in		efx_evq_t *eep,
+	__in		efx_qword_t *eqp,
+	__in		const efx_ev_callbacks_t *eecp,
+	__in_opt	void *arg)
+{
+	efx_nic_t *enp = eep->ee_enp;
+	unsigned code;
+	boolean_t should_abort = B_FALSE;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+
+	if (enp->en_family != EFX_FAMILY_SIENA)
+		goto out;
+
+	EFSYS_ASSERT(eecp->eec_link_change != NULL);
+	EFSYS_ASSERT(eecp->eec_exception != NULL);
+#if EFSYS_OPT_MON_STATS
+	EFSYS_ASSERT(eecp->eec_monitor != NULL);
+#endif
+
+	EFX_EV_QSTAT_INCR(eep, EV_MCDI_RESPONSE);
+
+	code = EFX_QWORD_FIELD(*eqp, MCDI_EVENT_CODE);
+	switch (code) {
+	case MCDI_EVENT_CODE_BADSSERT:
+		efx_mcdi_ev_death(enp, EINTR);
+		break;
+
+	case MCDI_EVENT_CODE_CMDDONE:
+		efx_mcdi_ev_cpl(enp,
+				MCDI_EV_FIELD(eqp, CMDDONE_SEQ),
+				MCDI_EV_FIELD(eqp, CMDDONE_DATALEN),
+				MCDI_EV_FIELD(eqp, CMDDONE_ERRNO));
+		break;
+
+	case MCDI_EVENT_CODE_LINKCHANGE: {
+		efx_link_mode_t link_mode;
+
+		siena_phy_link_ev(enp, eqp, &link_mode);
+		should_abort = eecp->eec_link_change(arg, link_mode);
+		break;
+	}
+	case MCDI_EVENT_CODE_SENSOREVT: {
+#if EFSYS_OPT_MON_STATS
+		efx_mon_stat_t id;
+		efx_mon_stat_value_t value;
+		int rc;
+
+		if ((rc = siena_mon_ev(enp, eqp, &id, &value)) == 0)
+			should_abort = eecp->eec_monitor(arg, id, value);
+		else if (rc == ENOTSUP) {
+			should_abort = eecp->eec_exception(arg,
+				EFX_EXCEPTION_UNKNOWN_SENSOREVT,
+				MCDI_EV_FIELD(eqp, DATA));
+		} else
+			EFSYS_ASSERT(rc == ENODEV);	/* Wrong port */
+#else
+		should_abort = B_FALSE;
+#endif
+		break;
+	}
+	case MCDI_EVENT_CODE_SCHEDERR:
+		/* Informational only */
+		break;
+
+	case MCDI_EVENT_CODE_REBOOT:
+		efx_mcdi_ev_death(enp, EIO);
+		break;
+
+	case MCDI_EVENT_CODE_MAC_STATS_DMA:
+#if EFSYS_OPT_MAC_STATS
+		if (eecp->eec_mac_stats != NULL) {
+			eecp->eec_mac_stats(arg,
+			    MCDI_EV_FIELD(eqp, MAC_STATS_DMA_GENERATION));
+		}
+#endif
+		break;
+
+	case MCDI_EVENT_CODE_FWALERT: {
+		uint32_t reason = MCDI_EV_FIELD(eqp, FWALERT_REASON);
+
+		if (reason == MCDI_EVENT_FWALERT_REASON_SRAM_ACCESS)
+			should_abort = eecp->eec_exception(arg,
+				EFX_EXCEPTION_FWALERT_SRAM,
+				MCDI_EV_FIELD(eqp, FWALERT_DATA));
+		else
+			should_abort = eecp->eec_exception(arg,
+				EFX_EXCEPTION_UNKNOWN_FWALERT,
+				MCDI_EV_FIELD(eqp, DATA));
+		break;
+	}
+
+	default:
+		EFSYS_PROBE1(mc_pcol_error, int, code);
+		break;
+	}
+
+out:
+	return (should_abort);
+}
+
+#endif	/* EFSYS_OPT_MCDI */
+
+	__checkReturn	int
+efx_ev_qprime(
+	__in		efx_evq_t *eep,
+	__in		unsigned int count)
+{
+	efx_nic_t *enp = eep->ee_enp;
+	uint32_t rptr;
+	efx_dword_t dword;
+	int rc;
+
+	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
+
+	if (!(enp->en_mod_flags & EFX_MOD_INTR)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	rptr = count & eep->ee_mask;
+
+	EFX_POPULATE_DWORD_1(dword, FRF_AZ_EVQ_RPTR, rptr);
+
+	EFX_BAR_TBL_WRITED(enp, FR_AZ_EVQ_RPTR_REG, eep->ee_index,
+			    &dword, B_FALSE);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	boolean_t
+efx_ev_qpending(
+	__in		efx_evq_t *eep,
+	__in		unsigned int count)
+{
+	size_t offset;
+	efx_qword_t qword;
+
+	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
+
+	offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
+	EFSYS_MEM_READQ(eep->ee_esmp, offset, &qword);
+
+	return (EFX_QWORD_FIELD(qword, EFX_DWORD_0) != 0xffffffff &&
+		EFX_QWORD_FIELD(qword, EFX_DWORD_1) != 0xffffffff);
+}
+
+#if EFSYS_OPT_EV_PREFETCH
+
+			void
+efx_ev_qprefetch(
+	__in		efx_evq_t *eep,
+	__in		unsigned int count)
+{
+	unsigned int offset;
+
+	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
+
+	offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
+	EFSYS_MEM_PREFETCH(eep->ee_esmp, offset);
+}
+
+#endif	/* EFSYS_OPT_EV_PREFETCH */
+
+#define	EFX_EV_BATCH	8
+
+#define	EFX_EV_PRESENT(_qword)						\
+	(EFX_QWORD_FIELD((_qword), EFX_DWORD_0) != 0xffffffff &&	\
+	EFX_QWORD_FIELD((_qword), EFX_DWORD_1) != 0xffffffff)
+
+			void
+efx_ev_qpoll(
+	__in		efx_evq_t *eep,
+	__inout		unsigned int *countp,
+	__in		const efx_ev_callbacks_t *eecp,
+	__in_opt	void *arg)
+{
+	efx_qword_t ev[EFX_EV_BATCH];
+	unsigned int batch;
+	unsigned int total;
+	unsigned int count;
+	unsigned int index;
+	size_t offset;
+
+	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
+	EFSYS_ASSERT(countp != NULL);
+	EFSYS_ASSERT(eecp != NULL);
+
+	count = *countp;
+	do {
+		/* Read up until the end of the batch period */
+		batch = EFX_EV_BATCH - (count & (EFX_EV_BATCH - 1));
+		offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
+		for (total = 0; total < batch; ++total) {
+			EFSYS_MEM_READQ(eep->ee_esmp, offset, &(ev[total]));
+
+			if (!EFX_EV_PRESENT(ev[total]))
+				break;
+
+			EFSYS_PROBE3(event, unsigned int, eep->ee_index,
+			    uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_1),
+			    uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_0));
+
+			offset += sizeof (efx_qword_t);
+		}
+
+#if EFSYS_OPT_EV_PREFETCH && (EFSYS_OPT_EV_PREFETCH_PERIOD > 1)
+		/*
+		 * Prefetch the next batch when we get within PREFETCH_PERIOD
+		 * of a completed batch. If the batch is smaller, then prefetch
+		 * immediately.
+		 */
+		if (total == batch && total < EFSYS_OPT_EV_PREFETCH_PERIOD)
+			EFSYS_MEM_PREFETCH(eep->ee_esmp, offset);
+#endif	/* EFSYS_OPT_EV_PREFETCH */
+
+		/* Process the batch of events */
+		for (index = 0; index < total; ++index) {
+			boolean_t should_abort;
+			uint32_t code;
+			efx_ev_handler_t handler;
+
+#if EFSYS_OPT_EV_PREFETCH
+			/* Prefetch if we've now reached the batch period */
+			if (total == batch &&
+			    index + EFSYS_OPT_EV_PREFETCH_PERIOD == total) {
+				offset = (count + batch) & eep->ee_mask;
+				offset *= sizeof (efx_qword_t);
+
+				EFSYS_MEM_PREFETCH(eep->ee_esmp, offset);
+			}
+#endif	/* EFSYS_OPT_EV_PREFETCH */
+
+			EFX_EV_QSTAT_INCR(eep, EV_ALL);
+
+			code = EFX_QWORD_FIELD(ev[index], FSF_AZ_EV_CODE);
+			handler = eep->ee_handler[code];
+			EFSYS_ASSERT(handler != NULL);
+			should_abort = handler(eep, &(ev[index]), eecp, arg);
+			if (should_abort) {
+				/* Ignore subsequent events */
+				total = index + 1;
+				break;
+			}
+		}
+
+		/*
+		 * Now that the hardware has most likely moved onto dma'ing
+		 * into the next cache line, clear the processed events. Take
+		 * care to only clear out events that we've processed
+		 */
+		EFX_SET_QWORD(ev[0]);
+		offset = (count & eep->ee_mask) * sizeof (efx_qword_t);
+		for (index = 0; index < total; ++index) {
+			EFSYS_MEM_WRITEQ(eep->ee_esmp, offset, &(ev[0]));
+			offset += sizeof (efx_qword_t);
+		}
+
+		count += total;
+
+	} while (total == batch);
+
+	*countp = count;
+}
+
+		void
+efx_ev_qpost(
+	__in	efx_evq_t *eep,
+	__in	uint16_t data)
+{
+	efx_nic_t *enp = eep->ee_enp;
+	efx_qword_t ev;
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
+
+	EFX_POPULATE_QWORD_2(ev, FSF_AZ_EV_CODE, FSE_AZ_EV_CODE_DRV_GEN_EV,
+	    FSF_AZ_EV_DATA_DW0, (uint32_t)data);
+
+	EFX_POPULATE_OWORD_3(oword, FRF_AZ_DRV_EV_QID, eep->ee_index,
+	    EFX_DWORD_0, EFX_QWORD_FIELD(ev, EFX_DWORD_0),
+	    EFX_DWORD_1, EFX_QWORD_FIELD(ev, EFX_DWORD_1));
+
+	EFX_BAR_WRITEO(enp, FR_AZ_DRV_EV_REG, &oword);
+}
+
+	__checkReturn	int
+efx_ev_qmoderate(
+	__in		efx_evq_t *eep,
+	__in		unsigned int us)
+{
+	efx_nic_t *enp = eep->ee_enp;
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	unsigned int locked;
+	efx_dword_t dword;
+	int rc;
+
+	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
+
+	if (us > encp->enc_evq_timer_max_us) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	/* If the value is zero then disable the timer */
+	if (us == 0) {
+		if (enp->en_family == EFX_FAMILY_FALCON)
+			EFX_POPULATE_DWORD_2(dword,
+			    FRF_AB_TC_TIMER_MODE, FFE_AB_TIMER_MODE_DIS,
+			    FRF_AB_TC_TIMER_VAL, 0);
+		else
+			EFX_POPULATE_DWORD_2(dword,
+			    FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS,
+			    FRF_CZ_TC_TIMER_VAL, 0);
+	} else {
+		uint32_t timer_val;
+
+		/* Calculate the timer value in quanta */
+		timer_val = us * 1000 / encp->enc_evq_timer_quantum_ns;
+
+		/* Moderation value is base 0 so we need to deduct 1 */
+		if (timer_val > 0)
+			timer_val--;
+
+		if (enp->en_family == EFX_FAMILY_FALCON)
+			EFX_POPULATE_DWORD_2(dword,
+			    FRF_AB_TC_TIMER_MODE, FFE_AB_TIMER_MODE_INT_HLDOFF,
+			    FRF_AB_TIMER_VAL, timer_val);
+		else
+			EFX_POPULATE_DWORD_2(dword,
+			    FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_INT_HLDOFF,
+			    FRF_CZ_TC_TIMER_VAL, timer_val);
+	}
+
+	locked = (eep->ee_index == 0) ? 1 : 0;
+
+	EFX_BAR_TBL_WRITED(enp, FR_BZ_TIMER_COMMAND_REGP0,
+	    eep->ee_index, &dword, locked);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_ev_qcreate(
+	__in		efx_nic_t *enp,
+	__in		unsigned int index,
+	__in		efsys_mem_t *esmp,
+	__in		size_t n,
+	__in		uint32_t id,
+	__deref_out	efx_evq_t **eepp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint32_t size;
+	efx_evq_t *eep;
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV);
+
+	EFSYS_ASSERT3U(enp->en_ev_qcount + 1, <, encp->enc_evq_limit);
+
+	if (!ISP2(n) || !(n & EFX_EVQ_NEVS_MASK)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+	if (index >= encp->enc_evq_limit) {
+		rc = EINVAL;
+		goto fail2;
+	}
+#if EFSYS_OPT_RX_SCALE
+	if (enp->en_intr.ei_type == EFX_INTR_LINE &&
+	    index >= EFX_MAXRSS_LEGACY) {
+		rc = EINVAL;
+		goto fail3;
+	}
+#endif
+	for (size = 0; (1 << size) <= (EFX_EVQ_MAXNEVS / EFX_EVQ_MINNEVS);
+	    size++)
+		if ((1 << size) == (int)(n / EFX_EVQ_MINNEVS))
+			break;
+	if (id + (1 << size) >= encp->enc_buftbl_limit) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	/* Allocate an EVQ object */
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_evq_t), eep);
+	if (eep == NULL) {
+		rc = ENOMEM;
+		goto fail5;
+	}
+
+	eep->ee_magic = EFX_EVQ_MAGIC;
+	eep->ee_enp = enp;
+	eep->ee_index = index;
+	eep->ee_mask = n - 1;
+	eep->ee_esmp = esmp;
+
+	/* Set up the handler table */
+	eep->ee_handler[FSE_AZ_EV_CODE_RX_EV] = efx_ev_rx;
+	eep->ee_handler[FSE_AZ_EV_CODE_TX_EV] = efx_ev_tx;
+	eep->ee_handler[FSE_AZ_EV_CODE_DRIVER_EV] = efx_ev_driver;
+	eep->ee_handler[FSE_AZ_EV_CODE_GLOBAL_EV] = efx_ev_global;
+	eep->ee_handler[FSE_AZ_EV_CODE_DRV_GEN_EV] = efx_ev_drv_gen;
+#if EFSYS_OPT_MCDI
+	eep->ee_handler[FSE_AZ_EV_CODE_MCDI_EVRESPONSE] = efx_ev_mcdi;
+#endif	/* EFSYS_OPT_MCDI */
+
+	/* Set up the new event queue */
+	if (enp->en_family != EFX_FAMILY_FALCON) {
+		EFX_POPULATE_OWORD_1(oword, FRF_CZ_TIMER_Q_EN, 1);
+		EFX_BAR_TBL_WRITEO(enp, FR_AZ_TIMER_TBL, index, &oword);
+	}
+
+	EFX_POPULATE_OWORD_3(oword, FRF_AZ_EVQ_EN, 1, FRF_AZ_EVQ_SIZE, size,
+	    FRF_AZ_EVQ_BUF_BASE_ID, id);
+
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_EVQ_PTR_TBL, index, &oword);
+
+	enp->en_ev_qcount++;
+	*eepp = eep;
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+#if EFSYS_OPT_RX_SCALE
+fail3:
+	EFSYS_PROBE(fail3);
+#endif
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_NAMES
+/* START MKCONFIG GENERATED EfxEventQueueStatNamesBlock 67e9bdcd920059bd */
+static const char 	__cs * __cs __efx_ev_qstat_name[] = {
+	"all",
+	"rx",
+	"rx_ok",
+	"rx_recovery",
+	"rx_frm_trunc",
+	"rx_tobe_disc",
+	"rx_pause_frm_err",
+	"rx_buf_owner_id_err",
+	"rx_ipv4_hdr_chksum_err",
+	"rx_tcp_udp_chksum_err",
+	"rx_eth_crc_err",
+	"rx_ip_frag_err",
+	"rx_mcast_pkt",
+	"rx_mcast_hash_match",
+	"rx_tcp_ipv4",
+	"rx_tcp_ipv6",
+	"rx_udp_ipv4",
+	"rx_udp_ipv6",
+	"rx_other_ipv4",
+	"rx_other_ipv6",
+	"rx_non_ip",
+	"rx_overrun",
+	"tx",
+	"tx_wq_ff_full",
+	"tx_pkt_err",
+	"tx_pkt_too_big",
+	"tx_unexpected",
+	"global",
+	"global_phy",
+	"global_mnt",
+	"global_rx_recovery",
+	"driver",
+	"driver_srm_upd_done",
+	"driver_tx_descq_fls_done",
+	"driver_rx_descq_fls_done",
+	"driver_rx_descq_fls_failed",
+	"driver_rx_dsc_error",
+	"driver_tx_dsc_error",
+	"drv_gen",
+	"mcdi_response",
+};
+/* END MKCONFIG GENERATED EfxEventQueueStatNamesBlock */
+
+		const char __cs *
+efx_ev_qstat_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(id, <, EV_NQSTATS);
+
+	return (__efx_ev_qstat_name[id]);
+}
+#endif	/* EFSYS_OPT_NAMES */
+
+#if EFSYS_OPT_QSTATS
+					void
+efx_ev_qstats_update(
+	__in				efx_evq_t *eep,
+	__inout_ecount(EV_NQSTATS)	efsys_stat_t *stat)
+{
+	unsigned int id;
+
+	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
+
+	for (id = 0; id < EV_NQSTATS; id++) {
+		efsys_stat_t *essp = &stat[id];
+
+		EFSYS_STAT_INCR(essp, eep->ee_stat[id]);
+		eep->ee_stat[id] = 0;
+	}
+}
+#endif	/* EFSYS_OPT_QSTATS */
+
+		void
+efx_ev_qdestroy(
+	__in	efx_evq_t *eep)
+{
+	efx_nic_t *enp = eep->ee_enp;
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
+
+	EFSYS_ASSERT(enp->en_ev_qcount != 0);
+	--enp->en_ev_qcount;
+
+	/* Purge event queue */
+	EFX_ZERO_OWORD(oword);
+
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_EVQ_PTR_TBL,
+	    eep->ee_index, &oword);
+
+	if (enp->en_family != EFX_FAMILY_FALCON) {
+		EFX_ZERO_OWORD(oword);
+		EFX_BAR_TBL_WRITEO(enp, FR_AZ_TIMER_TBL,
+		    eep->ee_index, &oword);
+	}
+
+	/* Free the EVQ object */
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep);
+}
+
+		void
+efx_ev_fini(
+	__in	efx_nic_t *enp)
+{
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV);
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
+	EFSYS_ASSERT3U(enp->en_ev_qcount, ==, 0);
+
+	enp->en_mod_flags &= ~EFX_MOD_EV;
+}
--- /dev/null	2013-08-22 18:57:27.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_impl.h	2013-08-22 18:57:27.881329815 -0400
@@ -0,0 +1,745 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_EFX_IMPL_H
+#define	_SYS_EFX_IMPL_H
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_regs.h"
+
+#if EFSYS_OPT_FALCON
+#include "falcon_impl.h"
+#endif	/* EFSYS_OPT_FALCON */
+
+#if EFSYS_OPT_SIENA
+#include "siena_impl.h"
+#endif	/* EFSYS_OPT_SIENA */
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	EFX_MOD_MCDI	0x00000001
+#define	EFX_MOD_PROBE	0x00000002
+#define	EFX_MOD_NVRAM	0x00000004
+#define	EFX_MOD_VPD	0x00000008
+#define	EFX_MOD_NIC	0x00000010
+#define	EFX_MOD_INTR	0x00000020
+#define	EFX_MOD_EV	0x00000040
+#define	EFX_MOD_RX	0x00000080
+#define	EFX_MOD_TX	0x00000100
+#define	EFX_MOD_PORT	0x00000200
+#define	EFX_MOD_MON	0x00000400
+#define	EFX_MOD_WOL	0x00000800
+#define	EFX_MOD_FILTER	0x00001000
+
+#define	EFX_RESET_MAC	0x00000001
+#define	EFX_RESET_PHY	0x00000002
+
+typedef enum efx_mac_type_e {
+	EFX_MAC_INVALID = 0,
+	EFX_MAC_FALCON_GMAC,
+	EFX_MAC_FALCON_XMAC,
+	EFX_MAC_SIENA,
+	EFX_MAC_NTYPES
+} efx_mac_type_t;
+
+typedef struct efx_mac_ops_s {
+	int		(*emo_reset)(efx_nic_t *); /* optional */
+	int		(*emo_poll)(efx_nic_t *, efx_link_mode_t *);
+	int		(*emo_up)(efx_nic_t *, boolean_t *);
+	int		(*emo_reconfigure)(efx_nic_t *);
+#if EFSYS_OPT_LOOPBACK
+	int		(*emo_loopback_set)(efx_nic_t *, efx_link_mode_t,
+					    efx_loopback_type_t);
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_MAC_STATS
+	int		(*emo_stats_upload)(efx_nic_t *, efsys_mem_t *);
+	int		(*emo_stats_periodic)(efx_nic_t *, efsys_mem_t *,
+					      uint16_t, boolean_t);
+	int		(*emo_stats_update)(efx_nic_t *, efsys_mem_t *,
+					    efsys_stat_t *, uint32_t *);
+#endif	/* EFSYS_OPT_MAC_STATS */
+} efx_mac_ops_t;
+
+typedef struct efx_phy_ops_s {
+	int		(*epo_power)(efx_nic_t *, boolean_t); /* optional */
+	int		(*epo_reset)(efx_nic_t *);
+	int		(*epo_reconfigure)(efx_nic_t *);
+	int		(*epo_verify)(efx_nic_t *);
+	int		(*epo_uplink_check)(efx_nic_t *,
+					    boolean_t *); /* optional */
+	int		(*epo_downlink_check)(efx_nic_t *, efx_link_mode_t *,
+					      unsigned int *, uint32_t *);
+	int		(*epo_oui_get)(efx_nic_t *, uint32_t *);
+#if EFSYS_OPT_PHY_STATS
+	int		(*epo_stats_update)(efx_nic_t *, efsys_mem_t *,
+					    uint32_t *);
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+#if EFSYS_OPT_NAMES
+	const char	__cs *(*epo_prop_name)(efx_nic_t *, unsigned int);
+#endif	/* EFSYS_OPT_PHY_PROPS */
+	int		(*epo_prop_get)(efx_nic_t *, unsigned int, uint32_t,
+					uint32_t *);
+	int		(*epo_prop_set)(efx_nic_t *, unsigned int, uint32_t);
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+	int		(*epo_bist_start)(efx_nic_t *, efx_phy_bist_type_t);
+	int		(*epo_bist_poll)(efx_nic_t *, efx_phy_bist_type_t,
+					 efx_phy_bist_result_t *, uint32_t *,
+					 unsigned long *, size_t);
+	void		(*epo_bist_stop)(efx_nic_t *, efx_phy_bist_type_t);
+#endif	/* EFSYS_OPT_PHY_BIST */
+} efx_phy_ops_t;
+
+typedef struct efx_port_s {
+	efx_mac_type_t		ep_mac_type;
+	uint32_t  		ep_phy_type;
+	uint8_t			ep_port;
+	uint32_t		ep_mac_pdu;
+	uint8_t			ep_mac_addr[6];
+	efx_link_mode_t		ep_link_mode;
+	boolean_t		ep_unicst;
+	boolean_t		ep_brdcst;
+	unsigned int		ep_fcntl;
+	boolean_t		ep_fcntl_autoneg;
+	efx_oword_t		ep_multicst_hash[2];
+#if EFSYS_OPT_LOOPBACK
+	efx_loopback_type_t	ep_loopback_type;
+	efx_link_mode_t		ep_loopback_link_mode;
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_PHY_FLAGS
+	uint32_t		ep_phy_flags;
+#endif	/* EFSYS_OPT_PHY_FLAGS */
+#if EFSYS_OPT_PHY_LED_CONTROL
+	efx_phy_led_mode_t	ep_phy_led_mode;
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+	efx_phy_media_type_t	ep_fixed_port_type;
+	efx_phy_media_type_t	ep_module_type;
+	uint32_t		ep_adv_cap_mask;
+	uint32_t		ep_lp_cap_mask;
+	uint32_t		ep_default_adv_cap_mask;
+	uint32_t		ep_phy_cap_mask;
+#if EFSYS_OPT_PHY_TXC43128 || EFSYS_OPT_PHY_QT2025C
+	union {
+		struct {
+			unsigned int	bug10934_count;
+		} ep_txc43128;
+		struct {
+			unsigned int	bug17190_count;
+		} ep_qt2025c;
+	};
+#endif
+	boolean_t		ep_mac_poll_needed; /* falcon only */
+	boolean_t		ep_mac_up; /* falcon only */
+	uint32_t		ep_fwver; /* falcon only */
+	boolean_t		ep_mac_drain;
+	boolean_t		ep_mac_stats_pending;
+#if EFSYS_OPT_PHY_BIST
+	efx_phy_bist_type_t	ep_current_bist;
+#endif
+	efx_mac_ops_t		*ep_emop;
+	efx_phy_ops_t		*ep_epop;
+} efx_port_t;
+
+typedef struct efx_mon_ops_s {
+	int	(*emo_reset)(efx_nic_t *);
+	int	(*emo_reconfigure)(efx_nic_t *);
+#if EFSYS_OPT_MON_STATS
+	int	(*emo_stats_update)(efx_nic_t *, efsys_mem_t *,
+				    efx_mon_stat_value_t *);
+#endif	/* EFSYS_OPT_MON_STATS */
+} efx_mon_ops_t;
+
+typedef struct efx_mon_s {
+	efx_mon_type_t	em_type;
+	efx_mon_ops_t	*em_emop;
+} efx_mon_t;
+
+typedef struct efx_intr_s {
+	efx_intr_type_t	ei_type;
+	efsys_mem_t	*ei_esmp;
+	unsigned int	ei_level;
+} efx_intr_t;
+
+typedef struct efx_nic_ops_s {
+	int	(*eno_probe)(efx_nic_t *);
+	int	(*eno_reset)(efx_nic_t *);
+	int	(*eno_init)(efx_nic_t *);
+#if EFSYS_OPT_DIAG
+	int	(*eno_sram_test)(efx_nic_t *, efx_sram_pattern_fn_t);
+	int	(*eno_register_test)(efx_nic_t *);
+#endif	/* EFSYS_OPT_DIAG */
+	void	(*eno_fini)(efx_nic_t *);
+	void	(*eno_unprobe)(efx_nic_t *);
+} efx_nic_ops_t;
+
+#ifndef EFX_TXQ_LIMIT_TARGET
+# define EFX_TXQ_LIMIT_TARGET 259
+#endif
+#ifndef EFX_RXQ_LIMIT_TARGET
+# define EFX_RXQ_LIMIT_TARGET 768
+#endif
+#ifndef EFX_TXQ_DC_SIZE
+#define EFX_TXQ_DC_SIZE 1 /* 16 descriptors */
+#endif
+#ifndef EFX_RXQ_DC_SIZE
+#define EFX_RXQ_DC_SIZE 3 /* 64 descriptors */
+#endif
+
+#if EFSYS_OPT_FILTER
+
+typedef enum efx_filter_type_e {
+	EFX_FILTER_RX_TCP_FULL,	/* TCP/IPv4 4-tuple {dIP,dTCP,sIP,sTCP} */
+	EFX_FILTER_RX_TCP_WILD,	/* TCP/IPv4 dest    {dIP,dTCP,  -,   -} */
+	EFX_FILTER_RX_UDP_FULL,	/* UDP/IPv4 4-tuple {dIP,dUDP,sIP,sUDP} */
+	EFX_FILTER_RX_UDP_WILD,	/* UDP/IPv4 dest    {dIP,dUDP,  -,   -} */
+
+#if EFSYS_OPT_SIENA
+	EFX_FILTER_RX_MAC_FULL,	/* Ethernet {dMAC,VLAN} */
+	EFX_FILTER_RX_MAC_WILD,	/* Ethernet {dMAC,   -} */
+
+	EFX_FILTER_TX_TCP_FULL,		/* TCP/IPv4 {dIP,dTCP,sIP,sTCP} */
+	EFX_FILTER_TX_TCP_WILD,		/* TCP/IPv4 {  -,   -,sIP,sTCP} */
+	EFX_FILTER_TX_UDP_FULL,		/* UDP/IPv4 {dIP,dTCP,sIP,sTCP} */
+	EFX_FILTER_TX_UDP_WILD,		/* UDP/IPv4 source (host, port) */
+
+	EFX_FILTER_TX_MAC_FULL,		/* Ethernet source (MAC address, VLAN ID) */
+	EFX_FILTER_TX_MAC_WILD,		/* Ethernet source (MAC address) */
+#endif /* EFSYS_OPT_SIENA */
+
+	EFX_FILTER_NTYPES
+} efx_filter_type_t;
+
+typedef enum efx_filter_tbl_id_e {
+	EFX_FILTER_TBL_RX_IP = 0,
+	EFX_FILTER_TBL_RX_MAC,
+	EFX_FILTER_TBL_TX_IP,
+	EFX_FILTER_TBL_TX_MAC,
+	EFX_FILTER_NTBLS
+} efx_filter_tbl_id_t;
+
+typedef struct efx_filter_tbl_s {
+	int			eft_size;	/* number of entries */
+	int			eft_used;	/* active count */
+	uint32_t		*eft_bitmap;	/* active bitmap */
+	efx_filter_spec_t	*eft_spec;	/* array of saved specs */
+} efx_filter_tbl_t;
+
+typedef struct efx_filter_s {
+	efx_filter_tbl_t	ef_tbl[EFX_FILTER_NTBLS];
+	unsigned int		ef_depth[EFX_FILTER_NTYPES];
+} efx_filter_t;
+
+
+extern	__checkReturn	int
+efx_filter_insert_filter(
+	__in		efx_nic_t *enp,
+	__in		efx_filter_spec_t *spec,
+	__in		boolean_t replace);
+
+extern	__checkReturn	int
+efx_filter_remove_filter(
+	__in		efx_nic_t *enp,
+	__in		efx_filter_spec_t *spec);
+
+extern			void
+efx_filter_remove_index(
+	__inout		efx_nic_t *enp,
+	__in		efx_filter_type_t type,
+	__in		int filter_idx);
+
+extern			void
+efx_filter_redirect_index(
+	__inout		efx_nic_t *enp,
+	__in		efx_filter_type_t type,
+	__in		int filter_index,
+	__in		int rxq_index);
+
+extern	__checkReturn	int
+efx_filter_clear_tbl(
+	__in		efx_nic_t *enp,
+	__in		efx_filter_tbl_id_t tbl);
+
+#endif	/* EFSYS_OPT_FILTER */
+
+#if EFSYS_OPT_NVRAM
+typedef struct efx_nvram_ops_s {
+#if EFSYS_OPT_DIAG
+	int	(*envo_test)(efx_nic_t *);
+#endif	/* EFSYS_OPT_DIAG */
+	int	(*envo_size)(efx_nic_t *, efx_nvram_type_t, size_t *);
+	int	(*envo_get_version)(efx_nic_t *, efx_nvram_type_t,
+				    uint32_t *, uint16_t *);
+	int	(*envo_rw_start)(efx_nic_t *, efx_nvram_type_t, size_t *);
+	int	(*envo_read_chunk)(efx_nic_t *, efx_nvram_type_t,
+				    unsigned int, caddr_t, size_t);
+	int	(*envo_erase)(efx_nic_t *, efx_nvram_type_t);
+	int	(*envo_write_chunk)(efx_nic_t *, efx_nvram_type_t,
+				    unsigned int, caddr_t, size_t);
+	void	(*envo_rw_finish)(efx_nic_t *, efx_nvram_type_t);
+	int	(*envo_set_version)(efx_nic_t *, efx_nvram_type_t, uint16_t *);
+
+} efx_nvram_ops_t;
+#endif /* EFSYS_OPT_NVRAM */
+
+#if EFSYS_OPT_VPD
+typedef struct efx_vpd_ops_s {
+	int	(*evpdo_init)(efx_nic_t *);
+	int	(*evpdo_size)(efx_nic_t *, size_t *);
+	int	(*evpdo_read)(efx_nic_t *, caddr_t, size_t);
+	int	(*evpdo_verify)(efx_nic_t *, caddr_t, size_t);
+	int	(*evpdo_reinit)(efx_nic_t *, caddr_t, size_t);
+	int	(*evpdo_get)(efx_nic_t *, caddr_t, size_t, efx_vpd_value_t *);
+	int	(*evpdo_set)(efx_nic_t *, caddr_t, size_t, efx_vpd_value_t *);
+	int	(*evpdo_next)(efx_nic_t *, caddr_t, size_t, efx_vpd_value_t *,
+			    unsigned int *);
+	int	(*evpdo_write)(efx_nic_t *, caddr_t, size_t);
+	void	(*evpdo_fini)(efx_nic_t *);
+} efx_vpd_ops_t;
+#endif	/* EFSYS_OPT_VPD */
+
+struct efx_nic_s {
+	uint32_t		en_magic;
+	efx_family_t		en_family;
+	uint32_t		en_features;
+	efsys_identifier_t	*en_esip;
+	efsys_lock_t		*en_eslp;
+	efsys_bar_t 		*en_esbp;
+	unsigned int		en_mod_flags;
+	unsigned int		en_reset_flags;
+	efx_nic_cfg_t		en_nic_cfg;
+	efx_port_t		en_port;
+	efx_mon_t		en_mon;
+	efx_intr_t		en_intr;
+	uint32_t		en_ev_qcount;
+	uint32_t		en_rx_qcount;
+	uint32_t		en_tx_qcount;
+	efx_nic_ops_t		*en_enop;
+#if EFSYS_OPT_FILTER
+	efx_filter_t		en_filter;
+#endif	/* EFSYS_OPT_FILTER */
+#if EFSYS_OPT_NVRAM
+	efx_nvram_type_t	en_nvram_locked;
+	efx_nvram_ops_t		*en_envop;
+#endif	/* EFSYS_OPT_NVRAM */
+#if EFSYS_OPT_VPD
+	efx_vpd_ops_t		*en_evpdop;
+#endif	/* EFSYS_OPT_VPD */
+	union {
+#if EFSYS_OPT_FALCON
+		struct {
+			falcon_spi_dev_t	enu_fsd[FALCON_SPI_NTYPES];
+			falcon_i2c_t		enu_fip;
+			boolean_t		enu_i2c_locked;
+#if EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE
+			const uint8_t		*enu_forced_cfg;
+#endif	/* EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE */
+			uint8_t			enu_mon_devid;
+#if EFSYS_OPT_PCIE_TUNE
+			unsigned int 		enu_nlanes;
+#endif	/* EFSYS_OPT_PCIE_TUNE */
+			uint16_t		enu_board_rev;
+			boolean_t		enu_internal_sram;
+			uint8_t			enu_sram_num_bank;
+			uint8_t			enu_sram_bank_size;
+		} falcon;
+#endif	/* EFSYS_OPT_FALCON */
+#if EFSYS_OPT_SIENA
+		struct {
+#if EFSYS_OPT_MCDI
+			efx_mcdi_iface_t	enu_mip;
+#endif	/* EFSYS_OPT_MCDI */
+#if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
+			unsigned int		enu_partn_mask;
+#endif	/* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */
+#if EFSYS_OPT_VPD
+			caddr_t			enu_svpd;
+			size_t			enu_svpd_length;
+#endif	/* EFSYS_OPT_VPD */
+		} siena;
+#endif	/* EFSYS_OPT_SIENA */
+	} en_u;
+};
+
+
+#define	EFX_NIC_MAGIC	0x02121996
+
+typedef	boolean_t (*efx_ev_handler_t)(efx_evq_t *, efx_qword_t *,
+    const efx_ev_callbacks_t *, void *);
+
+struct efx_evq_s {
+	uint32_t			ee_magic;
+	efx_nic_t			*ee_enp;
+	unsigned int			ee_index;
+	unsigned int			ee_mask;
+	efsys_mem_t			*ee_esmp;
+#if EFSYS_OPT_QSTATS
+	uint32_t			ee_stat[EV_NQSTATS];
+#endif	/* EFSYS_OPT_QSTATS */
+	efx_ev_handler_t		ee_handler[1 << FSF_AZ_EV_CODE_WIDTH];
+};
+
+#define	EFX_EVQ_MAGIC	0x08081997
+
+#define	EFX_EVQ_FALCON_TIMER_QUANTUM_NS	4968 /* 621 cycles */
+#define	EFX_EVQ_SIENA_TIMER_QUANTUM_NS	6144 /* 768 cycles */
+
+struct efx_rxq_s {
+	uint32_t			er_magic;
+	efx_nic_t			*er_enp;
+	unsigned int			er_index;
+	unsigned int			er_mask;
+	efsys_mem_t			*er_esmp;
+};
+
+#define	EFX_RXQ_MAGIC	0x15022005
+
+struct efx_txq_s {
+	uint32_t			et_magic;
+	efx_nic_t			*et_enp;
+	unsigned int			et_index;
+	unsigned int			et_mask;
+	efsys_mem_t			*et_esmp;
+#if EFSYS_OPT_QSTATS
+	uint32_t			et_stat[TX_NQSTATS];
+#endif	/* EFSYS_OPT_QSTATS */
+};
+
+#define	EFX_TXQ_MAGIC	0x05092005
+
+#define	EFX_MAC_ADDR_COPY(_dst, _src)					\
+	do {								\
+		(_dst)[0] = (_src)[0];					\
+		(_dst)[1] = (_src)[1];					\
+		(_dst)[2] = (_src)[2];					\
+		(_dst)[3] = (_src)[3];					\
+		(_dst)[4] = (_src)[4];					\
+		(_dst)[5] = (_src)[5];					\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#if EFSYS_OPT_CHECK_REG
+#define	EFX_CHECK_REG(_enp, _reg)					\
+	do {								\
+		const char __cs *name = #_reg;				\
+		char min = name[4];					\
+		char max = name[5];					\
+		char rev;						\
+									\
+		switch ((_enp)->en_family) {				\
+		case EFX_FAMILY_FALCON:					\
+			rev = 'B';					\
+			break;						\
+									\
+		case EFX_FAMILY_SIENA:					\
+			rev = 'C';					\
+			break;						\
+									\
+		default:						\
+			rev = '?';					\
+			break;						\
+		}							\
+									\
+		EFSYS_ASSERT3S(rev, >=, min);				\
+		EFSYS_ASSERT3S(rev, <=, max);				\
+									\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+#else
+#define	EFX_CHECK_REG(_enp, _reg) do {					\
+	_NOTE(CONSTANTCONDITION)					\
+	} while(B_FALSE)
+#endif
+
+#define	EFX_BAR_READD(_enp, _reg, _edp, _lock)				\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_BAR_READD((_enp)->en_esbp, _reg ## _OFST,		\
+		    (_edp), (_lock));					\
+		EFSYS_PROBE3(efx_bar_readd, const char *, #_reg,	\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_edp)->ed_u32[0]);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_WRITED(_enp, _reg, _edp, _lock)				\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_PROBE3(efx_bar_writed, const char *, #_reg,	\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_edp)->ed_u32[0]);			\
+		EFSYS_BAR_WRITED((_enp)->en_esbp, _reg ## _OFST,	\
+		    (_edp), (_lock));					\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_READQ(_enp, _reg, _eqp)					\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_BAR_READQ((_enp)->en_esbp, _reg ## _OFST,		\
+		    (_eqp));						\
+		EFSYS_PROBE4(efx_bar_readq, const char *, #_reg,	\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_eqp)->eq_u32[1],			\
+		    uint32_t, (_eqp)->eq_u32[0]);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_WRITEQ(_enp, _reg, _eqp)				\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_PROBE4(efx_bar_writeq, const char *, #_reg,	\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_eqp)->eq_u32[1],			\
+		    uint32_t, (_eqp)->eq_u32[0]);			\
+		EFSYS_BAR_WRITEQ((_enp)->en_esbp, _reg ## _OFST,	\
+		    (_eqp));						\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_READO(_enp, _reg, _eop)					\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_BAR_READO((_enp)->en_esbp, _reg ## _OFST,		\
+		    (_eop), B_TRUE);					\
+		EFSYS_PROBE6(efx_bar_reado, const char *, #_reg,	\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_eop)->eo_u32[3],			\
+		    uint32_t, (_eop)->eo_u32[2],			\
+		    uint32_t, (_eop)->eo_u32[1],			\
+		    uint32_t, (_eop)->eo_u32[0]);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_WRITEO(_enp, _reg, _eop)				\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_PROBE6(efx_bar_writeo, const char *, #_reg,	\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_eop)->eo_u32[3],			\
+		    uint32_t, (_eop)->eo_u32[2],			\
+		    uint32_t, (_eop)->eo_u32[1],			\
+		    uint32_t, (_eop)->eo_u32[0]);			\
+		EFSYS_BAR_WRITEO((_enp)->en_esbp, _reg ## _OFST,	\
+		    (_eop), B_TRUE);					\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_TBL_READD(_enp, _reg, _index, _edp, _lock)		\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_BAR_READD((_enp)->en_esbp,			\
+		    (_reg ## _OFST + ((_index) * _reg ## _STEP)),	\
+		    (_edp), (_lock));					\
+		EFSYS_PROBE4(efx_bar_tbl_readd, const char *, #_reg,	\
+		    uint32_t, (_index),					\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_edp)->ed_u32[0]);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_TBL_WRITED(_enp, _reg, _index, _edp, _lock)		\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_PROBE4(efx_bar_tbl_writed, const char *, #_reg,	\
+		    uint32_t, (_index),					\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_edp)->ed_u32[0]);			\
+		EFSYS_BAR_WRITED((_enp)->en_esbp,			\
+		    (_reg ## _OFST + ((_index) * _reg ## _STEP)),	\
+		    (_edp), (_lock));					\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_TBL_WRITED3(_enp, _reg, _index, _edp, _lock)		\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_PROBE4(efx_bar_tbl_writed, const char *, #_reg,	\
+		    uint32_t, (_index),					\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_edp)->ed_u32[0]);			\
+		EFSYS_BAR_WRITED((_enp)->en_esbp,			\
+		    (_reg ## _OFST +					\
+		    (3 * sizeof (efx_dword_t)) + 			\
+		    ((_index) * _reg ## _STEP)),			\
+		    (_edp), (_lock));					\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_TBL_READQ(_enp, _reg, _index, _eqp)			\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_BAR_READQ((_enp)->en_esbp,			\
+		    (_reg ## _OFST + ((_index) * _reg ## _STEP)),	\
+		    (_eqp));						\
+		EFSYS_PROBE5(efx_bar_tbl_readq, const char *, #_reg,	\
+		    uint32_t, (_index),					\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_eqp)->eq_u32[1],			\
+		    uint32_t, (_eqp)->eq_u32[0]);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_TBL_WRITEQ(_enp, _reg, _index, _eqp)			\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_PROBE5(efx_bar_tbl_writeq, const char *, #_reg,	\
+		    uint32_t, (_index),					\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_eqp)->eq_u32[1],			\
+		    uint32_t, (_eqp)->eq_u32[0]);			\
+		EFSYS_BAR_WRITEQ((_enp)->en_esbp,			\
+		    (_reg ## _OFST + ((_index) * _reg ## _STEP)),	\
+		    (_eqp));						\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_TBL_READO(_enp, _reg, _index, _eop)			\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_BAR_READO((_enp)->en_esbp,			\
+		    (_reg ## _OFST + ((_index) * _reg ## _STEP)),	\
+		    (_eop), B_TRUE);					\
+		EFSYS_PROBE7(efx_bar_tbl_reado, const char *, #_reg,	\
+		    uint32_t, (_index),					\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_eop)->eo_u32[3],			\
+		    uint32_t, (_eop)->eo_u32[2],			\
+		    uint32_t, (_eop)->eo_u32[1],			\
+		    uint32_t, (_eop)->eo_u32[0]);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_BAR_TBL_WRITEO(_enp, _reg, _index, _eop)			\
+	do {								\
+		EFX_CHECK_REG((_enp), (_reg));				\
+		EFSYS_PROBE7(efx_bar_tbl_writeo, const char *, #_reg,	\
+		    uint32_t, (_index),					\
+		    uint32_t, _reg ## _OFST,				\
+		    uint32_t, (_eop)->eo_u32[3],			\
+		    uint32_t, (_eop)->eo_u32[2],			\
+		    uint32_t, (_eop)->eo_u32[1],			\
+		    uint32_t, (_eop)->eo_u32[0]);			\
+		EFSYS_BAR_WRITEO((_enp)->en_esbp,			\
+		    (_reg ## _OFST + ((_index) * _reg ## _STEP)),	\
+		    (_eop), B_TRUE);					\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+extern	__checkReturn	int
+efx_mac_select(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+efx_phy_probe(
+	__in		efx_nic_t *enp);
+
+extern			void
+efx_phy_unprobe(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_VPD
+
+/* VPD utility functions */
+
+extern	__checkReturn		int
+efx_vpd_hunk_length(
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out			size_t *lengthp);
+
+extern	__checkReturn		int
+efx_vpd_hunk_verify(
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out_opt		boolean_t *cksummedp);
+
+extern	__checkReturn		int
+efx_vpd_hunk_reinit(
+	__in			caddr_t data,
+	__in			size_t size,
+	__in			boolean_t wantpid);
+
+extern	__checkReturn		int
+efx_vpd_hunk_get(
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_tag_t tag,
+	__in			efx_vpd_keyword_t keyword,
+	__out			unsigned int *payloadp,
+	__out			uint8_t *paylenp);
+
+extern	__checkReturn			int
+efx_vpd_hunk_next(
+	__in_bcount(size)		caddr_t data,
+	__in				size_t size,
+	__out				efx_vpd_tag_t *tagp,
+	__out				efx_vpd_keyword_t *keyword,
+	__out_bcount_opt(*paylenp)	unsigned int *payloadp,
+	__out_opt			uint8_t *paylenp,
+	__inout				unsigned int *contp);
+
+extern	__checkReturn		int
+efx_vpd_hunk_set(
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_value_t *evvp);
+
+#endif	/* EFSYS_OPT_VPD */
+
+#if EFSYS_OPT_DIAG
+
+extern	efx_sram_pattern_fn_t	__cs __efx_sram_pattern_fns[];
+
+typedef struct efx_register_set_s {
+	unsigned int		address;
+	unsigned int		step;
+	unsigned int		rows;
+	efx_oword_t		mask;
+} efx_register_set_t;
+
+extern	__checkReturn	int
+efx_nic_test_registers(
+	__in		efx_nic_t *enp,
+	__in		efx_register_set_t *rsp,
+	__in		size_t count);
+
+extern	__checkReturn	int
+efx_nic_test_tables(
+	__in		efx_nic_t *enp,
+	__in		efx_register_set_t *rsp,
+	__in		efx_pattern_type_t pattern,
+	__in		size_t count);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_EFX_IMPL_H */
--- /dev/null	2013-08-22 18:57:27.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_intr.c	2013-08-22 18:57:27.973979335 -0400
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+	__checkReturn	int
+efx_intr_init(
+	__in		efx_nic_t *enp,
+	__in		efx_intr_type_t type,
+	__in		efsys_mem_t *esmp)
+{
+	efx_intr_t *eip = &(enp->en_intr);
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+
+	if (enp->en_mod_flags & EFX_MOD_INTR) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	enp->en_mod_flags |= EFX_MOD_INTR;
+
+	eip->ei_type = type;
+	eip->ei_esmp = esmp;
+
+	/*
+	 * bug17213 workaround.
+	 *
+	 * Under legacy interrupts, don't share a level between fatal
+	 * interrupts and event queue interrupts. Under MSI-X, they
+	 * must share, or we won't get an interrupt.
+	 */
+	if (enp->en_family == EFX_FAMILY_SIENA &&
+	    eip->ei_type == EFX_INTR_LINE)
+		eip->ei_level = 0x1f;
+	else
+		eip->ei_level = 0;
+
+	/* Enable all the genuinely fatal interrupts */
+	EFX_SET_OWORD(oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0);
+	if (enp->en_family >= EFX_FAMILY_SIENA)
+		EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword);
+
+	/* Set up the interrupt address register */
+	EFX_POPULATE_OWORD_3(oword,
+	    FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0,
+	    FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff,
+	    FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32);
+	EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+			void
+efx_intr_enable(
+	__in		efx_nic_t *enp)
+{
+	efx_intr_t *eip = &(enp->en_intr);
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+
+	EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
+}
+
+			void
+efx_intr_disable(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+
+	EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
+
+	EFSYS_SPIN(10);
+}
+
+			void
+efx_intr_disable_unlocked(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+
+	EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
+			&oword, B_FALSE);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
+	EFSYS_BAR_WRITEO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
+	    &oword, B_FALSE);
+}
+
+	__checkReturn	int
+efx_intr_trigger(
+	__in		efx_nic_t *enp,
+	__in		unsigned int level)
+{
+	efx_intr_t *eip = &(enp->en_intr);
+	efx_oword_t oword;
+	unsigned int count;
+	uint32_t sel;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+
+	/* bug16757: No event queues can be initialized */
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
+
+	switch (enp->en_family) {
+	case EFX_FAMILY_FALCON:
+		if (level > EFX_NINTR_FALCON) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+
+	case EFX_FAMILY_SIENA:
+		if (level > EFX_NINTR_SIENA) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		break;
+	}
+
+	if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL))
+		return (ENOTSUP); /* avoid EFSYS_PROBE() */
+
+	sel = level;
+
+	/* Trigger a test interrupt */
+	EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
+
+	/*
+	 * Wait up to 100ms for the interrupt to be raised before restoring
+	 * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will
+	 * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL
+	 */
+	count = 0;
+	do {
+		EFSYS_SPIN(100);	/* 100us */
+
+		EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
+	} while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
+	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	boolean_t
+efx_intr_check_fatal(
+	__in		efx_nic_t *enp)
+{
+	efx_intr_t *eip = &(enp->en_intr);
+	efsys_mem_t *esmp = eip->ei_esmp;
+	efx_oword_t oword;
+
+	/* Read the syndrome */
+	EFSYS_MEM_READO(esmp, 0, &oword);
+
+	if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) {
+		EFSYS_PROBE(fatal);
+
+		/* Clear the fatal interrupt condition */
+		EFX_SET_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT, 0);
+		EFSYS_MEM_WRITEO(esmp, 0, &oword);
+
+		return (B_TRUE);
+	}
+
+	return (B_FALSE);
+}
+
+			void
+efx_intr_status_line(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *fatalp,
+	__out		uint32_t *qmaskp)
+{
+	efx_intr_t *eip = &(enp->en_intr);
+	efx_dword_t dword;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+
+	/*
+	 * Read the queue mask and implicitly acknowledge the
+	 * interrupt.
+	 */
+	EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
+	*qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+
+	EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
+
+	if (*qmaskp & (1U << eip->ei_level))
+		*fatalp = efx_intr_check_fatal(enp);
+	else
+		*fatalp = B_FALSE;
+}
+
+			void
+efx_intr_status_message(
+	__in		efx_nic_t *enp,
+	__in		unsigned int message,
+	__out		boolean_t *fatalp)
+{
+	efx_intr_t *eip = &(enp->en_intr);
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+
+	if (message == eip->ei_level)
+		*fatalp = efx_intr_check_fatal(enp);
+	else
+		*fatalp = B_FALSE;
+}
+
+		void
+efx_intr_fatal(
+	__in	efx_nic_t *enp)
+{
+#if EFSYS_OPT_DECODE_INTR_FATAL
+	efx_oword_t fatal;
+	efx_oword_t mem_per;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+
+	EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal);
+	EFX_ZERO_OWORD(mem_per);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0 ||
+	    EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
+		EFX_BAR_READO(enp, FR_AZ_MEM_STAT_REG, &mem_per);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRAM_OOB_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_OOB, 0, 0);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_BUFID_DC_OOB_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_BUFID_DC_OOB, 0, 0);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_MEM_PERR,
+		    EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
+		    EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_RBUF_OWN_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_RBUF_OWN, 0, 0);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_TBUF_OWN_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_TBUF_OWN, 0, 0);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_RDESCQ_OWN_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_RDESQ_OWN, 0, 0);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_TDESCQ_OWN_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_TDESQ_OWN, 0, 0);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVQ_OWN_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_EVQ_OWN, 0, 0);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVF_OFLO_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_EVFF_OFLO, 0, 0);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_ILL_ADR_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_ILL_ADDR, 0, 0);
+
+	if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0)
+		EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_PERR,
+		    EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
+		    EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
+#else
+	EFSYS_ASSERT(0);
+#endif
+}
+
+		void
+efx_intr_fini(
+	__in	efx_nic_t *enp)
+{
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
+
+	/* Clear the interrupt address register */
+	EFX_ZERO_OWORD(oword);
+	EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
+
+	enp->en_mod_flags &= ~EFX_MOD_INTR;
+}
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_mac.c	2013-08-22 18:57:28.062447405 -0400
@@ -0,0 +1,684 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_MAC_FALCON_GMAC
+#include "falcon_gmac.h"
+#endif
+
+#if EFSYS_OPT_MAC_FALCON_XMAC
+#include "falcon_xmac.h"
+#endif
+
+#if EFSYS_OPT_MAC_FALCON_GMAC
+static efx_mac_ops_t	__cs __efx_falcon_gmac_ops = {
+	falcon_gmac_reset,		/* emo_reset */
+	falcon_mac_poll,		/* emo_poll */
+	falcon_mac_up,			/* emo_up */
+	falcon_gmac_reconfigure,	/* emo_reconfigure */
+#if EFSYS_OPT_LOOPBACK
+	falcon_mac_loopback_set,	/* emo_loopback_set */
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_MAC_STATS
+	falcon_mac_stats_upload,	/* emo_stats_upload */
+	NULL,				/* emo_stats_periodic */
+	falcon_gmac_stats_update	/* emo_stats_update */
+#endif	/* EFSYS_OPT_MAC_STATS */
+};
+#endif	/* EFSYS_OPT_MAC_FALCON_GMAC */
+
+#if EFSYS_OPT_MAC_FALCON_XMAC
+static efx_mac_ops_t	__cs __efx_falcon_xmac_ops = {
+	falcon_xmac_reset,		/* emo_reset */
+	falcon_mac_poll,		/* emo_poll */
+	falcon_mac_up,			/* emo_up */
+	falcon_xmac_reconfigure,	/* emo_reconfigure */
+#if EFSYS_OPT_LOOPBACK
+	falcon_mac_loopback_set,	/* emo_loopback_set */
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_MAC_STATS
+	falcon_mac_stats_upload,	/* emo_stats_upload */
+	NULL,				/* emo_stats_periodic */
+	falcon_xmac_stats_update	/* emo_stats_update */
+#endif	/* EFSYS_OPT_MAC_STATS */
+};
+#endif	/* EFSYS_OPT_MAC_FALCON_XMAC */
+
+#if EFSYS_OPT_SIENA
+static efx_mac_ops_t	__cs __efx_siena_mac_ops = {
+	NULL,				/* emo_reset */
+	siena_mac_poll,			/* emo_poll */
+	siena_mac_up,			/* emo_up */
+	siena_mac_reconfigure,		/* emo_reconfigure */
+#if EFSYS_OPT_LOOPBACK
+	siena_mac_loopback_set,		/* emo_loopback_set */
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_MAC_STATS
+	siena_mac_stats_upload,		/* emo_stats_upload */
+	siena_mac_stats_periodic,	/* emo_stats_periodic */
+	siena_mac_stats_update		/* emo_stats_update */
+#endif	/* EFSYS_OPT_MAC_STATS */
+};
+#endif	/* EFSYS_OPT_SIENA */
+
+static efx_mac_ops_t	__cs * __cs __efx_mac_ops[] = {
+	NULL,
+#if EFSYS_OPT_MAC_FALCON_GMAC
+	&__efx_falcon_gmac_ops,
+#else
+	NULL,
+#endif	/* EFSYS_OPT_MAC_FALCON_GMAC */
+#if EFSYS_OPT_MAC_FALCON_XMAC
+	&__efx_falcon_xmac_ops,
+#else
+	NULL,
+#endif	/* EFSYS_OPT_MAC_FALCON_XMAC */
+#if EFSYS_OPT_SIENA
+	&__efx_siena_mac_ops,
+#else
+	NULL,
+#endif	/* EFSYS_OPT_SIENA */
+};
+
+	__checkReturn			int
+efx_mac_pdu_set(
+	__in				efx_nic_t *enp,
+	__in				size_t pdu)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	uint32_t old_pdu;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+	EFSYS_ASSERT(emop != NULL);
+
+	if (pdu < EFX_MAC_PDU_MIN) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (pdu > EFX_MAC_PDU_MAX) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	old_pdu = epp->ep_mac_pdu;
+	epp->ep_mac_pdu = (uint32_t)pdu;
+	if ((rc = emop->emo_reconfigure(enp)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+
+	epp->ep_mac_pdu = old_pdu;
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+efx_mac_addr_set(
+	__in				efx_nic_t *enp,
+	__in				uint8_t *addr)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	uint8_t old_addr[6];
+	uint32_t oui;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	if (addr[0] & 0x01) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	oui = addr[0] << 16 | addr[1] << 8 | addr[2];
+	if (oui == 0x000000) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
+	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
+	if ((rc = emop->emo_reconfigure(enp)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+
+	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+efx_mac_filter_set(
+	__in				efx_nic_t *enp,
+	__in				boolean_t unicst,
+	__in				boolean_t brdcst)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	boolean_t old_unicst;
+	boolean_t old_brdcst;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	old_unicst = unicst;
+	old_brdcst = brdcst;
+
+	epp->ep_unicst = unicst;
+	epp->ep_brdcst = brdcst;
+
+	if ((rc = emop->emo_reconfigure(enp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	epp->ep_unicst = old_unicst;
+	epp->ep_brdcst = old_brdcst;
+
+	return (rc);
+}
+
+	__checkReturn			int
+efx_mac_drain(
+	__in				efx_nic_t *enp,
+	__in				boolean_t enabled)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+	EFSYS_ASSERT(emop != NULL);
+
+	if (epp->ep_mac_drain == enabled)
+		return (0);
+
+	epp->ep_mac_drain = enabled;
+
+	if (enabled && emop->emo_reset != NULL) {
+		if ((rc = emop->emo_reset(enp)) != 0)
+			goto fail1;
+
+		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
+		enp->en_reset_flags &= ~EFX_RESET_PHY;
+	}
+
+	if ((rc = emop->emo_reconfigure(enp)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_mac_up(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *mac_upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	if ((rc = emop->emo_up(enp, mac_upp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+efx_mac_fcntl_set(
+	__in				efx_nic_t *enp,
+	__in				unsigned int fcntl,
+	__in				boolean_t autoneg)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	efx_phy_ops_t *epop = epp->ep_epop;
+	unsigned int old_fcntl;
+	boolean_t old_autoneg;
+	unsigned int old_adv_cap;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	/*
+	 * Ignore a request to set flow control autonegotiation
+	 * if the PHY doesn't support it.
+	 */
+	if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
+		autoneg = B_FALSE;
+
+	old_fcntl = epp->ep_fcntl;
+	old_autoneg = autoneg;
+	old_adv_cap = epp->ep_adv_cap_mask;
+
+	epp->ep_fcntl = fcntl;
+	epp->ep_fcntl_autoneg = autoneg;
+
+	/*
+	 * If the PHY supports autonegotiation, then encode the flow control
+	 * settings in the advertised capabilities, and restart AN. Otherwise,
+	 * just push the new settings directly to the MAC.
+	 */
+	if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) {
+		if (fcntl & EFX_FCNTL_RESPOND)
+			epp->ep_adv_cap_mask |=    (1 << EFX_PHY_CAP_PAUSE |
+						    1 << EFX_PHY_CAP_ASYM);
+		else
+			epp->ep_adv_cap_mask &=   ~(1 << EFX_PHY_CAP_PAUSE |
+						    1 << EFX_PHY_CAP_ASYM);
+
+		if (fcntl & EFX_FCNTL_GENERATE)
+			epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
+
+		if ((rc = epop->epo_reconfigure(enp)) != 0)
+			goto fail2;
+
+	} else {
+		if ((rc = emop->emo_reconfigure(enp)) != 0)
+			goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+
+	epp->ep_fcntl = old_fcntl;
+	epp->ep_fcntl_autoneg = old_autoneg;
+	epp->ep_adv_cap_mask = old_adv_cap;
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+			void
+efx_mac_fcntl_get(
+	__in		efx_nic_t *enp,
+	__out		unsigned int *fcntl_wantedp,
+	__out		unsigned int *fcntl_linkp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	unsigned int wanted;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	/*
+	 * If the PHY supports auto negotiation, then the requested flow
+	 * control settings are encoded in the advertised capabilities.
+	 */
+	if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) {
+		wanted = 0;
+
+		if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
+			wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
+		if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
+			wanted ^= EFX_FCNTL_GENERATE;
+	} else
+		wanted = epp->ep_fcntl;
+
+	*fcntl_linkp = epp->ep_fcntl;
+	*fcntl_wantedp = wanted;
+}
+
+	__checkReturn			int
+efx_mac_hash_set(
+	__in				efx_nic_t *enp,
+	__in_ecount(EFX_MAC_HASH_BITS)	unsigned int const *bucket)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	efx_oword_t old_hash[2];
+	unsigned int index;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
+
+	/* Set the lower 128 bits of the hash */
+	EFX_ZERO_OWORD(epp->ep_multicst_hash[0]);
+	for (index = 0; index < 128; index++) {
+		if (bucket[index] != 0)
+			EFX_SET_OWORD_BIT(epp->ep_multicst_hash[0], index);
+	}
+
+	/* Set the upper 128 bits of the hash */
+	EFX_ZERO_OWORD(epp->ep_multicst_hash[1]);
+	for (index = 0; index < 128; index++) {
+		if (bucket[index + 128] != 0)
+			EFX_SET_OWORD_BIT(epp->ep_multicst_hash[1], index);
+	}
+
+	if ((rc = emop->emo_reconfigure(enp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
+
+	return (rc);
+}
+
+#if EFSYS_OPT_MAC_STATS
+
+#if EFSYS_OPT_NAMES
+
+/* START MKCONFIG GENERATED EfxMacStatNamesBlock adf707adba80813e */
+static const char 	__cs * __cs __efx_mac_stat_name[] = {
+	"rx_octets",
+	"rx_pkts",
+	"rx_unicst_pkts",
+	"rx_multicst_pkts",
+	"rx_brdcst_pkts",
+	"rx_pause_pkts",
+	"rx_le_64_pkts",
+	"rx_65_to_127_pkts",
+	"rx_128_to_255_pkts",
+	"rx_256_to_511_pkts",
+	"rx_512_to_1023_pkts",
+	"rx_1024_to_15xx_pkts",
+	"rx_ge_15xx_pkts",
+	"rx_errors",
+	"rx_fcs_errors",
+	"rx_drop_events",
+	"rx_false_carrier_errors",
+	"rx_symbol_errors",
+	"rx_align_errors",
+	"rx_internal_errors",
+	"rx_jabber_pkts",
+	"rx_lane0_char_err",
+	"rx_lane1_char_err",
+	"rx_lane2_char_err",
+	"rx_lane3_char_err",
+	"rx_lane0_disp_err",
+	"rx_lane1_disp_err",
+	"rx_lane2_disp_err",
+	"rx_lane3_disp_err",
+	"rx_match_fault",
+	"rx_nodesc_drop_cnt",
+	"tx_octets",
+	"tx_pkts",
+	"tx_unicst_pkts",
+	"tx_multicst_pkts",
+	"tx_brdcst_pkts",
+	"tx_pause_pkts",
+	"tx_le_64_pkts",
+	"tx_65_to_127_pkts",
+	"tx_128_to_255_pkts",
+	"tx_256_to_511_pkts",
+	"tx_512_to_1023_pkts",
+	"tx_1024_to_15xx_pkts",
+	"tx_ge_15xx_pkts",
+	"tx_errors",
+	"tx_sgl_col_pkts",
+	"tx_mult_col_pkts",
+	"tx_ex_col_pkts",
+	"tx_late_col_pkts",
+	"tx_def_pkts",
+	"tx_ex_def_pkts",
+};
+/* END MKCONFIG GENERATED EfxMacStatNamesBlock */
+
+	__checkReturn			const char __cs *
+efx_mac_stat_name(
+	__in				efx_nic_t *enp,
+	__in				unsigned int id)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+
+	EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
+	return (__efx_mac_stat_name[id]);
+}
+
+#endif	/* EFSYS_OPT_STAT_NAME */
+
+	__checkReturn			int
+efx_mac_stats_upload(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+	EFSYS_ASSERT(emop != NULL);
+
+	/*
+	 * Don't assert !ep_mac_stats_pending, because the client might
+	 * have failed to finalise statistics when previously stopping
+	 * the port.
+	 */
+	if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
+		goto fail1;
+
+	epp->ep_mac_stats_pending = B_TRUE;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+efx_mac_stats_periodic(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__in				uint16_t period_ms,
+	__in				boolean_t events)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	EFSYS_ASSERT(emop != NULL);
+
+	if (emop->emo_stats_periodic == NULL) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+	__checkReturn			int
+efx_mac_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *essp,
+	__in				uint32_t *generationp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+	EFSYS_ASSERT(emop != NULL);
+
+	rc = emop->emo_stats_update(enp, esmp, essp, generationp);
+	if (rc == 0)
+		epp->ep_mac_stats_pending = B_FALSE;
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+	__checkReturn			int
+efx_mac_select(
+	__in				efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_type_t type = EFX_MAC_INVALID;
+	efx_mac_ops_t *emop;
+	int rc = EINVAL;
+
+#if EFSYS_OPT_SIENA
+	if (enp->en_family == EFX_FAMILY_SIENA) {
+		type = EFX_MAC_SIENA;
+		goto chosen;
+	}
+#endif
+
+#if EFSYS_OPT_FALCON
+	switch (epp->ep_link_mode) {
+#if EFSYS_OPT_MAC_FALCON_GMAC
+	case EFX_LINK_100HDX:
+	case EFX_LINK_100FDX:
+	case EFX_LINK_1000HDX:
+	case EFX_LINK_1000FDX:
+		type = EFX_MAC_FALCON_GMAC;
+		goto chosen;
+#endif	/* EFSYS_OPT_FALCON_GMAC */
+
+#if EFSYS_OPT_MAC_FALCON_XMAC
+	case EFX_LINK_10000FDX:
+		type = EFX_MAC_FALCON_XMAC;
+		goto chosen;
+#endif	/* EFSYS_OPT_FALCON_XMAC */
+
+	default:
+#if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC
+		/* Only initialise a MAC supported by the PHY */
+		if (epp->ep_phy_cap_mask &
+		    ((1 << EFX_PHY_CAP_1000FDX) |
+		    (1 << EFX_PHY_CAP_1000HDX) |
+		    (1 << EFX_PHY_CAP_100FDX) |
+		    (1 << EFX_PHY_CAP_100HDX) |
+		    (1 << EFX_PHY_CAP_10FDX) |
+		    (1 << EFX_PHY_CAP_10FDX)))
+			type = EFX_MAC_FALCON_GMAC;
+		else
+			type = EFX_MAC_FALCON_XMAC;
+#elif EFSYS_OPT_MAC_FALCON_GMAC
+		type = EFX_MAC_FALCON_GMAC;
+#else
+		type = EFX_MAC_FALCON_XMAC;
+#endif
+		goto chosen;
+	}
+#endif	/* EFSYS_OPT_FALCON */
+
+chosen:
+	EFSYS_ASSERT(type != EFX_MAC_INVALID);
+	EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
+	emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type];
+	EFSYS_ASSERT(emop != NULL);
+
+	epp->ep_mac_type = type;
+
+	if (emop->emo_reset != NULL) {
+		if ((rc = emop->emo_reset(enp)) != 0)
+			goto fail1;
+
+		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
+		enp->en_reset_flags &= ~EFX_RESET_MAC;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_mcdi.c	2013-08-22 18:57:28.153305276 -0400
@@ -0,0 +1,740 @@
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_regs_mcdi.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_MCDI
+
+/*
+ * A reboot/assertion causes the MCDI status word to be set after the
+ * command word is set or a REBOOT event is sent. If we notice a reboot
+ * via these mechanisms then wait 10ms for the status word to be set.
+ */
+#define	MCDI_STATUS_SLEEP_US	10000
+
+			void
+efx_mcdi_request_start(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp,
+	__in		boolean_t ev_cpl)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	efx_dword_t dword;
+	unsigned int seq;
+	unsigned int xflags;
+	unsigned int pdur;
+	unsigned int dbr;
+	unsigned int pos;
+	int state;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
+	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
+
+	switch (emip->emi_port)	{
+	case 1:
+		pdur = MC_SMEM_P0_PDU_OFST >> 2;
+		dbr = MC_SMEM_P0_DOORBELL_OFST >> 2;
+		break;
+	case 2:
+		pdur = MC_SMEM_P1_PDU_OFST >> 2;
+		dbr = MC_SMEM_P1_DOORBELL_OFST >> 2;
+		break;
+	default:
+		EFSYS_ASSERT(0);
+		pdur = dbr = 0;
+	};
+
+	/*
+	 * efx_mcdi_request_start() is naturally serialised against both
+	 * efx_mcdi_request_poll() and efx_mcdi_ev_cpl()/efx_mcdi_ev_death(),
+	 * by virtue of there only being one oustanding MCDI request.
+	 * Unfortunately, upper layers may also call efx_mcdi_request_abort()
+	 * at any time, to timeout a pending mcdi request, That request may
+	 * then subsequently complete, meaning efx_mcdi_ev_cpl() or
+	 * efx_mcdi_ev_death() may end up running in parallel with
+	 * efx_mcdi_request_start(). This race is handled by ensuring that
+	 * %emi_pending_req, %emi_ev_cpl and %emi_seq are protected by the
+	 * en_eslp lock.
+	 */
+	EFSYS_LOCK(enp->en_eslp, state);
+	EFSYS_ASSERT(emip->emi_pending_req == NULL);
+	emip->emi_pending_req = emrp;
+	emip->emi_ev_cpl = ev_cpl;
+	emip->emi_poll_cnt = 0;
+	seq = emip->emi_seq++ & 0xf;
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	xflags = 0;
+	if (ev_cpl)
+		xflags |= MCDI_HEADER_XFLAGS_EVREQ;
+
+	/* Construct the header in shared memory */
+	EFX_POPULATE_DWORD_6(dword,
+			    MCDI_HEADER_CODE, emrp->emr_cmd,
+			    MCDI_HEADER_RESYNC, 1,
+			    MCDI_HEADER_DATALEN, emrp->emr_in_length,
+			    MCDI_HEADER_SEQ, seq,
+			    MCDI_HEADER_RESPONSE, 0,
+			    MCDI_HEADER_XFLAGS, xflags);
+	EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, pdur, &dword, B_TRUE);
+
+	for (pos = 0; pos < emrp->emr_in_length; pos += sizeof (efx_dword_t)) {
+		memcpy(&dword, MCDI_IN(*emrp, efx_dword_t, pos),
+		    MIN(sizeof (dword), emrp->emr_in_length - pos));
+		EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM,
+		    pdur + 1 + (pos >> 2), &dword, B_FALSE);
+	}
+
+	/* Ring the doorbell */
+	EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 0xd004be11);
+	EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, dbr, &dword, B_FALSE);
+}
+
+static			void
+efx_mcdi_request_copyout(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	unsigned int pos;
+	unsigned int pdur;
+	efx_dword_t data;
+
+	pdur = (emip->emi_port == 1)
+	    ? MC_SMEM_P0_PDU_OFST >> 2
+	    : MC_SMEM_P1_PDU_OFST >> 2;
+
+	/* Copy payload out if caller supplied buffer */
+	if (emrp->emr_out_buf != NULL) {
+		size_t bytes = MIN(emrp->emr_out_length_used,
+				    emrp->emr_out_length);
+		for (pos = 0; pos < bytes; pos += sizeof (efx_dword_t)) {
+			EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM,
+			    pdur + 1 + (pos >> 2), &data, B_FALSE);
+			memcpy(MCDI_OUT(*emrp, efx_dword_t, pos), &data,
+			    MIN(sizeof (data), bytes - pos));
+		}
+	}
+}
+
+static			int
+efx_mcdi_request_errcode(
+	__in		unsigned int err)
+{
+
+	switch (err) {
+	case MC_CMD_ERR_ENOENT:
+		return (ENOENT);
+	case MC_CMD_ERR_EINTR:
+		return (EINTR);
+	case MC_CMD_ERR_EACCES:
+		return (EACCES);
+	case MC_CMD_ERR_EBUSY:
+		return (EBUSY);
+	case MC_CMD_ERR_EINVAL:
+		return (EINVAL);
+	case MC_CMD_ERR_EDEADLK:
+		return (EDEADLK);
+	case MC_CMD_ERR_ENOSYS:
+		return (ENOTSUP);
+	case MC_CMD_ERR_ETIME:
+		return (ETIMEDOUT);
+#ifdef WITH_MCDI_V2
+	case MC_CMD_ERR_EAGAIN:
+		return (EAGAIN);
+	case MC_CMD_ERR_ENOSPC:
+		return (ENOSPC);
+#endif
+	default:
+		EFSYS_PROBE1(mc_pcol_error, int, err);
+		return (EIO);
+	}
+}
+
+static			void
+efx_mcdi_raise_exception(
+	__in		efx_nic_t *enp,
+	__in_opt	efx_mcdi_req_t *emrp,
+	__in		int rc)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	const efx_mcdi_transport_t *emtp = emip->emi_mtp;
+	efx_mcdi_exception_t exception;
+
+	/* Reboot or Assertion failure only */
+	EFSYS_ASSERT(rc == EIO || rc == EINTR);
+
+	/*
+	 * If MC_CMD_REBOOT causes a reboot (dependent on parameters),
+	 * then the EIO is not worthy of an exception.
+	 */
+	if (emrp != NULL && emrp->emr_cmd == MC_CMD_REBOOT && rc == EIO)
+		return;
+
+	exception = (rc == EIO)
+		? EFX_MCDI_EXCEPTION_MC_REBOOT
+		: EFX_MCDI_EXCEPTION_MC_BADASSERT;
+
+	emtp->emt_exception(emtp->emt_context, exception);
+}
+
+static			int
+efx_mcdi_poll_reboot(
+	__in		efx_nic_t *enp)
+{
+#if 1
+	/*
+	 * XXX Bug 25922, bug 26099: This function is not being used
+	 * properly.  Until its callers are fixed, it should always
+	 * return 0.
+	 */
+	_NOTE(ARGUNUSED(enp))
+	return (0);
+#else
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	unsigned int rebootr;
+	efx_dword_t dword;
+	uint32_t value;
+
+	EFSYS_ASSERT(emip->emi_port == 1 || emip->emi_port == 2);
+	rebootr = ((emip->emi_port == 1)
+	    ? MC_SMEM_P0_STATUS_OFST >> 2
+	    : MC_SMEM_P1_STATUS_OFST >> 2);
+
+	EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, rebootr, &dword, B_FALSE);
+	value = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+
+	if (value == 0)
+		return (0);
+
+	EFX_ZERO_DWORD(dword);
+	EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, rebootr, &dword, B_FALSE);
+
+	if (value == MC_STATUS_DWORD_ASSERT)
+		return (EINTR);
+	else
+		return (EIO);
+#endif
+}
+
+	__checkReturn	boolean_t
+efx_mcdi_request_poll(
+	__in		efx_nic_t *enp)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	efx_mcdi_req_t *emrp;
+	efx_dword_t dword;
+	unsigned int pdur;
+	unsigned int seq;
+	unsigned int length;
+	int state;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
+
+	/* Serialise against post-watchdog efx_mcdi_ev* */
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	EFSYS_ASSERT(emip->emi_pending_req != NULL);
+	EFSYS_ASSERT(!emip->emi_ev_cpl);
+	emrp = emip->emi_pending_req;
+
+	/* Check for reboot atomically w.r.t efx_mcdi_request_start */
+	if (emip->emi_poll_cnt++ == 0) {
+		if ((rc = efx_mcdi_poll_reboot(enp)) != 0) {
+			emip->emi_pending_req = NULL;
+			EFSYS_UNLOCK(enp->en_eslp, state);
+
+			goto fail1;
+		}
+	}
+
+	EFSYS_ASSERT(emip->emi_port == 1 || emip->emi_port == 2);
+	pdur = (emip->emi_port == 1)
+	    ? MC_SMEM_P0_PDU_OFST >> 2
+	    : MC_SMEM_P1_PDU_OFST >> 2;
+
+	/* Read the command header */
+	EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, pdur, &dword, B_FALSE);
+	if (EFX_DWORD_FIELD(dword, MCDI_HEADER_RESPONSE) == 0) {
+		EFSYS_UNLOCK(enp->en_eslp, state);
+		return (B_FALSE);
+	}
+
+	/* Request complete */
+	emip->emi_pending_req = NULL;
+	seq = (emip->emi_seq - 1) & 0xf;
+
+	/* Check for synchronous reboot */
+	if (EFX_DWORD_FIELD(dword, MCDI_HEADER_ERROR) != 0 &&
+	    EFX_DWORD_FIELD(dword, MCDI_HEADER_DATALEN) == 0) {
+		/* Consume status word */
+		EFSYS_SPIN(MCDI_STATUS_SLEEP_US);
+		efx_mcdi_poll_reboot(enp);
+		EFSYS_UNLOCK(enp->en_eslp, state);
+		rc = EIO;
+		goto fail2;
+	}
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	/* Check that the returned data is consistent */
+	if (EFX_DWORD_FIELD(dword, MCDI_HEADER_CODE) != emrp->emr_cmd ||
+	    EFX_DWORD_FIELD(dword, MCDI_HEADER_SEQ) != seq) {
+		/* Response is for a different request */
+		rc = EIO;
+		goto fail3;
+	}
+
+	length = EFX_DWORD_FIELD(dword, MCDI_HEADER_DATALEN);
+	if (EFX_DWORD_FIELD(dword, MCDI_HEADER_ERROR)) {
+		efx_dword_t errdword;
+		int errcode;
+
+		EFSYS_ASSERT3U(length, ==, 4);
+		EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM,
+		    pdur + 1 + (MC_CMD_ERR_CODE_OFST >> 2),
+		    &errdword, B_FALSE);
+		errcode = EFX_DWORD_FIELD(errdword, EFX_DWORD_0);
+		rc = efx_mcdi_request_errcode(errcode);
+		EFSYS_PROBE2(mcdi_err, int, emrp->emr_cmd, int, errcode);
+		goto fail4;
+
+	} else {
+		emrp->emr_out_length_used = length;
+		emrp->emr_rc = 0;
+		efx_mcdi_request_copyout(enp, emrp);
+	}
+
+	goto out;
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	/* Fill out error state */
+	emrp->emr_rc = rc;
+	emrp->emr_out_length_used = 0;
+
+	/* Reboot/Assertion */
+	if (rc == EIO || rc == EINTR)
+		efx_mcdi_raise_exception(enp, emrp, rc);
+
+out:
+	return (B_TRUE);
+}
+
+			void
+efx_mcdi_execute(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	const efx_mcdi_transport_t *emtp = emip->emi_mtp;
+
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
+
+	emtp->emt_execute(emtp->emt_context, emrp);
+}
+
+			void
+efx_mcdi_ev_cpl(
+	__in		efx_nic_t *enp,
+	__in		unsigned int seq,
+	__in		unsigned int outlen,
+	__in		int errcode)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	const efx_mcdi_transport_t *emtp = emip->emi_mtp;
+	efx_mcdi_req_t *emrp;
+	int state;
+
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
+
+	/*
+	 * Serialise against efx_mcdi_request_poll()/efx_mcdi_request_start()
+	 * when we're completing an aborted request.
+	 */
+	EFSYS_LOCK(enp->en_eslp, state);
+	if (emip->emi_pending_req == NULL || !emip->emi_ev_cpl ||
+	    (seq != ((emip->emi_seq - 1) & 0xf))) {
+		EFSYS_ASSERT(emip->emi_aborted > 0);
+		if (emip->emi_aborted > 0)
+			--emip->emi_aborted;
+		EFSYS_UNLOCK(enp->en_eslp, state);
+		return;
+	}
+
+	emrp = emip->emi_pending_req;
+	emip->emi_pending_req = NULL;
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	/*
+	 * Fill out the remaining hdr fields, and copyout the payload
+	 * if the user supplied an output buffer.
+	 */
+	if (errcode != 0) {
+		EFSYS_PROBE2(mcdi_err, int, emrp->emr_cmd,
+		    int, errcode);
+		emrp->emr_out_length_used = 0;
+		emrp->emr_rc = efx_mcdi_request_errcode(errcode);
+	} else {
+		emrp->emr_out_length_used = outlen;
+		emrp->emr_rc = 0;
+		efx_mcdi_request_copyout(enp, emrp);
+	}
+
+	emtp->emt_ev_cpl(emtp->emt_context);
+}
+
+			void
+efx_mcdi_ev_death(
+	__in		efx_nic_t *enp,
+	__in		int rc)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	const efx_mcdi_transport_t *emtp = emip->emi_mtp;
+	efx_mcdi_req_t *emrp = NULL;
+	boolean_t ev_cpl;
+	int state;
+
+	/*
+	 * The MCDI request (if there is one) has been terminated, either
+	 * by a BADASSERT or REBOOT event.
+	 *
+	 * If there is an oustanding event-completed MCDI operation, then we
+	 * will never receive the completion event (because both MCDI
+	 * completions and BADASSERT events are sent to the same evq). So
+	 * complete this MCDI op.
+	 *
+	 * This function might run in parallel with efx_mcdi_request_poll()
+	 * for poll completed mcdi requests, and also with
+	 * efx_mcdi_request_start() for post-watchdog completions.
+	 */
+	EFSYS_LOCK(enp->en_eslp, state);
+	emrp = emip->emi_pending_req;
+	ev_cpl = emip->emi_ev_cpl;
+	if (emrp != NULL && emip->emi_ev_cpl) {
+		emip->emi_pending_req = NULL;
+
+		emrp->emr_out_length_used = 0;
+		emrp->emr_rc = rc;
+		++emip->emi_aborted;
+	}
+
+	/*
+	 * Since we're running in parallel with a request, consume the
+	 * status word before dropping the lock.
+	 */
+	if (rc == EIO || rc == EINTR) {
+		EFSYS_SPIN(MCDI_STATUS_SLEEP_US);
+		(void) efx_mcdi_poll_reboot(enp);
+	}
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	efx_mcdi_raise_exception(enp, emrp, rc);
+
+	if (emrp != NULL && ev_cpl)
+		emtp->emt_ev_cpl(emtp->emt_context);
+}
+
+	__checkReturn		int
+efx_mcdi_version(
+	__in			efx_nic_t *enp,
+	__out_ecount_opt(4)	uint16_t versionp[4],
+	__out_opt		uint32_t *buildp,
+	__out_opt		efx_mcdi_boot_t *statusp)
+{
+	uint8_t outbuf[MAX(MC_CMD_GET_VERSION_OUT_LEN,
+		    MC_CMD_GET_BOOT_STATUS_OUT_LEN)];
+	efx_mcdi_req_t req;
+	efx_word_t *ver_words;
+	uint16_t version[4];
+	uint32_t build;
+	efx_mcdi_boot_t status;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
+
+	EFX_STATIC_ASSERT(MC_CMD_GET_VERSION_IN_LEN == 0);
+	req.emr_cmd = MC_CMD_GET_VERSION;
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = MC_CMD_GET_VERSION_OUT_LEN;
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	/* bootrom support */
+	if (req.emr_out_length_used == MC_CMD_GET_VERSION_V0_OUT_LEN) {
+		version[0] = version[1] = version[2] = version[3] = 0;
+		build = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE);
+
+		goto version;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_GET_VERSION_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	ver_words = MCDI_OUT2(req, efx_word_t, GET_VERSION_OUT_VERSION);
+	version[0] = EFX_WORD_FIELD(ver_words[0], EFX_WORD_0);
+	version[1] = EFX_WORD_FIELD(ver_words[1], EFX_WORD_0);
+	version[2] = EFX_WORD_FIELD(ver_words[2], EFX_WORD_0);
+	version[3] = EFX_WORD_FIELD(ver_words[3], EFX_WORD_0);
+	build = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE);
+
+version:
+	/* The bootrom doesn't understand BOOT_STATUS */
+	if (build == MC_CMD_GET_VERSION_OUT_FIRMWARE_BOOTROM) {
+		status = EFX_MCDI_BOOT_ROM;
+		goto out;
+	}
+
+	req.emr_cmd = MC_CMD_GET_BOOT_STATUS;
+	EFX_STATIC_ASSERT(MC_CMD_GET_BOOT_STATUS_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = MC_CMD_GET_BOOT_STATUS_OUT_LEN;
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_GET_BOOT_STATUS_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	if (MCDI_OUT_DWORD_FIELD(req, GET_BOOT_STATUS_OUT_FLAGS,
+	    GET_BOOT_STATUS_OUT_FLAGS_PRIMARY))
+		status = EFX_MCDI_BOOT_PRIMARY;
+	else
+		status = EFX_MCDI_BOOT_SECONDARY;
+
+out:
+	if (versionp != NULL)
+		memcpy(versionp, version, sizeof (version));
+	if (buildp != NULL)
+		*buildp = build;
+	if (statusp != NULL)
+		*statusp = status;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_mcdi_init(
+	__in		efx_nic_t *enp,
+	__in		const efx_mcdi_transport_t *mtp)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	efx_oword_t oword;
+	unsigned int portnum;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
+	enp->en_mod_flags |= EFX_MOD_MCDI;
+
+	if (enp->en_family == EFX_FAMILY_FALCON)
+		return (0);
+
+	emip->emi_mtp = mtp;
+
+	/* Determine the port number to use for MCDI */
+	EFX_BAR_READO(enp, FR_AZ_CS_DEBUG_REG, &oword);
+	portnum = EFX_OWORD_FIELD(oword, FRF_CZ_CS_PORT_NUM);
+
+	if (portnum == 0) {
+		/* Presumably booted from ROM; only MCDI port 1 will work */
+		emip->emi_port = 1;
+	} else if (portnum <= 2) {
+		emip->emi_port = portnum;
+	} else {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	/*
+	 * Wipe the atomic reboot status so subsequent MCDI requests succeed.
+	 * BOOT_STATUS is preserved so eno_nic_probe() can boot out of the
+	 * assertion handler.
+	 */
+	(void) efx_mcdi_poll_reboot(enp);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	enp->en_mod_flags &= ~EFX_MOD_MCDI;
+
+	return (rc);
+}
+
+
+	__checkReturn	int
+efx_mcdi_reboot(
+	__in		efx_nic_t *enp)
+{
+	uint8_t payload[MC_CMD_REBOOT_IN_LEN];
+	efx_mcdi_req_t req;
+	int rc;
+
+	/*
+	 * We could require the caller to have caused en_mod_flags=0 to
+	 * call this function. This doesn't help the other port though,
+	 * who's about to get the MC ripped out from underneath them.
+	 * Since they have to cope with the subsequent fallout of MCDI
+	 * failures, we should as well.
+	 */
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+
+	req.emr_cmd = MC_CMD_REBOOT;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_REBOOT_IN_LEN;
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS, 0);
+
+	efx_mcdi_execute(enp, &req);
+
+	/* Invert EIO */
+	if (req.emr_rc != EIO) {
+		rc = EIO;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	boolean_t
+efx_mcdi_request_abort(
+	__in		efx_nic_t *enp)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	efx_mcdi_req_t *emrp;
+	boolean_t aborted;
+	int state;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
+
+	/*
+	 * efx_mcdi_ev_* may have already completed this event, and be
+	 * spinning/blocked on the upper layer lock. So it *is* legitimate
+	 * to for emi_pending_req to be NULL. If there is a pending event
+	 * completed request, then provide a "credit" to allow
+	 * efx_mcdi_ev_cpl() to accept a single spurious completion.
+	 */
+	EFSYS_LOCK(enp->en_eslp, state);
+	emrp = emip->emi_pending_req;
+	aborted = (emrp != NULL);
+	if (aborted) {
+		emip->emi_pending_req = NULL;
+
+		/* Error the request */
+		emrp->emr_out_length_used = 0;
+		emrp->emr_rc = ETIMEDOUT;
+
+		/* Provide a credit for seqno/emr_pending_req mismatches */
+		if (emip->emi_ev_cpl)
+			++emip->emi_aborted;
+
+		/*
+		 * The upper layer has called us, so we don't
+		 * need to complete the request.
+		 */
+	}
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	return (aborted);
+}
+
+			void
+efx_mcdi_fini(
+	__in		efx_nic_t *enp)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+
+	EFSYS_ASSERT3U(enp->en_mod_flags, ==, EFX_MOD_MCDI);
+	enp->en_mod_flags &= ~EFX_MOD_MCDI;
+
+	if (~(enp->en_features) & EFX_FEATURE_MCDI)
+		return;
+
+	emip->emi_mtp = NULL;
+	emip->emi_port = 0;
+	emip->emi_aborted = 0;
+}
+
+#endif	/* EFSYS_OPT_MCDI */
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_mcdi.h	2013-08-22 18:57:28.244916752 -0400
@@ -0,0 +1,241 @@
+/*-
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_EFX_MCDI_H
+#define	_SYS_EFX_MCDI_H
+
+#include "efx.h"
+#include "efx_regs.h"
+#include "efx_regs_mcdi.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* Number of retries attempted for init code */
+#define	EFX_MCDI_REQ_RETRY_INIT 2
+
+struct efx_mcdi_req_s {
+	/* Inputs: Command #, input buffer and length */
+	unsigned int	emr_cmd;
+	uint8_t		*emr_in_buf;
+	size_t		emr_in_length;
+	/* Outputs: retcode, buffer, length, and length used*/
+	int		emr_rc;
+	uint8_t		*emr_out_buf;
+	size_t		emr_out_length;
+	size_t		emr_out_length_used;
+};
+
+typedef struct efx_mcdi_iface_s {
+	const efx_mcdi_transport_t *emi_mtp;
+	unsigned int		emi_port;
+	unsigned int		emi_seq;
+	efx_mcdi_req_t		*emi_pending_req;
+	boolean_t		emi_ev_cpl;
+	int			emi_aborted;
+	uint32_t		emi_poll_cnt;
+} efx_mcdi_iface_t;
+
+extern			void
+efx_mcdi_execute(
+	__in		efx_nic_t *enp,
+	__in		efx_mcdi_req_t *emrp);
+
+extern			void
+efx_mcdi_ev_cpl(
+	__in		efx_nic_t *enp,
+	__in		unsigned int seq,
+	__in		unsigned int outlen,
+	__in		int errcode);
+
+extern			void
+efx_mcdi_ev_death(
+	__in		efx_nic_t *enp,
+	__in		int rc);
+
+typedef enum efx_mcdi_boot_e {
+	EFX_MCDI_BOOT_PRIMARY,
+	EFX_MCDI_BOOT_SECONDARY,
+	EFX_MCDI_BOOT_ROM,
+} efx_mcdi_boot_t;
+
+extern	__checkReturn		int
+efx_mcdi_version(
+	__in			efx_nic_t *enp,
+	__out_ecount_opt(4)	uint16_t versionp[4],
+	__out_opt		uint32_t *buildp,
+	__out_opt		efx_mcdi_boot_t *statusp);
+
+#define	MCDI_IN(_emr, _type, _ofst)					\
+	((_type *)((_emr).emr_in_buf + (_ofst)))
+
+#define	MCDI_IN2(_emr, _type, _ofst)					\
+	MCDI_IN(_emr, _type, MC_CMD_ ## _ofst ## _OFST)
+
+#define	MCDI_IN_SET_BYTE(_emr, _ofst, _value)				\
+	EFX_POPULATE_BYTE_1(*MCDI_IN2(_emr, efx_byte_t, _ofst),		\
+		EFX_BYTE_0, _value)
+
+#define	MCDI_IN_SET_DWORD(_emr, _ofst, _value)				\
+	EFX_POPULATE_DWORD_1(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		EFX_DWORD_0, _value)
+
+#define	MCDI_IN_POPULATE_DWORD_1(_emr, _ofst, _field1, _value1)		\
+	EFX_POPULATE_DWORD_1(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1)
+
+#define	MCDI_IN_POPULATE_DWORD_2(_emr, _ofst, _field1, _value1,		\
+		_field2, _value2)					\
+	EFX_POPULATE_DWORD_2(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2)
+
+#define	MCDI_IN_POPULATE_DWORD_3(_emr, _ofst, _field1, _value1,		\
+		_field2, _value2, _field3, _value3)			\
+	EFX_POPULATE_DWORD_3(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2,				\
+		MC_CMD_ ## _field3, _value3)
+
+#define	MCDI_IN_POPULATE_DWORD_4(_emr, _ofst, _field1, _value1,		\
+		_field2, _value2, _field3, _value3, _field4, _value4)	\
+	EFX_POPULATE_DWORD_4(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2,				\
+		MC_CMD_ ## _field3, _value3,				\
+		MC_CMD_ ## _field4, _value4)
+
+#define	MCDI_IN_POPULATE_DWORD_5(_emr, _ofst, _field1, _value1,		\
+		_field2, _value2, _field3, _value3, _field4, _value4,	\
+		_field5, _value5)					\
+	EFX_POPULATE_DWORD_5(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2,				\
+		MC_CMD_ ## _field3, _value3,				\
+		MC_CMD_ ## _field4, _value4,				\
+		MC_CMD_ ## _field5, _value5)
+
+#define	MCDI_IN_POPULATE_DWORD_6(_emr, _ofst, _field1, _value1,		\
+		_field2, _value2, _field3, _value3, _field4, _value4,	\
+		_field5, _value5, _field6, _value6)			\
+	EFX_POPULATE_DWORD_6(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2,				\
+		MC_CMD_ ## _field3, _value3,				\
+		MC_CMD_ ## _field4, _value4,				\
+		MC_CMD_ ## _field5, _value5,				\
+		MC_CMD_ ## _field6, _value6)
+
+#define	MCDI_IN_POPULATE_DWORD_7(_emr, _ofst, _field1, _value1,		\
+		_field2, _value2, _field3, _value3, _field4, _value4,	\
+		_field5, _value5, _field6, _value6, _field7, _value7)	\
+	EFX_POPULATE_DWORD_7(MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2,				\
+		MC_CMD_ ## _field3, _value3,				\
+		MC_CMD_ ## _field4, _value4,				\
+		MC_CMD_ ## _field5, _value5,				\
+		MC_CMD_ ## _field6, _value6,				\
+		MC_CMD_ ## _field7, _value7)
+
+#define	MCDI_IN_POPULATE_DWORD_8(_emr, _ofst, _field1, _value1,		\
+		_field2, _value2, _field3, _value3, _field4, _value4,	\
+		_field5, _value5, _field6, _value6, _field7, _value7,	\
+		_field8, _value8)					\
+	EFX_POPULATE_DWORD_8(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2,				\
+		MC_CMD_ ## _field3, _value3,				\
+		MC_CMD_ ## _field4, _value4,				\
+		MC_CMD_ ## _field5, _value5,				\
+		MC_CMD_ ## _field6, _value6,				\
+		MC_CMD_ ## _field7, _value7,				\
+		MC_CMD_ ## _field8, _value8)
+
+#define	MCDI_IN_POPULATE_DWORD_9(_emr, _ofst, _field1, _value1,		\
+		_field2, _value2, _field3, _value3, _field4, _value4,	\
+		_field5, _value5, _field6, _value6, _field7, _value7,	\
+		_field8, _value8, _field9, _value9)			\
+	EFX_POPULATE_DWORD_9(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2,				\
+		MC_CMD_ ## _field3, _value3,				\
+		MC_CMD_ ## _field4, _value4,				\
+		MC_CMD_ ## _field5, _value5,				\
+		MC_CMD_ ## _field6, _value6,				\
+		MC_CMD_ ## _field7, _value7,				\
+		MC_CMD_ ## _field8, _value8,				\
+		MC_CMD_ ## _field9, _value9)
+
+#define	MCDI_IN_POPULATE_DWORD_10(_emr, _ofst, _field1, _value1,	\
+		_field2, _value2, _field3, _value3, _field4, _value4,	\
+		_field5, _value5, _field6, _value6, _field7, _value7,	\
+		_field8, _value8, _field9, _value9, _field10, _value10)	\
+	EFX_POPULATE_DWORD_10(*MCDI_IN2(_emr, efx_dword_t, _ofst),	\
+		MC_CMD_ ## _field1, _value1,				\
+		MC_CMD_ ## _field2, _value2,				\
+		MC_CMD_ ## _field3, _value3,				\
+		MC_CMD_ ## _field4, _value4,				\
+		MC_CMD_ ## _field5, _value5,				\
+		MC_CMD_ ## _field6, _value6,				\
+		MC_CMD_ ## _field7, _value7,				\
+		MC_CMD_ ## _field8, _value8,				\
+		MC_CMD_ ## _field9, _value9,				\
+		MC_CMD_ ## _field10, _value10)
+
+#define	MCDI_OUT(_emr, _type, _ofst)					\
+	((_type *)((_emr).emr_out_buf + (_ofst)))
+
+#define	MCDI_OUT2(_emr, _type, _ofst)					\
+	MCDI_OUT(_emr, _type, MC_CMD_ ## _ofst ## _OFST)
+
+#define	MCDI_OUT_BYTE(_emr, _ofst)					\
+	EFX_BYTE_FIELD(*MCDI_OUT2(_emr, efx_byte_t, _ofst),		\
+		    EFX_BYTE_0)
+
+#define	MCDI_OUT_WORD(_emr, _ofst)					\
+	EFX_WORD_FIELD(*MCDI_OUT2(_emr, efx_word_t, _ofst),		\
+		    EFX_WORD_0)
+
+#define	MCDI_OUT_DWORD(_emr, _ofst)					\
+	EFX_DWORD_FIELD(*MCDI_OUT2(_emr, efx_dword_t, _ofst),		\
+			EFX_DWORD_0)
+
+#define	MCDI_OUT_DWORD_FIELD(_emr, _ofst, _field)			\
+	EFX_DWORD_FIELD(*MCDI_OUT2(_emr, efx_dword_t, _ofst),		\
+			MC_CMD_ ## _field)
+
+#define	MCDI_EV_FIELD(_eqp, _field)					\
+	EFX_QWORD_FIELD(*_eqp, MCDI_EVENT_ ## _field)
+
+#define MCDI_CMD_DWORD_FIELD(_edp, _field)				\
+	EFX_DWORD_FIELD(*_edp, MC_CMD_ ## _field)
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_EFX_MCDI_H */
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_mon.c	2013-08-22 18:57:28.333668291 -0400
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_MON_NULL
+#include "nullmon.h"
+#endif
+
+#if EFSYS_OPT_MON_LM87
+#include "lm87.h"
+#endif
+
+#if EFSYS_OPT_MON_MAX6647
+#include "max6647.h"
+#endif
+
+#if EFSYS_OPT_NAMES
+
+static const char	__cs * __cs __efx_mon_name[] = {
+	"",
+	"nullmon",
+	"lm87",
+	"max6647",
+	"sfx90x0"
+};
+
+		const char __cs *
+efx_mon_name(
+	__in	efx_nic_t *enp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+
+	EFSYS_ASSERT(encp->enc_mon_type != EFX_MON_INVALID);
+	EFSYS_ASSERT3U(encp->enc_mon_type, <, EFX_MON_NTYPES);
+	return (__efx_mon_name[encp->enc_mon_type]);
+}
+
+#endif	/* EFSYS_OPT_NAMES */
+
+#if EFSYS_OPT_MON_NULL
+static efx_mon_ops_t	__cs __efx_mon_null_ops = {
+	nullmon_reset,			/* emo_reset */
+	nullmon_reconfigure,		/* emo_reconfigure */
+#if EFSYS_OPT_MON_STATS
+	nullmon_stats_update		/* emo_stat_update */
+#endif	/* EFSYS_OPT_MON_STATS */
+};
+#endif
+
+#if EFSYS_OPT_MON_LM87
+static efx_mon_ops_t	__cs __efx_mon_lm87_ops = {
+	lm87_reset,			/* emo_reset */
+	lm87_reconfigure,		/* emo_reconfigure */
+#if EFSYS_OPT_MON_STATS
+	lm87_stats_update		/* emo_stat_update */
+#endif	/* EFSYS_OPT_MON_STATS */
+};
+#endif
+
+#if EFSYS_OPT_MON_MAX6647
+static efx_mon_ops_t	__cs __efx_mon_max6647_ops = {
+	max6647_reset,			/* emo_reset */
+	max6647_reconfigure,		/* emo_reconfigure */
+#if EFSYS_OPT_MON_STATS
+	max6647_stats_update		/* emo_stat_update */
+#endif	/* EFSYS_OPT_MON_STATS */
+};
+#endif
+
+#if EFSYS_OPT_MON_SIENA
+static efx_mon_ops_t	__cs __efx_mon_siena_ops = {
+	siena_mon_reset,		/* emo_reset */
+	siena_mon_reconfigure,		/* emo_reconfigure */
+#if EFSYS_OPT_MON_STATS
+	siena_mon_stats_update		/* emo_stat_update */
+#endif	/* EFSYS_OPT_MON_STATS */
+};
+#endif
+
+
+static efx_mon_ops_t	__cs * __cs __efx_mon_ops[] = {
+	NULL,
+#if EFSYS_OPT_MON_NULL
+	&__efx_mon_null_ops,
+#else
+	NULL,
+#endif
+#if EFSYS_OPT_MON_LM87
+	&__efx_mon_lm87_ops,
+#else
+	NULL,
+#endif
+#if EFSYS_OPT_MON_MAX6647
+	&__efx_mon_max6647_ops,
+#else
+	NULL,
+#endif
+#if EFSYS_OPT_MON_SIENA
+	&__efx_mon_siena_ops
+#else
+	NULL
+#endif
+};
+
+	__checkReturn	int
+efx_mon_init(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_mon_t *emp = &(enp->en_mon);
+	efx_mon_ops_t *emop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+
+	if (enp->en_mod_flags & EFX_MOD_MON) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	enp->en_mod_flags |= EFX_MOD_MON;
+
+	emp->em_type = encp->enc_mon_type;
+
+	EFSYS_ASSERT(encp->enc_mon_type != EFX_MON_INVALID);
+	EFSYS_ASSERT3U(emp->em_type, <, EFX_MON_NTYPES);
+	if ((emop = (efx_mon_ops_t *)__efx_mon_ops[emp->em_type]) == NULL) {
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if ((rc = emop->emo_reset(enp)) != 0)
+		goto fail3;
+
+	if ((rc = emop->emo_reconfigure(enp)) != 0)
+		goto fail4;
+
+	emp->em_emop = emop;
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail5);
+
+	(void) emop->emo_reset(enp);
+
+fail3:
+	EFSYS_PROBE(fail4);
+fail2:
+	EFSYS_PROBE(fail3);
+
+	emp->em_type = EFX_MON_INVALID;
+
+	enp->en_mod_flags &= ~EFX_MOD_MON;
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_MON_STATS
+
+#if EFSYS_OPT_NAMES
+
+/* START MKCONFIG GENERATED MonitorStatNamesBlock cc98f339ca74c6b8 */
+static const char 	__cs * __cs __mon_stat_name[] = {
+	"value_2_5v",
+	"value_vccp1",
+	"value_vcc",
+	"value_5v",
+	"value_12v",
+	"value_vccp2",
+	"value_ext_temp",
+	"value_int_temp",
+	"value_ain1",
+	"value_ain2",
+	"controller_cooling",
+	"ext_cooling",
+	"1v",
+	"1_2v",
+	"1_8v",
+	"3_3v",
+	"1_2va",
+	"vref",
+};
+
+/* END MKCONFIG GENERATED MonitorStatNamesBlock */
+
+extern					const char __cs *
+efx_mon_stat_name(
+	__in				efx_nic_t *enp,
+	__in				efx_mon_stat_t id)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+
+	EFSYS_ASSERT3U(id, <, EFX_MON_NSTATS);
+	return (__mon_stat_name[id]);
+}
+
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn			int
+efx_mon_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values)
+{
+	efx_mon_t *emp = &(enp->en_mon);
+	efx_mon_ops_t *emop = emp->em_emop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MON);
+
+	return (emop->emo_stats_update(enp, esmp, values));
+}
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+		void
+efx_mon_fini(
+	__in	efx_nic_t *enp)
+{
+	efx_mon_t *emp = &(enp->en_mon);
+	efx_mon_ops_t *emop = emp->em_emop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MON);
+
+	emp->em_emop = NULL;
+
+	rc = emop->emo_reset(enp);
+	if (rc != 0)
+		EFSYS_PROBE1(fail1, int, rc);
+
+	emp->em_type = EFX_MON_INVALID;
+
+	enp->en_mod_flags &= ~EFX_MOD_MON;
+}
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_nic.c	2013-08-22 18:57:28.421268743 -0400
@@ -0,0 +1,678 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+	__checkReturn	int
+efx_family(
+	__in		uint16_t venid,
+	__in		uint16_t devid,
+	__out		efx_family_t *efp)
+{
+#if EFSYS_OPT_FALCON
+	if (venid == EFX_PCI_VENID_SFC && devid == EFX_PCI_DEVID_FALCON) {
+		*efp = EFX_FAMILY_FALCON;
+		return (0);
+	}
+#endif
+#if EFSYS_OPT_SIENA
+	if (venid == EFX_PCI_VENID_SFC && devid == EFX_PCI_DEVID_BETHPAGE) {
+		*efp = EFX_FAMILY_SIENA;
+		return (0);
+	}
+	if (venid == EFX_PCI_VENID_SFC && devid == EFX_PCI_DEVID_SIENA) {
+		*efp = EFX_FAMILY_SIENA;
+		return (0);
+	}
+	if (venid == EFX_PCI_VENID_SFC &&
+	    devid == EFX_PCI_DEVID_SIENA_F1_UNINIT) {
+		*efp = EFX_FAMILY_SIENA;
+		return (0);
+	}
+#endif
+	return (ENOTSUP);
+}
+
+/*
+ * To support clients which aren't provided with any PCI context infer
+ * the hardware family by inspecting the hardware. Obviously the caller
+ * must be damn sure they're really talking to a supported device.
+ */
+	__checkReturn	int
+efx_infer_family(
+	__in		efsys_bar_t *esbp,
+	__out		efx_family_t *efp)
+{
+	efx_family_t family;
+	efx_oword_t oword;
+	unsigned int portnum;
+	int rc;
+
+	EFSYS_BAR_READO(esbp, FR_AZ_CS_DEBUG_REG_OFST, &oword, B_TRUE);
+	portnum = EFX_OWORD_FIELD(oword, FRF_CZ_CS_PORT_NUM);
+	switch (portnum) {
+#if EFSYS_OPT_FALCON
+	case 0:
+		family = EFX_FAMILY_FALCON;
+		break;
+#endif
+#if EFSYS_OPT_SIENA
+	case 1:
+	case 2:
+		family = EFX_FAMILY_SIENA;
+		break;
+#endif
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (efp != NULL)
+		*efp = family;
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+/*
+ * The built-in default value device id for port 1 of Siena is 0x0810.
+ * manftest needs to be able to cope with that.
+ */
+
+#define	EFX_BIU_MAGIC0	0x01234567
+#define	EFX_BIU_MAGIC1	0xfedcba98
+
+static	__checkReturn	int
+efx_nic_biu_test(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	int rc;
+
+	/*
+	 * Write magic values to scratch registers 0 and 1, then
+	 * verify that the values were written correctly.  Interleave
+	 * the accesses to ensure that the BIU is not just reading
+	 * back the cached value that was last written.
+	 */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0);
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1);
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword);
+
+	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword);
+	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) {
+		rc = EIO;
+		goto fail1;
+	}
+
+	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword);
+	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) {
+		rc = EIO;
+		goto fail2;
+	}
+
+	/*
+	 * Perform the same test, with the values swapped.  This
+	 * ensures that subsequent tests don't start with the correct
+	 * values already written into the scratch registers.
+	 */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1);
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0);
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword);
+
+	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword);
+	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) {
+		rc = EIO;
+		goto fail3;
+	}
+
+	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword);
+	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) {
+		rc = EIO;
+		goto fail4;
+	}
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_FALCON
+
+static efx_nic_ops_t	__cs __efx_nic_falcon_ops = {
+	falcon_nic_probe,		/* eno_probe */
+	falcon_nic_reset,		/* eno_reset */
+	falcon_nic_init,		/* eno_init */
+#if EFSYS_OPT_DIAG
+	falcon_sram_test,		/* eno_sram_test */
+	falcon_nic_register_test,	/* eno_register_test */
+#endif	/* EFSYS_OPT_DIAG */
+	falcon_nic_fini,		/* eno_fini */
+	falcon_nic_unprobe,		/* eno_unprobe */
+};
+
+#endif	/* EFSYS_OPT_FALCON */
+
+#if EFSYS_OPT_SIENA
+
+static efx_nic_ops_t	__cs __efx_nic_siena_ops = {
+	siena_nic_probe,		/* eno_probe */
+	siena_nic_reset,		/* eno_reset */
+	siena_nic_init,			/* eno_init */
+#if EFSYS_OPT_DIAG
+	siena_sram_test,		/* eno_sram_test */
+	siena_nic_register_test,	/* eno_register_test */
+#endif	/* EFSYS_OPT_DIAG */
+	siena_nic_fini,			/* eno_fini */
+	siena_nic_unprobe,		/* eno_unprobe */
+};
+
+#endif	/* EFSYS_OPT_SIENA */
+
+	__checkReturn	int
+efx_nic_create(
+	__in		efx_family_t family,
+	__in		efsys_identifier_t *esip,
+	__in		efsys_bar_t *esbp,
+	__in		efsys_lock_t *eslp,
+	__deref_out	efx_nic_t **enpp)
+{
+	efx_nic_t *enp;
+	int rc;
+
+	EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
+	EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
+
+	/* Allocate a NIC object */
+	EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
+
+	if (enp == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	enp->en_magic = EFX_NIC_MAGIC;
+
+	switch (family) {
+#if EFSYS_OPT_FALCON
+	case EFX_FAMILY_FALCON:
+		enp->en_enop = (efx_nic_ops_t *)&__efx_nic_falcon_ops;
+		enp->en_features = 0;
+		break;
+#endif	/* EFSYS_OPT_FALCON */
+
+#if EFSYS_OPT_SIENA
+	case EFX_FAMILY_SIENA:
+		enp->en_enop = (efx_nic_ops_t *)&__efx_nic_siena_ops;
+		enp->en_features =
+		    EFX_FEATURE_IPV6 |
+		    EFX_FEATURE_LFSR_HASH_INSERT |
+		    EFX_FEATURE_LINK_EVENTS |
+		    EFX_FEATURE_PERIODIC_MAC_STATS |
+		    EFX_FEATURE_WOL |
+		    EFX_FEATURE_MCDI |
+		    EFX_FEATURE_LOOKAHEAD_SPLIT |
+		    EFX_FEATURE_MAC_HEADER_FILTERS;
+		break;
+#endif	/* EFSYS_OPT_SIENA */
+
+	default:
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	enp->en_family = family;
+	enp->en_esip = esip;
+	enp->en_esbp = esbp;
+	enp->en_eslp = eslp;
+
+	*enpp = enp;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail3);
+
+	enp->en_magic = 0;
+
+	/* Free the NIC object */
+	EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_nic_probe(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_ops_t *enop;
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+#if EFSYS_OPT_MCDI
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
+#endif	/* EFSYS_OPT_MCDI */
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
+
+	/* Test BIU */
+	if ((rc = efx_nic_biu_test(enp)) != 0)
+		goto fail1;
+
+	/* Clear the region register */
+	EFX_POPULATE_OWORD_4(oword,
+	    FRF_AZ_ADR_REGION0, 0,
+	    FRF_AZ_ADR_REGION1, (1 << 16),
+	    FRF_AZ_ADR_REGION2, (2 << 16),
+	    FRF_AZ_ADR_REGION3, (3 << 16));
+	EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
+
+	enop = enp->en_enop;
+	if ((rc = enop->eno_probe(enp)) != 0)
+		goto fail2;
+
+	if ((rc = efx_phy_probe(enp)) != 0)
+		goto fail3;
+
+	enp->en_mod_flags |= EFX_MOD_PROBE;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+
+	enop->eno_unprobe(enp);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_PCIE_TUNE
+
+	__checkReturn	int
+efx_nic_pcie_tune(
+	__in		efx_nic_t *enp,
+	unsigned int	nlanes)
+{
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
+
+#if EFSYS_OPT_FALCON
+	if (enp->en_family == EFX_FAMILY_FALCON)
+		return (falcon_nic_pcie_tune(enp, nlanes));
+#endif
+	return (ENOTSUP);
+}
+
+	__checkReturn	int
+efx_nic_pcie_extended_sync(
+	__in		efx_nic_t *enp)
+{
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
+
+#if EFSYS_OPT_SIENA
+	if (enp->en_family == EFX_FAMILY_SIENA)
+		return (siena_nic_pcie_extended_sync(enp));
+#endif
+
+	return (ENOTSUP);
+}
+
+#endif	/* EFSYS_OPT_PCIE_TUNE */
+
+	__checkReturn	int
+efx_nic_init(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_ops_t *enop = enp->en_enop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+
+	if (enp->en_mod_flags & EFX_MOD_NIC) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if ((rc = enop->eno_init(enp)) != 0)
+		goto fail2;
+
+	enp->en_mod_flags |= EFX_MOD_NIC;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+			void
+efx_nic_fini(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_ops_t *enop = enp->en_enop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
+	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
+
+	enop->eno_fini(enp);
+
+	enp->en_mod_flags &= ~EFX_MOD_NIC;
+}
+
+			void
+efx_nic_unprobe(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_ops_t *enop = enp->en_enop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+#if EFSYS_OPT_MCDI
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
+#endif	/* EFSYS_OPT_MCDI */
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
+
+	efx_phy_unprobe(enp);
+
+	enop->eno_unprobe(enp);
+
+	enp->en_mod_flags &= ~EFX_MOD_PROBE;
+}
+
+			void
+efx_nic_destroy(
+	__in	efx_nic_t *enp)
+{
+	efsys_identifier_t *esip = enp->en_esip;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
+
+	enp->en_family = 0;
+	enp->en_esip = NULL;
+	enp->en_esbp = NULL;
+	enp->en_eslp = NULL;
+
+	enp->en_enop = NULL;
+
+	enp->en_magic = 0;
+
+	/* Free the NIC object */
+	EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
+}
+
+	__checkReturn	int
+efx_nic_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_ops_t *enop = enp->en_enop;
+	unsigned int mod_flags;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
+	/*
+	 * All modules except the MCDI, PROBE, NVRAM, VPD, MON (which we
+	 * do not reset here) must have been shut down or never initialized.
+	 *
+	 * A rule of thumb here is: If the controller or MC reboots, is *any*
+	 * state lost. If it's lost and needs reapplying, then the module
+	 * *must* not be initialised during the reset.
+	 */
+	mod_flags = enp->en_mod_flags;
+	mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
+		    EFX_MOD_VPD | EFX_MOD_MON);
+	EFSYS_ASSERT3U(mod_flags, ==, 0);
+	if (mod_flags != 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if ((rc = enop->eno_reset(enp)) != 0)
+		goto fail2;
+
+	enp->en_reset_flags |= EFX_RESET_MAC;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+			const efx_nic_cfg_t *
+efx_nic_cfg_get(
+	__in		efx_nic_t *enp)
+{
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+
+	return (&(enp->en_nic_cfg));
+}
+
+#if EFSYS_OPT_DIAG
+
+	__checkReturn	int
+efx_nic_register_test(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_ops_t *enop = enp->en_enop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
+
+	if ((rc = enop->eno_register_test(enp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_nic_test_registers(
+	__in		efx_nic_t *enp,
+	__in		efx_register_set_t *rsp,
+	__in		size_t count)
+{
+	unsigned int bit;
+	efx_oword_t original;
+	efx_oword_t reg;
+	efx_oword_t buf;
+	int rc;
+
+	while (count > 0) {
+		/* This function is only suitable for registers */
+		EFSYS_ASSERT(rsp->rows == 1);
+
+		/* bit sweep on and off */
+		EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original,
+			    B_TRUE);
+		for (bit = 0; bit < 128; bit++) {
+			/* Is this bit in the mask? */
+			if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit))
+				continue;
+
+			/* Test this bit can be set in isolation */
+			reg = original;
+			EFX_AND_OWORD(reg, rsp->mask);
+			EFX_SET_OWORD_BIT(reg, bit);
+
+			EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
+				    B_TRUE);
+			EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
+				    B_TRUE);
+
+			EFX_AND_OWORD(buf, rsp->mask);
+			if (memcmp(&reg, &buf, sizeof (reg))) {
+				rc = EIO;
+				goto fail1;
+			}
+
+			/* Test this bit can be cleared in isolation */
+			EFX_OR_OWORD(reg, rsp->mask);
+			EFX_CLEAR_OWORD_BIT(reg, bit);
+
+			EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
+				    B_TRUE);
+			EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
+				    B_TRUE);
+
+			EFX_AND_OWORD(buf, rsp->mask);
+			if (memcmp(&reg, &buf, sizeof (reg))) {
+				rc = EIO;
+				goto fail2;
+			}
+		}
+
+		/* Restore the old value */
+		EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original,
+			    B_TRUE);
+
+		--count;
+		++rsp;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	/* Restore the old value */
+	EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE);
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_nic_test_tables(
+	__in		efx_nic_t *enp,
+	__in		efx_register_set_t *rsp,
+	__in		efx_pattern_type_t pattern,
+	__in		size_t count)
+{
+	efx_sram_pattern_fn_t func;
+	unsigned int index;
+	unsigned int address;
+	efx_oword_t reg;
+	efx_oword_t buf;
+	int rc;
+
+	EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES);
+	func = __efx_sram_pattern_fns[pattern];
+
+	while (count > 0) {
+		/* Write */
+		address = rsp->address;
+		for (index = 0; index < rsp->rows; ++index) {
+			func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
+			func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
+			EFX_AND_OWORD(reg, rsp->mask);
+			EFSYS_BAR_WRITEO(enp->en_esbp, address, &reg, B_TRUE);
+
+			address += rsp->step;
+		}
+
+		/* Read */
+		address = rsp->address;
+		for (index = 0; index < rsp->rows; ++index) {
+			func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
+			func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
+			EFX_AND_OWORD(reg, rsp->mask);
+			EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE);
+			if (memcmp(&reg, &buf, sizeof (reg))) {
+				rc = EIO;
+				goto fail1;
+			}
+
+			address += rsp->step;
+		}
+
+		++rsp;
+		--count;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_DIAG */
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_nvram.c	2013-08-22 18:57:28.513826071 -0400
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_NVRAM
+
+#if EFSYS_OPT_FALCON
+
+static efx_nvram_ops_t	__cs	__efx_nvram_falcon_ops = {
+#if EFSYS_OPT_DIAG
+	falcon_nvram_test,		/* envo_test */
+#endif	/* EFSYS_OPT_DIAG */
+	falcon_nvram_size,		/* envo_size */
+	falcon_nvram_get_version,	/* envo_get_version */
+	falcon_nvram_rw_start,		/* envo_rw_start */
+	falcon_nvram_read_chunk,	/* envo_read_chunk */
+	falcon_nvram_erase,		/* envo_erase */
+	falcon_nvram_write_chunk,	/* envo_write_chunk */
+	falcon_nvram_rw_finish,		/* envo_rw_finish */
+	falcon_nvram_set_version,	/* envo_set_version */
+};
+
+#endif	/* EFSYS_OPT_FALCON */
+
+#if EFSYS_OPT_SIENA
+
+static efx_nvram_ops_t	__cs	__efx_nvram_siena_ops = {
+#if EFSYS_OPT_DIAG
+	siena_nvram_test,		/* envo_test */
+#endif	/* EFSYS_OPT_DIAG */
+	siena_nvram_size,		/* envo_size */
+	siena_nvram_get_version,	/* envo_get_version */
+	siena_nvram_rw_start,		/* envo_rw_start */
+	siena_nvram_read_chunk,		/* envo_read_chunk */
+	siena_nvram_erase,		/* envo_erase */
+	siena_nvram_write_chunk,	/* envo_write_chunk */
+	siena_nvram_rw_finish,		/* envo_rw_finish */
+	siena_nvram_set_version,	/* envo_set_version */
+};
+
+#endif	/* EFSYS_OPT_SIENA */
+
+	__checkReturn	int
+efx_nvram_init(
+	__in		efx_nic_t *enp)
+{
+	efx_nvram_ops_t *envop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
+
+	switch (enp->en_family) {
+#if EFSYS_OPT_FALCON
+	case EFX_FAMILY_FALCON:
+		envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops;
+		break;
+#endif	/* EFSYS_OPT_FALCON */
+
+#if EFSYS_OPT_SIENA
+	case EFX_FAMILY_SIENA:
+		envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops;
+		break;
+#endif	/* EFSYS_OPT_SIENA */
+
+	default:
+		EFSYS_ASSERT(0);
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	enp->en_envop = envop;
+	enp->en_mod_flags |= EFX_MOD_NVRAM;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_DIAG
+
+	__checkReturn		int
+efx_nvram_test(
+	__in			efx_nic_t *enp)
+{
+	efx_nvram_ops_t *envop = enp->en_envop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	if ((rc = envop->envo_test(enp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_DIAG */
+
+	__checkReturn		int
+efx_nvram_size(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *sizep)
+{
+	efx_nvram_ops_t *envop = enp->en_envop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+
+	if ((rc = envop->envo_size(enp, type, sizep)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4])
+{
+	efx_nvram_ops_t *envop = enp->en_envop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+
+	if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out_opt		size_t *chunk_sizep)
+{
+	efx_nvram_ops_t *envop = enp->en_envop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
+
+	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
+
+	if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0)
+		goto fail1;
+
+	enp->en_nvram_locked = type;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_nvram_ops_t *envop = enp->en_envop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
+
+	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
+
+	if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_nvram_erase(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type)
+{
+	efx_nvram_ops_t *envop = enp->en_envop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
+
+	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
+
+	if ((rc = envop->envo_erase(enp, type)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_nvram_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_nvram_ops_t *envop = enp->en_envop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
+
+	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
+
+	if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+				void
+efx_nvram_rw_finish(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type)
+{
+	efx_nvram_ops_t *envop = enp->en_envop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
+
+	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
+
+	envop->envo_rw_finish(enp, type);
+
+	enp->en_nvram_locked = EFX_NVRAM_INVALID;
+}
+
+	__checkReturn		int
+efx_nvram_set_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint16_t version[4])
+{
+	efx_nvram_ops_t *envop = enp->en_envop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+
+	/*
+	 * The Siena implementation of envo_set_version() will attempt to
+	 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
+	 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
+	 */
+	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
+
+	if ((rc = envop->envo_set_version(enp, type, version)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+efx_nvram_fini(
+	__in		efx_nic_t *enp)
+{
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
+
+	enp->en_envop = NULL;
+	enp->en_mod_flags &= ~EFX_MOD_NVRAM;
+}
+
+#endif	/* EFSYS_OPT_NVRAM */
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_phy.c	2013-08-22 18:57:28.602132357 -0400
@@ -0,0 +1,765 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#if EFSYS_OPT_FALCON
+#include "falcon_nvram.h"
+#endif
+
+#if EFSYS_OPT_MAC_FALCON_XMAC
+#include "falcon_xmac.h"
+#endif
+
+#if EFSYS_OPT_MAC_FALCON_GMAC
+#include "falcon_gmac.h"
+#endif
+
+#if EFSYS_OPT_PHY_NULL
+#include "nullphy.h"
+#endif
+
+#if EFSYS_OPT_PHY_QT2022C2
+#include "qt2022c2.h"
+#endif
+
+#if EFSYS_OPT_PHY_SFX7101
+#include "sfx7101.h"
+#endif
+
+#if EFSYS_OPT_PHY_TXC43128
+#include "txc43128.h"
+#endif
+
+#if EFSYS_OPT_PHY_SFT9001
+#include "sft9001.h"
+#endif
+
+#if EFSYS_OPT_PHY_QT2025C
+#include "qt2025c.h"
+#endif
+
+#if EFSYS_OPT_PHY_NULL
+static efx_phy_ops_t	__cs __efx_phy_null_ops = {
+	NULL,				/* epo_power */
+	nullphy_reset,			/* epo_reset */
+	nullphy_reconfigure,		/* epo_reconfigure */
+	nullphy_verify,			/* epo_verify */
+	NULL,				/* epo_uplink_check */
+	nullphy_downlink_check,		/* epo_downlink_check */
+	nullphy_oui_get,		/* epo_oui_get */
+#if EFSYS_OPT_PHY_STATS
+	nullphy_stats_update,		/* epo_stats_update */
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+#if EFSYS_OPT_NAMES
+	nullphy_prop_name,		/* epo_prop_name */
+#endif
+	nullphy_prop_get,		/* epo_prop_get */
+	nullphy_prop_set,		/* epo_prop_set */
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+	NULL,				/* epo_bist_start */
+	NULL,				/* epo_bist_poll */
+	NULL,				/* epo_bist_stop */
+#endif	/* EFSYS_OPT_PHY_BIST */
+};
+#endif	/* EFSYS_OPT_PHY_NULL */
+
+#if EFSYS_OPT_PHY_QT2022C2
+static efx_phy_ops_t	__cs __efx_phy_qt2022c2_ops = {
+	NULL,				/* epo_power */
+	qt2022c2_reset,			/* epo_reset */
+	qt2022c2_reconfigure,		/* epo_reconfigure */
+	qt2022c2_verify,		/* epo_verify */
+	qt2022c2_uplink_check,		/* epo_uplink_check */
+	qt2022c2_downlink_check,	/* epo_downlink_check */
+	qt2022c2_oui_get,		/* epo_oui_get */
+#if EFSYS_OPT_PHY_STATS
+	qt2022c2_stats_update,		/* epo_stats_update */
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+#if EFSYS_OPT_NAMES
+	qt2022c2_prop_name,		/* epo_prop_name */
+#endif
+	qt2022c2_prop_get,		/* epo_prop_get */
+	qt2022c2_prop_set,		/* epo_prop_set */
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+	NULL,				/* epo_bist_start */
+	NULL,				/* epo_bist_poll */
+	NULL,				/* epo_bist_stop */
+#endif	/* EFSYS_OPT_PHY_BIST */
+};
+#endif	/* EFSYS_OPT_PHY_QT2022C2 */
+
+#if EFSYS_OPT_PHY_SFX7101
+static efx_phy_ops_t	__cs __efx_phy_sfx7101_ops = {
+	sfx7101_power,			/* epo_power */
+	sfx7101_reset,			/* epo_reset */
+	sfx7101_reconfigure,		/* epo_reconfigure */
+	sfx7101_verify,			/* epo_verify */
+	sfx7101_uplink_check,		/* epo_uplink_check */
+	sfx7101_downlink_check,		/* epo_downlink_check */
+	sfx7101_oui_get,		/* epo_oui_get */
+#if EFSYS_OPT_PHY_STATS
+	sfx7101_stats_update,		/* epo_stats_update */
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+#if EFSYS_OPT_NAMES
+	sfx7101_prop_name,		/* epo_prop_name */
+#endif
+	sfx7101_prop_get,		/* epo_prop_get */
+	sfx7101_prop_set,		/* epo_prop_set */
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+	NULL,				/* epo_bist_start */
+	NULL,				/* epo_bist_poll */
+	NULL,				/* epo_bist_stop */
+#endif	/* EFSYS_OPT_PHY_BIST */
+};
+#endif	/* EFSYS_OPT_PHY_SFX7101 */
+
+#if EFSYS_OPT_PHY_TXC43128
+static efx_phy_ops_t	__cs __efx_phy_txc43128_ops = {
+	NULL,				/* epo_power */
+	txc43128_reset,			/* epo_reset */
+	txc43128_reconfigure,		/* epo_reconfigure */
+	txc43128_verify,		/* epo_verify */
+	txc43128_uplink_check,		/* epo_uplink_check */
+	txc43128_downlink_check,	/* epo_downlink_check */
+	txc43128_oui_get,		/* epo_oui_get */
+#if EFSYS_OPT_PHY_STATS
+	txc43128_stats_update,		/* epo_stats_update */
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+#if EFSYS_OPT_NAMES
+	txc43128_prop_name,		/* epo_prop_name */
+#endif
+	txc43128_prop_get,		/* epo_prop_get */
+	txc43128_prop_set,		/* epo_prop_set */
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+	NULL,				/* epo_bist_start */
+	NULL,				/* epo_bist_poll */
+	NULL,				/* epo_bist_stop */
+#endif	/* EFSYS_OPT_PHY_BIST */
+};
+#endif	/* EFSYS_OPT_PHY_TXC43128 */
+
+#if EFSYS_OPT_PHY_SFT9001
+static efx_phy_ops_t	__cs __efx_phy_sft9001_ops = {
+	NULL,				/* epo_power */
+	sft9001_reset,			/* epo_reset */
+	sft9001_reconfigure,		/* epo_reconfigure */
+	sft9001_verify,			/* epo_verify */
+	sft9001_uplink_check,		/* epo_uplink_check */
+	sft9001_downlink_check,		/* epo_downlink_check */
+	sft9001_oui_get,		/* epo_oui_get */
+#if EFSYS_OPT_PHY_STATS
+	sft9001_stats_update,		/* epo_stats_update */
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+#if EFSYS_OPT_NAMES
+	sft9001_prop_name,		/* epo_prop_name */
+#endif
+	sft9001_prop_get,		/* epo_prop_get */
+	sft9001_prop_set,		/* epo_prop_set */
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+	sft9001_bist_start,		/* epo_bist_start */
+	sft9001_bist_poll,		/* epo_bist_poll */
+	sft9001_bist_stop,		/* epo_bist_stop */
+#endif	/* EFSYS_OPT_PHY_BIST */
+};
+#endif	/* EFSYS_OPT_PHY_SFT9001 */
+
+#if EFSYS_OPT_PHY_QT2025C
+static efx_phy_ops_t	__cs __efx_phy_qt2025c_ops = {
+	NULL,				/* epo_power */
+	qt2025c_reset,			/* epo_reset */
+	qt2025c_reconfigure,		/* epo_reconfigure */
+	qt2025c_verify,			/* epo_verify */
+	qt2025c_uplink_check,		/* epo_uplink_check */
+	qt2025c_downlink_check,		/* epo_downlink_check */
+	qt2025c_oui_get,		/* epo_oui_get */
+#if EFSYS_OPT_PHY_STATS
+	qt2025c_stats_update,		/* epo_stats_update */
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+#if EFSYS_OPT_NAMES
+	qt2025c_prop_name,		/* epo_prop_name */
+#endif
+	qt2025c_prop_get,		/* epo_prop_get */
+	qt2025c_prop_set,		/* epo_prop_set */
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+	NULL,				/* epo_bist_start */
+	NULL,				/* epo_bist_poll */
+	NULL,				/* epo_bist_stop */
+#endif	/* EFSYS_OPT_PHY_BIST */
+};
+#endif	/* EFSYS_OPT_PHY_QT2025C */
+
+#if EFSYS_OPT_SIENA
+static efx_phy_ops_t	__cs __efx_phy_siena_ops = {
+	siena_phy_power,		/* epo_power */
+	NULL,				/* epo_reset */
+	siena_phy_reconfigure,		/* epo_reconfigure */
+	siena_phy_verify,		/* epo_verify */
+	NULL,				/* epo_uplink_check */
+	NULL,				/* epo_downlink_check */
+	siena_phy_oui_get,		/* epo_oui_get */
+#if EFSYS_OPT_PHY_STATS
+	siena_phy_stats_update,		/* epo_stats_update */
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+#if EFSYS_OPT_NAMES
+	siena_phy_prop_name,		/* epo_prop_name */
+#endif
+	siena_phy_prop_get,		/* epo_prop_get */
+	siena_phy_prop_set,		/* epo_prop_set */
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+	siena_phy_bist_start, 		/* epo_bist_start */
+	siena_phy_bist_poll,		/* epo_bist_poll */
+	siena_phy_bist_stop,		/* epo_bist_stop */
+#endif	/* EFSYS_OPT_PHY_BIST */
+};
+#endif	/* EFSYS_OPT_SIENA */
+
+	__checkReturn	int
+efx_phy_probe(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_phy_ops_t *epop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+
+	epp->ep_port = encp->enc_port;
+	epp->ep_phy_type = encp->enc_phy_type;
+
+	/* Hook in operations structure */
+	switch (enp->en_family) {
+#if EFSYS_OPT_FALCON
+	case EFX_FAMILY_FALCON:
+		switch (epp->ep_phy_type) {
+#if EFSYS_OPT_PHY_NULL
+		case PHY_TYPE_NONE_DECODE:
+			epop = (efx_phy_ops_t *)&__efx_phy_null_ops;
+			break;
+#endif
+#if EFSYS_OPT_PHY_QT2022C2
+		case PHY_TYPE_QT2022C2_DECODE:
+			epop = (efx_phy_ops_t *)&__efx_phy_qt2022c2_ops;
+			break;
+#endif
+#if EFSYS_OPT_PHY_SFX7101
+		case PHY_TYPE_SFX7101_DECODE:
+			epop = (efx_phy_ops_t *)&__efx_phy_sfx7101_ops;
+			break;
+#endif
+#if EFSYS_OPT_PHY_TXC43128
+		case PHY_TYPE_TXC43128_DECODE:
+			epop = (efx_phy_ops_t *)&__efx_phy_txc43128_ops;
+			break;
+#endif
+#if EFSYS_OPT_PHY_SFT9001
+		case PHY_TYPE_SFT9001A_DECODE:
+		case PHY_TYPE_SFT9001B_DECODE:
+			epop = (efx_phy_ops_t *)&__efx_phy_sft9001_ops;
+			break;
+#endif
+#if EFSYS_OPT_PHY_QT2025C
+		case EFX_PHY_QT2025C:
+			epop = (efx_phy_ops_t *)&__efx_phy_qt2025c_ops;
+			break;
+#endif
+		default:
+			rc = ENOTSUP;
+			goto fail1;
+		}
+		break;
+#endif	/* EFSYS_OPT_FALCON */
+#if EFSYS_OPT_SIENA
+	case EFX_FAMILY_SIENA:
+		epop = (efx_phy_ops_t *)&__efx_phy_siena_ops;
+		break;
+#endif	/* EFSYS_OPT_SIENA */
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	epp->ep_epop = epop;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	epp->ep_port = 0;
+	epp->ep_phy_type = 0;
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_phy_verify(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	return (epop->epo_verify(enp));
+}
+
+#if EFSYS_OPT_PHY_LED_CONTROL
+
+	__checkReturn	int
+efx_phy_led_set(
+	__in		efx_nic_t *enp,
+	__in		efx_phy_led_mode_t mode)
+{
+	efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+	uint32_t mask;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	if (epp->ep_phy_led_mode == mode)
+		goto done;
+
+	mask = (1 << EFX_PHY_LED_DEFAULT);
+	mask |= encp->enc_led_mask;
+
+	if (!((1 << mode) & mask)) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
+	epp->ep_phy_led_mode = mode;
+
+	if ((rc = epop->epo_reconfigure(enp)) != 0)
+		goto fail2;
+
+done:
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+			void
+efx_phy_adv_cap_get(
+	__in		efx_nic_t *enp,
+	__in		uint32_t flag,
+	__out		uint32_t *maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+
+	switch (flag) {
+	case EFX_PHY_CAP_CURRENT:
+		*maskp = epp->ep_adv_cap_mask;
+		break;
+	case EFX_PHY_CAP_DEFAULT:
+		*maskp = epp->ep_default_adv_cap_mask;
+		break;
+	case EFX_PHY_CAP_PERM:
+		*maskp = epp->ep_phy_cap_mask;
+		break;
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		break;
+	}
+}
+
+	__checkReturn	int
+efx_phy_adv_cap_set(
+	__in		efx_nic_t *enp,
+	__in		uint32_t mask)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+	uint32_t old_mask;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	if ((mask & ~epp->ep_phy_cap_mask) != 0) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (epp->ep_adv_cap_mask == mask)
+		goto done;
+
+	old_mask = epp->ep_adv_cap_mask;
+	epp->ep_adv_cap_mask = mask;
+
+	if ((rc = epop->epo_reconfigure(enp)) != 0)
+		goto fail2;
+
+done:
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+
+	epp->ep_adv_cap_mask = old_mask;
+	/* Reconfigure for robustness */
+	if (epop->epo_reconfigure(enp) != 0) {
+		/*
+		 * We may have an inconsistent view of our advertised speed
+		 * capabilities.
+		 */
+		EFSYS_ASSERT(0);
+	}
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	void
+efx_phy_lp_cap_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	*maskp = epp->ep_lp_cap_mask;
+}
+
+	__checkReturn	int
+efx_phy_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	return (epop->epo_oui_get(enp, ouip));
+}
+
+			void
+efx_phy_media_type_get(
+	__in		efx_nic_t *enp,
+	__out		efx_phy_media_type_t *typep)
+{
+	efx_port_t *epp = &(enp->en_port);
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
+		*typep = epp->ep_module_type;
+	else
+		*typep = epp->ep_fixed_port_type;
+}
+
+#if EFSYS_OPT_PHY_STATS
+
+#if EFSYS_OPT_NAMES
+
+/* START MKCONFIG GENERATED PhyStatNamesBlock 271268f3da0e804f */
+static const char 	__cs * __cs __efx_phy_stat_name[] = {
+	"oui",
+	"pma_pmd_link_up",
+	"pma_pmd_rx_fault",
+	"pma_pmd_tx_fault",
+	"pma_pmd_rev_a",
+	"pma_pmd_rev_b",
+	"pma_pmd_rev_c",
+	"pma_pmd_rev_d",
+	"pcs_link_up",
+	"pcs_rx_fault",
+	"pcs_tx_fault",
+	"pcs_ber",
+	"pcs_block_errors",
+	"phy_xs_link_up",
+	"phy_xs_rx_fault",
+	"phy_xs_tx_fault",
+	"phy_xs_align",
+	"phy_xs_sync_a",
+	"phy_xs_sync_b",
+	"phy_xs_sync_c",
+	"phy_xs_sync_d",
+	"an_link_up",
+	"an_master",
+	"an_local_rx_ok",
+	"an_remote_rx_ok",
+	"cl22ext_link_up",
+	"snr_a",
+	"snr_b",
+	"snr_c",
+	"snr_d",
+	"pma_pmd_signal_a",
+	"pma_pmd_signal_b",
+	"pma_pmd_signal_c",
+	"pma_pmd_signal_d",
+	"an_complete",
+	"pma_pmd_rev_major",
+	"pma_pmd_rev_minor",
+	"pma_pmd_rev_micro",
+	"pcs_fw_version_0",
+	"pcs_fw_version_1",
+	"pcs_fw_version_2",
+	"pcs_fw_version_3",
+	"pcs_fw_build_yy",
+	"pcs_fw_build_mm",
+	"pcs_fw_build_dd",
+	"pcs_op_mode",
+};
+
+/* END MKCONFIG GENERATED PhyStatNamesBlock */
+
+					const char __cs *
+efx_phy_stat_name(
+	__in				efx_nic_t *enp,
+	__in				efx_phy_stat_t type)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
+
+	return (__efx_phy_stat_name[type]);
+}
+
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn			int
+efx_phy_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	return (epop->epo_stats_update(enp, esmp, stat));
+}
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+		const char __cs *
+efx_phy_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+
+	return (epop->epo_prop_name(enp, id));
+}
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn	int
+efx_phy_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	return (epop->epo_prop_get(enp, id, flags, valp));
+}
+
+	__checkReturn	int
+efx_phy_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	return (epop->epo_prop_set(enp, id, val));
+}
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_BIST
+
+	__checkReturn		int
+efx_phy_bist_start(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	EFSYS_ASSERT3U(type, !=, EFX_PHY_BIST_TYPE_UNKNOWN);
+	EFSYS_ASSERT3U(type, <, EFX_PHY_BIST_TYPE_NTYPES);
+	EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_PHY_BIST_TYPE_UNKNOWN);
+
+	if (epop->epo_bist_start == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = epop->epo_bist_start(enp, type)) != 0)
+		goto fail2;
+
+	epp->ep_current_bist = type;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_phy_bist_poll(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type,
+	__out			efx_phy_bist_result_t *resultp,
+	__out_opt		uint32_t *value_maskp,
+	__out_ecount_opt(count)	unsigned long *valuesp,
+	__in			size_t count)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	EFSYS_ASSERT3U(type, !=, EFX_PHY_BIST_TYPE_UNKNOWN);
+	EFSYS_ASSERT3U(type, <, EFX_PHY_BIST_TYPE_NTYPES);
+	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
+
+	EFSYS_ASSERT(epop->epo_bist_poll != NULL);
+	if (epop->epo_bist_poll == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
+	    valuesp, count)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+			void
+efx_phy_bist_stop(
+	__in		efx_nic_t *enp,
+	__in		efx_phy_bist_type_t type)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	EFSYS_ASSERT3U(type, !=, EFX_PHY_BIST_TYPE_UNKNOWN);
+	EFSYS_ASSERT3U(type, <, EFX_PHY_BIST_TYPE_NTYPES);
+	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
+
+	EFSYS_ASSERT(epop->epo_bist_stop != NULL);
+
+	if (epop->epo_bist_stop != NULL)
+		epop->epo_bist_stop(enp, type);
+
+	epp->ep_current_bist = EFX_PHY_BIST_TYPE_UNKNOWN;
+}
+
+#endif	/* EFSYS_OPT_PHY_BIST */
+			void
+efx_phy_unprobe(
+	__in	efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+
+	epp->ep_epop = NULL;
+
+	epp->ep_adv_cap_mask = 0;
+
+	epp->ep_port = 0;
+	epp->ep_phy_type = 0;
+}
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_port.c	2013-08-22 18:57:28.694990986 -0400
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_impl.h"
+
+	__checkReturn	int
+efx_port_init(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+
+	if (enp->en_mod_flags & EFX_MOD_PORT) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	enp->en_mod_flags |= EFX_MOD_PORT;
+
+	epp->ep_mac_type = EFX_MAC_INVALID;
+	epp->ep_link_mode = EFX_LINK_UNKNOWN;
+	epp->ep_mac_poll_needed = B_TRUE;
+	epp->ep_mac_drain = B_TRUE;
+
+	/* Configure the MAC */
+	if ((rc = efx_mac_select(enp)) != 0)
+		goto fail1;
+
+	epp->ep_emop->emo_reconfigure(enp);
+
+	/*
+	 * Turn on the PHY if available, otherwise reset it, and
+	 * reconfigure it with the current configuration.
+	 */
+	if (epop->epo_power != NULL) {
+		if ((rc = epop->epo_power(enp, B_TRUE)) != 0)
+			goto fail2;
+	} else {
+		if ((rc = epop->epo_reset(enp)) != 0)
+			goto fail2;
+	}
+
+	EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY);
+	enp->en_reset_flags &= ~EFX_RESET_PHY;
+
+	if ((rc = epop->epo_reconfigure(enp)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	enp->en_mod_flags &= ~EFX_MOD_PORT;
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_port_poll(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t	*link_modep)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	efx_link_mode_t ignore_link_mode;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	EFSYS_ASSERT(emop != NULL);
+	EFSYS_ASSERT(!epp->ep_mac_stats_pending);
+
+	if (link_modep == NULL)
+		link_modep = &ignore_link_mode;
+
+	if ((rc = emop->emo_poll(enp, link_modep)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_LOOPBACK
+
+	__checkReturn	int
+efx_port_loopback_set(
+	__in		efx_nic_t *enp,
+	__in		efx_link_mode_t link_mode,
+	__in		efx_loopback_type_t loopback_type)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_mac_ops_t *emop = epp->ep_emop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+	EFSYS_ASSERT(emop != NULL);
+
+	EFSYS_ASSERT(link_mode < EFX_LINK_NMODES);
+	if ((1 << loopback_type) & ~encp->enc_loopback_types[link_mode]) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (epp->ep_loopback_type == loopback_type &&
+	    epp->ep_loopback_link_mode == link_mode)
+		return (0);
+
+	if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_NAMES
+
+static const char 	__cs * __cs __efx_loopback_type_name[] = {
+	"OFF",
+	"DATA",
+	"GMAC",
+	"XGMII",
+	"XGXS",
+	"XAUI",
+	"GMII",
+	"SGMII",
+	"XGBR",
+	"XFI",
+	"XAUI_FAR",
+	"GMII_FAR",
+	"SGMII_FAR",
+	"XFI_FAR",
+	"GPHY",
+	"PHY_XS",
+	"PCS",
+	"PMA_PMD",
+};
+
+	__checkReturn	const char __cs *
+efx_loopback_type_name(
+	__in		efx_nic_t *enp,
+	__in		efx_loopback_type_t type)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);
+
+	return (__efx_loopback_type_name[type]);
+}
+
+#endif	/* EFSYS_OPT_NAMES */
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+			void
+efx_port_fini(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
+
+	EFSYS_ASSERT(epp->ep_mac_drain);
+
+	epp->ep_emop = NULL;
+	epp->ep_mac_type = EFX_MAC_INVALID;
+	epp->ep_mac_drain = B_FALSE;
+	epp->ep_mac_poll_needed = B_FALSE;
+
+	/* Turn off the PHY */
+	if (epop->epo_power != NULL)
+		(void) epop->epo_power(enp, B_FALSE);
+
+	enp->en_mod_flags &= ~EFX_MOD_PORT;
+}
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_regs.h	2013-08-22 18:57:28.781647624 -0400
@@ -0,0 +1,3865 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_EFX_REGS_H
+#define	_SYS_EFX_REGS_H
+
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+
+/**************************************************************************
+ *
+ * Falcon/Siena registers and descriptors
+ *
+ **************************************************************************
+ */
+
+/*
+ * FR_AB_EE_VPD_CFG0_REG_SF(128bit):
+ * SPI/VPD configuration register 0
+ */
+#define	FR_AB_EE_VPD_CFG0_REG_SF_OFST 0x00000300
+/* falcona0,falconb0=eeprom_flash */
+/*
+ * FR_AB_EE_VPD_CFG0_REG(128bit):
+ * SPI/VPD configuration register 0
+ */
+#define	FR_AB_EE_VPD_CFG0_REG_OFST 0x00000140
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_EE_SF_FASTRD_EN_LBN 127
+#define	FRF_AB_EE_SF_FASTRD_EN_WIDTH 1
+#define	FRF_AB_EE_SF_CLOCK_DIV_LBN 120
+#define	FRF_AB_EE_SF_CLOCK_DIV_WIDTH 7
+#define	FRF_AB_EE_VPD_WIP_POLL_LBN 119
+#define	FRF_AB_EE_VPD_WIP_POLL_WIDTH 1
+#define	FRF_AB_EE_EE_CLOCK_DIV_LBN 112
+#define	FRF_AB_EE_EE_CLOCK_DIV_WIDTH 7
+#define	FRF_AB_EE_EE_WR_TMR_VALUE_LBN 96
+#define	FRF_AB_EE_EE_WR_TMR_VALUE_WIDTH 16
+#define	FRF_AB_EE_VPDW_LENGTH_LBN 80
+#define	FRF_AB_EE_VPDW_LENGTH_WIDTH 15
+#define	FRF_AB_EE_VPDW_BASE_LBN 64
+#define	FRF_AB_EE_VPDW_BASE_WIDTH 15
+#define	FRF_AB_EE_VPD_WR_CMD_EN_LBN 56
+#define	FRF_AB_EE_VPD_WR_CMD_EN_WIDTH 8
+#define	FRF_AB_EE_VPD_BASE_LBN 32
+#define	FRF_AB_EE_VPD_BASE_WIDTH 24
+#define	FRF_AB_EE_VPD_LENGTH_LBN 16
+#define	FRF_AB_EE_VPD_LENGTH_WIDTH 15
+#define	FRF_AB_EE_VPD_AD_SIZE_LBN 8
+#define	FRF_AB_EE_VPD_AD_SIZE_WIDTH 5
+#define	FRF_AB_EE_VPD_ACCESS_ON_LBN 5
+#define	FRF_AB_EE_VPD_ACCESS_ON_WIDTH 1
+#define	FRF_AB_EE_VPD_ACCESS_BLOCK_LBN 4
+#define	FRF_AB_EE_VPD_ACCESS_BLOCK_WIDTH 1
+#define	FRF_AB_EE_VPD_DEV_SF_SEL_LBN 2
+#define	FRF_AB_EE_VPD_DEV_SF_SEL_WIDTH 1
+#define	FRF_AB_EE_VPD_EN_AD9_MODE_LBN 1
+#define	FRF_AB_EE_VPD_EN_AD9_MODE_WIDTH 1
+#define	FRF_AB_EE_VPD_EN_LBN 0
+#define	FRF_AB_EE_VPD_EN_WIDTH 1
+
+
+/*
+ * FR_AB_PCIE_SD_CTL0123_REG_SF(128bit):
+ * PCIE SerDes control register 0 to 3
+ */
+#define	FR_AB_PCIE_SD_CTL0123_REG_SF_OFST 0x00000320
+/* falcona0,falconb0=eeprom_flash */
+/*
+ * FR_AB_PCIE_SD_CTL0123_REG(128bit):
+ * PCIE SerDes control register 0 to 3
+ */
+#define	FR_AB_PCIE_SD_CTL0123_REG_OFST 0x00000320
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_PCIE_TESTSIG_H_LBN 96
+#define	FRF_AB_PCIE_TESTSIG_H_WIDTH 19
+#define	FRF_AB_PCIE_TESTSIG_L_LBN 64
+#define	FRF_AB_PCIE_TESTSIG_L_WIDTH 19
+#define	FRF_AB_PCIE_OFFSET_LBN 56
+#define	FRF_AB_PCIE_OFFSET_WIDTH 8
+#define	FRF_AB_PCIE_OFFSETEN_H_LBN 55
+#define	FRF_AB_PCIE_OFFSETEN_H_WIDTH 1
+#define	FRF_AB_PCIE_OFFSETEN_L_LBN 54
+#define	FRF_AB_PCIE_OFFSETEN_L_WIDTH 1
+#define	FRF_AB_PCIE_HIVMODE_H_LBN 53
+#define	FRF_AB_PCIE_HIVMODE_H_WIDTH 1
+#define	FRF_AB_PCIE_HIVMODE_L_LBN 52
+#define	FRF_AB_PCIE_HIVMODE_L_WIDTH 1
+#define	FRF_AB_PCIE_PARRESET_H_LBN 51
+#define	FRF_AB_PCIE_PARRESET_H_WIDTH 1
+#define	FRF_AB_PCIE_PARRESET_L_LBN 50
+#define	FRF_AB_PCIE_PARRESET_L_WIDTH 1
+#define	FRF_AB_PCIE_LPBKWDRV_H_LBN 49
+#define	FRF_AB_PCIE_LPBKWDRV_H_WIDTH 1
+#define	FRF_AB_PCIE_LPBKWDRV_L_LBN 48
+#define	FRF_AB_PCIE_LPBKWDRV_L_WIDTH 1
+#define	FRF_AB_PCIE_LPBK_LBN 40
+#define	FRF_AB_PCIE_LPBK_WIDTH 8
+#define	FRF_AB_PCIE_PARLPBK_LBN 32
+#define	FRF_AB_PCIE_PARLPBK_WIDTH 8
+#define	FRF_AB_PCIE_RXTERMADJ_H_LBN 30
+#define	FRF_AB_PCIE_RXTERMADJ_H_WIDTH 2
+#define	FRF_AB_PCIE_RXTERMADJ_L_LBN 28
+#define	FRF_AB_PCIE_RXTERMADJ_L_WIDTH 2
+#define	FFE_AB_PCIE_RXTERMADJ_MIN15PCNT 3
+#define	FFE_AB_PCIE_RXTERMADJ_PL10PCNT 2
+#define	FFE_AB_PCIE_RXTERMADJ_MIN17PCNT 1
+#define	FFE_AB_PCIE_RXTERMADJ_NOMNL 0
+#define	FRF_AB_PCIE_TXTERMADJ_H_LBN 26
+#define	FRF_AB_PCIE_TXTERMADJ_H_WIDTH 2
+#define	FRF_AB_PCIE_TXTERMADJ_L_LBN 24
+#define	FRF_AB_PCIE_TXTERMADJ_L_WIDTH 2
+#define	FFE_AB_PCIE_TXTERMADJ_MIN15PCNT 3
+#define	FFE_AB_PCIE_TXTERMADJ_PL10PCNT 2
+#define	FFE_AB_PCIE_TXTERMADJ_MIN17PCNT 1
+#define	FFE_AB_PCIE_TXTERMADJ_NOMNL 0
+#define	FRF_AB_PCIE_RXEQCTL_H_LBN 18
+#define	FRF_AB_PCIE_RXEQCTL_H_WIDTH 2
+#define	FRF_AB_PCIE_RXEQCTL_L_LBN 16
+#define	FRF_AB_PCIE_RXEQCTL_L_WIDTH 2
+#define	FFE_AB_PCIE_RXEQCTL_OFF_ALT 3
+#define	FFE_AB_PCIE_RXEQCTL_OFF 2
+#define	FFE_AB_PCIE_RXEQCTL_MIN 1
+#define	FFE_AB_PCIE_RXEQCTL_MAX 0
+#define	FRF_AB_PCIE_HIDRV_LBN 8
+#define	FRF_AB_PCIE_HIDRV_WIDTH 8
+#define	FRF_AB_PCIE_LODRV_LBN 0
+#define	FRF_AB_PCIE_LODRV_WIDTH 8
+
+
+/*
+ * FR_AB_PCIE_SD_CTL45_REG_SF(128bit):
+ * PCIE SerDes control register 4 and 5
+ */
+#define	FR_AB_PCIE_SD_CTL45_REG_SF_OFST 0x00000330
+/* falcona0,falconb0=eeprom_flash */
+/*
+ * FR_AB_PCIE_SD_CTL45_REG(128bit):
+ * PCIE SerDes control register 4 and 5
+ */
+#define	FR_AB_PCIE_SD_CTL45_REG_OFST 0x00000330
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_PCIE_DTX7_LBN 60
+#define	FRF_AB_PCIE_DTX7_WIDTH 4
+#define	FRF_AB_PCIE_DTX6_LBN 56
+#define	FRF_AB_PCIE_DTX6_WIDTH 4
+#define	FRF_AB_PCIE_DTX5_LBN 52
+#define	FRF_AB_PCIE_DTX5_WIDTH 4
+#define	FRF_AB_PCIE_DTX4_LBN 48
+#define	FRF_AB_PCIE_DTX4_WIDTH 4
+#define	FRF_AB_PCIE_DTX3_LBN 44
+#define	FRF_AB_PCIE_DTX3_WIDTH 4
+#define	FRF_AB_PCIE_DTX2_LBN 40
+#define	FRF_AB_PCIE_DTX2_WIDTH 4
+#define	FRF_AB_PCIE_DTX1_LBN 36
+#define	FRF_AB_PCIE_DTX1_WIDTH 4
+#define	FRF_AB_PCIE_DTX0_LBN 32
+#define	FRF_AB_PCIE_DTX0_WIDTH 4
+#define	FRF_AB_PCIE_DEQ7_LBN 28
+#define	FRF_AB_PCIE_DEQ7_WIDTH 4
+#define	FRF_AB_PCIE_DEQ6_LBN 24
+#define	FRF_AB_PCIE_DEQ6_WIDTH 4
+#define	FRF_AB_PCIE_DEQ5_LBN 20
+#define	FRF_AB_PCIE_DEQ5_WIDTH 4
+#define	FRF_AB_PCIE_DEQ4_LBN 16
+#define	FRF_AB_PCIE_DEQ4_WIDTH 4
+#define	FRF_AB_PCIE_DEQ3_LBN 12
+#define	FRF_AB_PCIE_DEQ3_WIDTH 4
+#define	FRF_AB_PCIE_DEQ2_LBN 8
+#define	FRF_AB_PCIE_DEQ2_WIDTH 4
+#define	FRF_AB_PCIE_DEQ1_LBN 4
+#define	FRF_AB_PCIE_DEQ1_WIDTH 4
+#define	FRF_AB_PCIE_DEQ0_LBN 0
+#define	FRF_AB_PCIE_DEQ0_WIDTH 4
+
+
+/*
+ * FR_AB_PCIE_PCS_CTL_STAT_REG_SF(128bit):
+ * PCIE PCS control and status register
+ */
+#define	FR_AB_PCIE_PCS_CTL_STAT_REG_SF_OFST 0x00000340
+/* falcona0,falconb0=eeprom_flash */
+/*
+ * FR_AB_PCIE_PCS_CTL_STAT_REG(128bit):
+ * PCIE PCS control and status register
+ */
+#define	FR_AB_PCIE_PCS_CTL_STAT_REG_OFST 0x00000340
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_PCIE_PRBSERRCOUNT0_H_LBN 52
+#define	FRF_AB_PCIE_PRBSERRCOUNT0_H_WIDTH 4
+#define	FRF_AB_PCIE_PRBSERRCOUNT0_L_LBN 48
+#define	FRF_AB_PCIE_PRBSERRCOUNT0_L_WIDTH 4
+#define	FRF_AB_PCIE_PRBSERR_LBN 40
+#define	FRF_AB_PCIE_PRBSERR_WIDTH 8
+#define	FRF_AB_PCIE_PRBSERRH0_LBN 32
+#define	FRF_AB_PCIE_PRBSERRH0_WIDTH 8
+#define	FRF_AB_PCIE_FASTINIT_H_LBN 15
+#define	FRF_AB_PCIE_FASTINIT_H_WIDTH 1
+#define	FRF_AB_PCIE_FASTINIT_L_LBN 14
+#define	FRF_AB_PCIE_FASTINIT_L_WIDTH 1
+#define	FRF_AB_PCIE_CTCDISABLE_H_LBN 13
+#define	FRF_AB_PCIE_CTCDISABLE_H_WIDTH 1
+#define	FRF_AB_PCIE_CTCDISABLE_L_LBN 12
+#define	FRF_AB_PCIE_CTCDISABLE_L_WIDTH 1
+#define	FRF_AB_PCIE_PRBSSYNC_H_LBN 11
+#define	FRF_AB_PCIE_PRBSSYNC_H_WIDTH 1
+#define	FRF_AB_PCIE_PRBSSYNC_L_LBN 10
+#define	FRF_AB_PCIE_PRBSSYNC_L_WIDTH 1
+#define	FRF_AB_PCIE_PRBSERRACK_H_LBN 9
+#define	FRF_AB_PCIE_PRBSERRACK_H_WIDTH 1
+#define	FRF_AB_PCIE_PRBSERRACK_L_LBN 8
+#define	FRF_AB_PCIE_PRBSERRACK_L_WIDTH 1
+#define	FRF_AB_PCIE_PRBSSEL_LBN 0
+#define	FRF_AB_PCIE_PRBSSEL_WIDTH 8
+
+
+/*
+ * FR_AB_HW_INIT_REG_SF(128bit):
+ * Hardware initialization register
+ */
+#define	FR_AB_HW_INIT_REG_SF_OFST 0x00000350
+/* falcona0,falconb0=eeprom_flash */
+/*
+ * FR_AZ_HW_INIT_REG(128bit):
+ * Hardware initialization register
+ */
+#define	FR_AZ_HW_INIT_REG_OFST 0x000000c0
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_BB_BDMRD_CPLF_FULL_LBN 124
+#define	FRF_BB_BDMRD_CPLF_FULL_WIDTH 1
+#define	FRF_BB_PCIE_CPL_TIMEOUT_CTRL_LBN 121
+#define	FRF_BB_PCIE_CPL_TIMEOUT_CTRL_WIDTH 3
+#define	FRF_CZ_TX_MRG_TAGS_LBN 120
+#define	FRF_CZ_TX_MRG_TAGS_WIDTH 1
+#define	FRF_AZ_TRGT_MASK_ALL_LBN 100
+#define	FRF_AZ_TRGT_MASK_ALL_WIDTH 1
+#define	FRF_AZ_DOORBELL_DROP_LBN 92
+#define	FRF_AZ_DOORBELL_DROP_WIDTH 8
+#define	FRF_AB_TX_RREQ_MASK_EN_LBN 76
+#define	FRF_AB_TX_RREQ_MASK_EN_WIDTH 1
+#define	FRF_AB_PE_EIDLE_DIS_LBN 75
+#define	FRF_AB_PE_EIDLE_DIS_WIDTH 1
+#define	FRF_AZ_FC_BLOCKING_EN_LBN 45
+#define	FRF_AZ_FC_BLOCKING_EN_WIDTH 1
+#define	FRF_AZ_B2B_REQ_EN_LBN 44
+#define	FRF_AZ_B2B_REQ_EN_WIDTH 1
+#define	FRF_AZ_POST_WR_MASK_LBN 40
+#define	FRF_AZ_POST_WR_MASK_WIDTH 4
+#define	FRF_AZ_TLP_TC_LBN 34
+#define	FRF_AZ_TLP_TC_WIDTH 3
+#define	FRF_AZ_TLP_ATTR_LBN 32
+#define	FRF_AZ_TLP_ATTR_WIDTH 2
+#define	FRF_AB_INTB_VEC_LBN 24
+#define	FRF_AB_INTB_VEC_WIDTH 5
+#define	FRF_AB_INTA_VEC_LBN 16
+#define	FRF_AB_INTA_VEC_WIDTH 5
+#define	FRF_AZ_WD_TIMER_LBN 8
+#define	FRF_AZ_WD_TIMER_WIDTH 8
+#define	FRF_AZ_US_DISABLE_LBN 5
+#define	FRF_AZ_US_DISABLE_WIDTH 1
+#define	FRF_AZ_TLP_EP_LBN 4
+#define	FRF_AZ_TLP_EP_WIDTH 1
+#define	FRF_AZ_ATTR_SEL_LBN 3
+#define	FRF_AZ_ATTR_SEL_WIDTH 1
+#define	FRF_AZ_TD_SEL_LBN 1
+#define	FRF_AZ_TD_SEL_WIDTH 1
+#define	FRF_AZ_TLP_TD_LBN 0
+#define	FRF_AZ_TLP_TD_WIDTH 1
+
+
+/*
+ * FR_AB_NIC_STAT_REG_SF(128bit):
+ * NIC status register
+ */
+#define	FR_AB_NIC_STAT_REG_SF_OFST 0x00000360
+/* falcona0,falconb0=eeprom_flash */
+/*
+ * FR_AB_NIC_STAT_REG(128bit):
+ * NIC status register
+ */
+#define	FR_AB_NIC_STAT_REG_OFST 0x00000200
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_BB_AER_DIS_LBN 34
+#define	FRF_BB_AER_DIS_WIDTH 1
+#define	FRF_BB_EE_STRAP_EN_LBN 31
+#define	FRF_BB_EE_STRAP_EN_WIDTH 1
+#define	FRF_BB_EE_STRAP_LBN 24
+#define	FRF_BB_EE_STRAP_WIDTH 4
+#define	FRF_BB_REVISION_ID_LBN 17
+#define	FRF_BB_REVISION_ID_WIDTH 7
+#define	FRF_AB_ONCHIP_SRAM_LBN 16
+#define	FRF_AB_ONCHIP_SRAM_WIDTH 1
+#define	FRF_AB_SF_PRST_LBN 9
+#define	FRF_AB_SF_PRST_WIDTH 1
+#define	FRF_AB_EE_PRST_LBN 8
+#define	FRF_AB_EE_PRST_WIDTH 1
+#define	FRF_AB_ATE_MODE_LBN 3
+#define	FRF_AB_ATE_MODE_WIDTH 1
+#define	FRF_AB_STRAP_PINS_LBN 0
+#define	FRF_AB_STRAP_PINS_WIDTH 3
+
+
+/*
+ * FR_AB_GLB_CTL_REG_SF(128bit):
+ * Global control register
+ */
+#define	FR_AB_GLB_CTL_REG_SF_OFST 0x00000370
+/* falcona0,falconb0=eeprom_flash */
+/*
+ * FR_AB_GLB_CTL_REG(128bit):
+ * Global control register
+ */
+#define	FR_AB_GLB_CTL_REG_OFST 0x00000220
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_EXT_PHY_RST_CTL_LBN 63
+#define	FRF_AB_EXT_PHY_RST_CTL_WIDTH 1
+#define	FRF_AB_XAUI_SD_RST_CTL_LBN 62
+#define	FRF_AB_XAUI_SD_RST_CTL_WIDTH 1
+#define	FRF_AB_PCIE_SD_RST_CTL_LBN 61
+#define	FRF_AB_PCIE_SD_RST_CTL_WIDTH 1
+#define	FRF_AA_PCIX_RST_CTL_LBN 60
+#define	FRF_AA_PCIX_RST_CTL_WIDTH 1
+#define	FRF_BB_BIU_RST_CTL_LBN 60
+#define	FRF_BB_BIU_RST_CTL_WIDTH 1
+#define	FRF_AB_PCIE_STKY_RST_CTL_LBN 59
+#define	FRF_AB_PCIE_STKY_RST_CTL_WIDTH 1
+#define	FRF_AB_PCIE_NSTKY_RST_CTL_LBN 58
+#define	FRF_AB_PCIE_NSTKY_RST_CTL_WIDTH 1
+#define	FRF_AB_PCIE_CORE_RST_CTL_LBN 57
+#define	FRF_AB_PCIE_CORE_RST_CTL_WIDTH 1
+#define	FRF_AB_XGRX_RST_CTL_LBN 56
+#define	FRF_AB_XGRX_RST_CTL_WIDTH 1
+#define	FRF_AB_XGTX_RST_CTL_LBN 55
+#define	FRF_AB_XGTX_RST_CTL_WIDTH 1
+#define	FRF_AB_EM_RST_CTL_LBN 54
+#define	FRF_AB_EM_RST_CTL_WIDTH 1
+#define	FRF_AB_EV_RST_CTL_LBN 53
+#define	FRF_AB_EV_RST_CTL_WIDTH 1
+#define	FRF_AB_SR_RST_CTL_LBN 52
+#define	FRF_AB_SR_RST_CTL_WIDTH 1
+#define	FRF_AB_RX_RST_CTL_LBN 51
+#define	FRF_AB_RX_RST_CTL_WIDTH 1
+#define	FRF_AB_TX_RST_CTL_LBN 50
+#define	FRF_AB_TX_RST_CTL_WIDTH 1
+#define	FRF_AB_EE_RST_CTL_LBN 49
+#define	FRF_AB_EE_RST_CTL_WIDTH 1
+#define	FRF_AB_CS_RST_CTL_LBN 48
+#define	FRF_AB_CS_RST_CTL_WIDTH 1
+#define	FRF_AB_HOT_RST_CTL_LBN 40
+#define	FRF_AB_HOT_RST_CTL_WIDTH 2
+#define	FRF_AB_RST_EXT_PHY_LBN 31
+#define	FRF_AB_RST_EXT_PHY_WIDTH 1
+#define	FRF_AB_RST_XAUI_SD_LBN 30
+#define	FRF_AB_RST_XAUI_SD_WIDTH 1
+#define	FRF_AB_RST_PCIE_SD_LBN 29
+#define	FRF_AB_RST_PCIE_SD_WIDTH 1
+#define	FRF_AA_RST_PCIX_LBN 28
+#define	FRF_AA_RST_PCIX_WIDTH 1
+#define	FRF_BB_RST_BIU_LBN 28
+#define	FRF_BB_RST_BIU_WIDTH 1
+#define	FRF_AB_RST_PCIE_STKY_LBN 27
+#define	FRF_AB_RST_PCIE_STKY_WIDTH 1
+#define	FRF_AB_RST_PCIE_NSTKY_LBN 26
+#define	FRF_AB_RST_PCIE_NSTKY_WIDTH 1
+#define	FRF_AB_RST_PCIE_CORE_LBN 25
+#define	FRF_AB_RST_PCIE_CORE_WIDTH 1
+#define	FRF_AB_RST_XGRX_LBN 24
+#define	FRF_AB_RST_XGRX_WIDTH 1
+#define	FRF_AB_RST_XGTX_LBN 23
+#define	FRF_AB_RST_XGTX_WIDTH 1
+#define	FRF_AB_RST_EM_LBN 22
+#define	FRF_AB_RST_EM_WIDTH 1
+#define	FRF_AB_RST_EV_LBN 21
+#define	FRF_AB_RST_EV_WIDTH 1
+#define	FRF_AB_RST_SR_LBN 20
+#define	FRF_AB_RST_SR_WIDTH 1
+#define	FRF_AB_RST_RX_LBN 19
+#define	FRF_AB_RST_RX_WIDTH 1
+#define	FRF_AB_RST_TX_LBN 18
+#define	FRF_AB_RST_TX_WIDTH 1
+#define	FRF_AB_RST_SF_LBN 17
+#define	FRF_AB_RST_SF_WIDTH 1
+#define	FRF_AB_RST_CS_LBN 16
+#define	FRF_AB_RST_CS_WIDTH 1
+#define	FRF_AB_INT_RST_DUR_LBN 4
+#define	FRF_AB_INT_RST_DUR_WIDTH 3
+#define	FRF_AB_EXT_PHY_RST_DUR_LBN 1
+#define	FRF_AB_EXT_PHY_RST_DUR_WIDTH 3
+#define	FFE_AB_EXT_PHY_RST_DUR_10240US 7
+#define	FFE_AB_EXT_PHY_RST_DUR_5120US 6
+#define	FFE_AB_EXT_PHY_RST_DUR_2560US 5
+#define	FFE_AB_EXT_PHY_RST_DUR_1280US 4
+#define	FFE_AB_EXT_PHY_RST_DUR_640US 3
+#define	FFE_AB_EXT_PHY_RST_DUR_320US 2
+#define	FFE_AB_EXT_PHY_RST_DUR_160US 1
+#define	FFE_AB_EXT_PHY_RST_DUR_80US 0
+#define	FRF_AB_SWRST_LBN 0
+#define	FRF_AB_SWRST_WIDTH 1
+
+
+/*
+ * FR_AZ_IOM_IND_ADR_REG(32bit):
+ * IO-mapped indirect access address register
+ */
+#define	FR_AZ_IOM_IND_ADR_REG_OFST 0x00000000
+/* falcona0,falconb0,sienaa0=net_func_bar0 */
+
+#define	FRF_AZ_IOM_AUTO_ADR_INC_EN_LBN 24
+#define	FRF_AZ_IOM_AUTO_ADR_INC_EN_WIDTH 1
+#define	FRF_AZ_IOM_IND_ADR_LBN 0
+#define	FRF_AZ_IOM_IND_ADR_WIDTH 24
+
+
+/*
+ * FR_AZ_IOM_IND_DAT_REG(32bit):
+ * IO-mapped indirect access data register
+ */
+#define	FR_AZ_IOM_IND_DAT_REG_OFST 0x00000004
+/* falcona0,falconb0,sienaa0=net_func_bar0 */
+
+#define	FRF_AZ_IOM_IND_DAT_LBN 0
+#define	FRF_AZ_IOM_IND_DAT_WIDTH 32
+
+
+/*
+ * FR_AZ_ADR_REGION_REG(128bit):
+ * Address region register
+ */
+#define	FR_AZ_ADR_REGION_REG_OFST 0x00000000
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_ADR_REGION3_LBN 96
+#define	FRF_AZ_ADR_REGION3_WIDTH 18
+#define	FRF_AZ_ADR_REGION2_LBN 64
+#define	FRF_AZ_ADR_REGION2_WIDTH 18
+#define	FRF_AZ_ADR_REGION1_LBN 32
+#define	FRF_AZ_ADR_REGION1_WIDTH 18
+#define	FRF_AZ_ADR_REGION0_LBN 0
+#define	FRF_AZ_ADR_REGION0_WIDTH 18
+
+
+/*
+ * FR_AZ_INT_EN_REG_KER(128bit):
+ * Kernel driver Interrupt enable register
+ */
+#define	FR_AZ_INT_EN_REG_KER_OFST 0x00000010
+/* falcona0,falconb0,sienaa0=net_func_bar2 */
+
+#define	FRF_AZ_KER_INT_LEVE_SEL_LBN 8
+#define	FRF_AZ_KER_INT_LEVE_SEL_WIDTH 6
+#define	FRF_AZ_KER_INT_CHAR_LBN 4
+#define	FRF_AZ_KER_INT_CHAR_WIDTH 1
+#define	FRF_AZ_KER_INT_KER_LBN 3
+#define	FRF_AZ_KER_INT_KER_WIDTH 1
+#define	FRF_AZ_DRV_INT_EN_KER_LBN 0
+#define	FRF_AZ_DRV_INT_EN_KER_WIDTH 1
+
+
+/*
+ * FR_AZ_INT_EN_REG_CHAR(128bit):
+ * Char Driver interrupt enable register
+ */
+#define	FR_AZ_INT_EN_REG_CHAR_OFST 0x00000020
+/* falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_CHAR_INT_LEVE_SEL_LBN 8
+#define	FRF_AZ_CHAR_INT_LEVE_SEL_WIDTH 6
+#define	FRF_AZ_CHAR_INT_CHAR_LBN 4
+#define	FRF_AZ_CHAR_INT_CHAR_WIDTH 1
+#define	FRF_AZ_CHAR_INT_KER_LBN 3
+#define	FRF_AZ_CHAR_INT_KER_WIDTH 1
+#define	FRF_AZ_DRV_INT_EN_CHAR_LBN 0
+#define	FRF_AZ_DRV_INT_EN_CHAR_WIDTH 1
+
+
+/*
+ * FR_AZ_INT_ADR_REG_KER(128bit):
+ * Interrupt host address for Kernel driver
+ */
+#define	FR_AZ_INT_ADR_REG_KER_OFST 0x00000030
+/* falcona0,falconb0,sienaa0=net_func_bar2 */
+
+#define	FRF_AZ_NORM_INT_VEC_DIS_KER_LBN 64
+#define	FRF_AZ_NORM_INT_VEC_DIS_KER_WIDTH 1
+#define	FRF_AZ_INT_ADR_KER_LBN 0
+#define	FRF_AZ_INT_ADR_KER_WIDTH 64
+#define	FRF_AZ_INT_ADR_KER_DW0_LBN 0
+#define	FRF_AZ_INT_ADR_KER_DW0_WIDTH 32
+#define	FRF_AZ_INT_ADR_KER_DW1_LBN 32
+#define	FRF_AZ_INT_ADR_KER_DW1_WIDTH 32
+
+
+/*
+ * FR_AZ_INT_ADR_REG_CHAR(128bit):
+ * Interrupt host address for Char driver
+ */
+#define	FR_AZ_INT_ADR_REG_CHAR_OFST 0x00000040
+/* falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_NORM_INT_VEC_DIS_CHAR_LBN 64
+#define	FRF_AZ_NORM_INT_VEC_DIS_CHAR_WIDTH 1
+#define	FRF_AZ_INT_ADR_CHAR_LBN 0
+#define	FRF_AZ_INT_ADR_CHAR_WIDTH 64
+#define	FRF_AZ_INT_ADR_CHAR_DW0_LBN 0
+#define	FRF_AZ_INT_ADR_CHAR_DW0_WIDTH 32
+#define	FRF_AZ_INT_ADR_CHAR_DW1_LBN 32
+#define	FRF_AZ_INT_ADR_CHAR_DW1_WIDTH 32
+
+
+/*
+ * FR_AA_INT_ACK_KER(32bit):
+ * Kernel interrupt acknowledge register
+ */
+#define	FR_AA_INT_ACK_KER_OFST 0x00000050
+/* falcona0=net_func_bar2 */
+
+#define	FRF_AA_INT_ACK_KER_FIELD_LBN 0
+#define	FRF_AA_INT_ACK_KER_FIELD_WIDTH 32
+
+
+/*
+ * FR_BZ_INT_ISR0_REG(128bit):
+ * Function 0 Interrupt Acknowlege Status register
+ */
+#define	FR_BZ_INT_ISR0_REG_OFST 0x00000090
+/* falconb0,sienaa0=net_func_bar2 */
+
+#define	FRF_BZ_INT_ISR_REG_LBN 0
+#define	FRF_BZ_INT_ISR_REG_WIDTH 64
+#define	FRF_BZ_INT_ISR_REG_DW0_LBN 0
+#define	FRF_BZ_INT_ISR_REG_DW0_WIDTH 32
+#define	FRF_BZ_INT_ISR_REG_DW1_LBN 32
+#define	FRF_BZ_INT_ISR_REG_DW1_WIDTH 32
+
+
+/*
+ * FR_AB_EE_SPI_HCMD_REG(128bit):
+ * SPI host command register
+ */
+#define	FR_AB_EE_SPI_HCMD_REG_OFST 0x00000100
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_EE_SPI_HCMD_CMD_EN_LBN 31
+#define	FRF_AB_EE_SPI_HCMD_CMD_EN_WIDTH 1
+#define	FRF_AB_EE_WR_TIMER_ACTIVE_LBN 28
+#define	FRF_AB_EE_WR_TIMER_ACTIVE_WIDTH 1
+#define	FRF_AB_EE_SPI_HCMD_SF_SEL_LBN 24
+#define	FRF_AB_EE_SPI_HCMD_SF_SEL_WIDTH 1
+#define	FRF_AB_EE_SPI_HCMD_DABCNT_LBN 16
+#define	FRF_AB_EE_SPI_HCMD_DABCNT_WIDTH 5
+#define	FRF_AB_EE_SPI_HCMD_READ_LBN 15
+#define	FRF_AB_EE_SPI_HCMD_READ_WIDTH 1
+#define	FRF_AB_EE_SPI_HCMD_DUBCNT_LBN 12
+#define	FRF_AB_EE_SPI_HCMD_DUBCNT_WIDTH 2
+#define	FRF_AB_EE_SPI_HCMD_ADBCNT_LBN 8
+#define	FRF_AB_EE_SPI_HCMD_ADBCNT_WIDTH 2
+#define	FRF_AB_EE_SPI_HCMD_ENC_LBN 0
+#define	FRF_AB_EE_SPI_HCMD_ENC_WIDTH 8
+
+
+/*
+ * FR_CZ_USR_EV_CFG(32bit):
+ * User Level Event Configuration register
+ */
+#define	FR_CZ_USR_EV_CFG_OFST 0x00000100
+/* sienaa0=net_func_bar2 */
+
+#define	FRF_CZ_USREV_DIS_LBN 16
+#define	FRF_CZ_USREV_DIS_WIDTH 1
+#define	FRF_CZ_DFLT_EVQ_LBN 0
+#define	FRF_CZ_DFLT_EVQ_WIDTH 10
+
+
+/*
+ * FR_AB_EE_SPI_HADR_REG(128bit):
+ * SPI host address register
+ */
+#define	FR_AB_EE_SPI_HADR_REG_OFST 0x00000110
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_EE_SPI_HADR_DUBYTE_LBN 24
+#define	FRF_AB_EE_SPI_HADR_DUBYTE_WIDTH 8
+#define	FRF_AB_EE_SPI_HADR_ADR_LBN 0
+#define	FRF_AB_EE_SPI_HADR_ADR_WIDTH 24
+
+
+/*
+ * FR_AB_EE_SPI_HDATA_REG(128bit):
+ * SPI host data register
+ */
+#define	FR_AB_EE_SPI_HDATA_REG_OFST 0x00000120
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_EE_SPI_HDATA3_LBN 96
+#define	FRF_AB_EE_SPI_HDATA3_WIDTH 32
+#define	FRF_AB_EE_SPI_HDATA2_LBN 64
+#define	FRF_AB_EE_SPI_HDATA2_WIDTH 32
+#define	FRF_AB_EE_SPI_HDATA1_LBN 32
+#define	FRF_AB_EE_SPI_HDATA1_WIDTH 32
+#define	FRF_AB_EE_SPI_HDATA0_LBN 0
+#define	FRF_AB_EE_SPI_HDATA0_WIDTH 32
+
+
+/*
+ * FR_AB_EE_BASE_PAGE_REG(128bit):
+ * Expansion ROM base mirror register
+ */
+#define	FR_AB_EE_BASE_PAGE_REG_OFST 0x00000130
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_EE_EXPROM_MASK_LBN 16
+#define	FRF_AB_EE_EXPROM_MASK_WIDTH 13
+#define	FRF_AB_EE_EXP_ROM_WINDOW_BASE_LBN 0
+#define	FRF_AB_EE_EXP_ROM_WINDOW_BASE_WIDTH 13
+
+
+/*
+ * FR_AB_EE_VPD_SW_CNTL_REG(128bit):
+ * VPD access SW control register
+ */
+#define	FR_AB_EE_VPD_SW_CNTL_REG_OFST 0x00000150
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_EE_VPD_CYCLE_PENDING_LBN 31
+#define	FRF_AB_EE_VPD_CYCLE_PENDING_WIDTH 1
+#define	FRF_AB_EE_VPD_CYC_WRITE_LBN 28
+#define	FRF_AB_EE_VPD_CYC_WRITE_WIDTH 1
+#define	FRF_AB_EE_VPD_CYC_ADR_LBN 0
+#define	FRF_AB_EE_VPD_CYC_ADR_WIDTH 15
+
+
+/*
+ * FR_AB_EE_VPD_SW_DATA_REG(128bit):
+ * VPD access SW data register
+ */
+#define	FR_AB_EE_VPD_SW_DATA_REG_OFST 0x00000160
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_EE_VPD_CYC_DAT_LBN 0
+#define	FRF_AB_EE_VPD_CYC_DAT_WIDTH 32
+
+
+/*
+ * FR_BB_PCIE_CORE_INDIRECT_REG(64bit):
+ * Indirect Access to PCIE Core registers
+ */
+#define	FR_BB_PCIE_CORE_INDIRECT_REG_OFST 0x000001f0
+/* falconb0=net_func_bar2 */
+
+#define	FRF_BB_PCIE_CORE_TARGET_DATA_LBN 32
+#define	FRF_BB_PCIE_CORE_TARGET_DATA_WIDTH 32
+#define	FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR_LBN 15
+#define	FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR_WIDTH 1
+#define	FRF_BB_PCIE_CORE_TARGET_REG_ADRS_LBN 0
+#define	FRF_BB_PCIE_CORE_TARGET_REG_ADRS_WIDTH 12
+
+
+/*
+ * FR_AB_GPIO_CTL_REG(128bit):
+ * GPIO control register
+ */
+#define	FR_AB_GPIO_CTL_REG_OFST 0x00000210
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GPIO15_OEN_LBN 63
+#define	FRF_AB_GPIO15_OEN_WIDTH 1
+#define	FRF_AB_GPIO14_OEN_LBN 62
+#define	FRF_AB_GPIO14_OEN_WIDTH 1
+#define	FRF_AB_GPIO13_OEN_LBN 61
+#define	FRF_AB_GPIO13_OEN_WIDTH 1
+#define	FRF_AB_GPIO12_OEN_LBN 60
+#define	FRF_AB_GPIO12_OEN_WIDTH 1
+#define	FRF_AB_GPIO11_OEN_LBN 59
+#define	FRF_AB_GPIO11_OEN_WIDTH 1
+#define	FRF_AB_GPIO10_OEN_LBN 58
+#define	FRF_AB_GPIO10_OEN_WIDTH 1
+#define	FRF_AB_GPIO9_OEN_LBN 57
+#define	FRF_AB_GPIO9_OEN_WIDTH 1
+#define	FRF_AB_GPIO8_OEN_LBN 56
+#define	FRF_AB_GPIO8_OEN_WIDTH 1
+#define	FRF_AB_GPIO15_OUT_LBN 55
+#define	FRF_AB_GPIO15_OUT_WIDTH 1
+#define	FRF_AB_GPIO14_OUT_LBN 54
+#define	FRF_AB_GPIO14_OUT_WIDTH 1
+#define	FRF_AB_GPIO13_OUT_LBN 53
+#define	FRF_AB_GPIO13_OUT_WIDTH 1
+#define	FRF_AB_GPIO12_OUT_LBN 52
+#define	FRF_AB_GPIO12_OUT_WIDTH 1
+#define	FRF_AB_GPIO11_OUT_LBN 51
+#define	FRF_AB_GPIO11_OUT_WIDTH 1
+#define	FRF_AB_GPIO10_OUT_LBN 50
+#define	FRF_AB_GPIO10_OUT_WIDTH 1
+#define	FRF_AB_GPIO9_OUT_LBN 49
+#define	FRF_AB_GPIO9_OUT_WIDTH 1
+#define	FRF_AB_GPIO8_OUT_LBN 48
+#define	FRF_AB_GPIO8_OUT_WIDTH 1
+#define	FRF_AB_GPIO15_IN_LBN 47
+#define	FRF_AB_GPIO15_IN_WIDTH 1
+#define	FRF_AB_GPIO14_IN_LBN 46
+#define	FRF_AB_GPIO14_IN_WIDTH 1
+#define	FRF_AB_GPIO13_IN_LBN 45
+#define	FRF_AB_GPIO13_IN_WIDTH 1
+#define	FRF_AB_GPIO12_IN_LBN 44
+#define	FRF_AB_GPIO12_IN_WIDTH 1
+#define	FRF_AB_GPIO11_IN_LBN 43
+#define	FRF_AB_GPIO11_IN_WIDTH 1
+#define	FRF_AB_GPIO10_IN_LBN 42
+#define	FRF_AB_GPIO10_IN_WIDTH 1
+#define	FRF_AB_GPIO9_IN_LBN 41
+#define	FRF_AB_GPIO9_IN_WIDTH 1
+#define	FRF_AB_GPIO8_IN_LBN 40
+#define	FRF_AB_GPIO8_IN_WIDTH 1
+#define	FRF_AB_GPIO15_PWRUP_VALUE_LBN 39
+#define	FRF_AB_GPIO15_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO14_PWRUP_VALUE_LBN 38
+#define	FRF_AB_GPIO14_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO13_PWRUP_VALUE_LBN 37
+#define	FRF_AB_GPIO13_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO12_PWRUP_VALUE_LBN 36
+#define	FRF_AB_GPIO12_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO11_PWRUP_VALUE_LBN 35
+#define	FRF_AB_GPIO11_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO10_PWRUP_VALUE_LBN 34
+#define	FRF_AB_GPIO10_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO9_PWRUP_VALUE_LBN 33
+#define	FRF_AB_GPIO9_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO8_PWRUP_VALUE_LBN 32
+#define	FRF_AB_GPIO8_PWRUP_VALUE_WIDTH 1
+#define	FRF_BB_CLK156_OUT_EN_LBN 31
+#define	FRF_BB_CLK156_OUT_EN_WIDTH 1
+#define	FRF_BB_USE_NIC_CLK_LBN 30
+#define	FRF_BB_USE_NIC_CLK_WIDTH 1
+#define	FRF_AB_GPIO5_OEN_LBN 29
+#define	FRF_AB_GPIO5_OEN_WIDTH 1
+#define	FRF_AB_GPIO4_OEN_LBN 28
+#define	FRF_AB_GPIO4_OEN_WIDTH 1
+#define	FRF_AB_GPIO3_OEN_LBN 27
+#define	FRF_AB_GPIO3_OEN_WIDTH 1
+#define	FRF_AB_GPIO2_OEN_LBN 26
+#define	FRF_AB_GPIO2_OEN_WIDTH 1
+#define	FRF_AB_GPIO1_OEN_LBN 25
+#define	FRF_AB_GPIO1_OEN_WIDTH 1
+#define	FRF_AB_GPIO0_OEN_LBN 24
+#define	FRF_AB_GPIO0_OEN_WIDTH 1
+#define	FRF_AB_GPIO5_OUT_LBN 21
+#define	FRF_AB_GPIO5_OUT_WIDTH 1
+#define	FRF_AB_GPIO4_OUT_LBN 20
+#define	FRF_AB_GPIO4_OUT_WIDTH 1
+#define	FRF_AB_GPIO3_OUT_LBN 19
+#define	FRF_AB_GPIO3_OUT_WIDTH 1
+#define	FRF_AB_GPIO2_OUT_LBN 18
+#define	FRF_AB_GPIO2_OUT_WIDTH 1
+#define	FRF_AB_GPIO1_OUT_LBN 17
+#define	FRF_AB_GPIO1_OUT_WIDTH 1
+#define	FRF_AB_GPIO0_OUT_LBN 16
+#define	FRF_AB_GPIO0_OUT_WIDTH 1
+#define	FRF_AB_GPIO5_IN_LBN 13
+#define	FRF_AB_GPIO5_IN_WIDTH 1
+#define	FRF_AB_GPIO4_IN_LBN 12
+#define	FRF_AB_GPIO4_IN_WIDTH 1
+#define	FRF_AB_GPIO3_IN_LBN 11
+#define	FRF_AB_GPIO3_IN_WIDTH 1
+#define	FRF_AB_GPIO2_IN_LBN 10
+#define	FRF_AB_GPIO2_IN_WIDTH 1
+#define	FRF_AB_GPIO1_IN_LBN 9
+#define	FRF_AB_GPIO1_IN_WIDTH 1
+#define	FRF_AB_GPIO0_IN_LBN 8
+#define	FRF_AB_GPIO0_IN_WIDTH 1
+#define	FRF_AB_GPIO5_PWRUP_VALUE_LBN 5
+#define	FRF_AB_GPIO5_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO4_PWRUP_VALUE_LBN 4
+#define	FRF_AB_GPIO4_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO3_PWRUP_VALUE_LBN 3
+#define	FRF_AB_GPIO3_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO2_PWRUP_VALUE_LBN 2
+#define	FRF_AB_GPIO2_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO1_PWRUP_VALUE_LBN 1
+#define	FRF_AB_GPIO1_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO0_PWRUP_VALUE_LBN 0
+#define	FRF_AB_GPIO0_PWRUP_VALUE_WIDTH 1
+
+
+/*
+ * FR_AZ_FATAL_INTR_REG_KER(128bit):
+ * Fatal interrupt register for Kernel
+ */
+#define	FR_AZ_FATAL_INTR_REG_KER_OFST 0x00000230
+/* falcona0,falconb0,sienaa0=net_func_bar2 */
+
+#define	FRF_CZ_SRAM_PERR_INT_P_KER_EN_LBN 44
+#define	FRF_CZ_SRAM_PERR_INT_P_KER_EN_WIDTH 1
+#define	FRF_AB_PCI_BUSERR_INT_KER_EN_LBN 43
+#define	FRF_AB_PCI_BUSERR_INT_KER_EN_WIDTH 1
+#define	FRF_CZ_MBU_PERR_INT_KER_EN_LBN 43
+#define	FRF_CZ_MBU_PERR_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_SRAM_OOB_INT_KER_EN_LBN 42
+#define	FRF_AZ_SRAM_OOB_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_BUFID_OOB_INT_KER_EN_LBN 41
+#define	FRF_AZ_BUFID_OOB_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_MEM_PERR_INT_KER_EN_LBN 40
+#define	FRF_AZ_MEM_PERR_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_RBUF_OWN_INT_KER_EN_LBN 39
+#define	FRF_AZ_RBUF_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_TBUF_OWN_INT_KER_EN_LBN 38
+#define	FRF_AZ_TBUF_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_RDESCQ_OWN_INT_KER_EN_LBN 37
+#define	FRF_AZ_RDESCQ_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_TDESCQ_OWN_INT_KER_EN_LBN 36
+#define	FRF_AZ_TDESCQ_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_EVQ_OWN_INT_KER_EN_LBN 35
+#define	FRF_AZ_EVQ_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_EVF_OFLO_INT_KER_EN_LBN 34
+#define	FRF_AZ_EVF_OFLO_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_ILL_ADR_INT_KER_EN_LBN 33
+#define	FRF_AZ_ILL_ADR_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_SRM_PERR_INT_KER_EN_LBN 32
+#define	FRF_AZ_SRM_PERR_INT_KER_EN_WIDTH 1
+#define	FRF_CZ_SRAM_PERR_INT_P_KER_LBN 12
+#define	FRF_CZ_SRAM_PERR_INT_P_KER_WIDTH 1
+#define	FRF_AB_PCI_BUSERR_INT_KER_LBN 11
+#define	FRF_AB_PCI_BUSERR_INT_KER_WIDTH 1
+#define	FRF_CZ_MBU_PERR_INT_KER_LBN 11
+#define	FRF_CZ_MBU_PERR_INT_KER_WIDTH 1
+#define	FRF_AZ_SRAM_OOB_INT_KER_LBN 10
+#define	FRF_AZ_SRAM_OOB_INT_KER_WIDTH 1
+#define	FRF_AZ_BUFID_DC_OOB_INT_KER_LBN 9
+#define	FRF_AZ_BUFID_DC_OOB_INT_KER_WIDTH 1
+#define	FRF_AZ_MEM_PERR_INT_KER_LBN 8
+#define	FRF_AZ_MEM_PERR_INT_KER_WIDTH 1
+#define	FRF_AZ_RBUF_OWN_INT_KER_LBN 7
+#define	FRF_AZ_RBUF_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_TBUF_OWN_INT_KER_LBN 6
+#define	FRF_AZ_TBUF_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_RDESCQ_OWN_INT_KER_LBN 5
+#define	FRF_AZ_RDESCQ_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_TDESCQ_OWN_INT_KER_LBN 4
+#define	FRF_AZ_TDESCQ_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_EVQ_OWN_INT_KER_LBN 3
+#define	FRF_AZ_EVQ_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_EVF_OFLO_INT_KER_LBN 2
+#define	FRF_AZ_EVF_OFLO_INT_KER_WIDTH 1
+#define	FRF_AZ_ILL_ADR_INT_KER_LBN 1
+#define	FRF_AZ_ILL_ADR_INT_KER_WIDTH 1
+#define	FRF_AZ_SRM_PERR_INT_KER_LBN 0
+#define	FRF_AZ_SRM_PERR_INT_KER_WIDTH 1
+
+
+/*
+ * FR_AZ_FATAL_INTR_REG_CHAR(128bit):
+ * Fatal interrupt register for Char
+ */
+#define	FR_AZ_FATAL_INTR_REG_CHAR_OFST 0x00000240
+/* falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_CZ_SRAM_PERR_INT_P_CHAR_EN_LBN 44
+#define	FRF_CZ_SRAM_PERR_INT_P_CHAR_EN_WIDTH 1
+#define	FRF_AB_PCI_BUSERR_INT_CHAR_EN_LBN 43
+#define	FRF_AB_PCI_BUSERR_INT_CHAR_EN_WIDTH 1
+#define	FRF_CZ_MBU_PERR_INT_CHAR_EN_LBN 43
+#define	FRF_CZ_MBU_PERR_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_SRAM_OOB_INT_CHAR_EN_LBN 42
+#define	FRF_AZ_SRAM_OOB_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_BUFID_OOB_INT_CHAR_EN_LBN 41
+#define	FRF_AZ_BUFID_OOB_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_MEM_PERR_INT_CHAR_EN_LBN 40
+#define	FRF_AZ_MEM_PERR_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_RBUF_OWN_INT_CHAR_EN_LBN 39
+#define	FRF_AZ_RBUF_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_TBUF_OWN_INT_CHAR_EN_LBN 38
+#define	FRF_AZ_TBUF_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_RDESCQ_OWN_INT_CHAR_EN_LBN 37
+#define	FRF_AZ_RDESCQ_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_TDESCQ_OWN_INT_CHAR_EN_LBN 36
+#define	FRF_AZ_TDESCQ_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_EVQ_OWN_INT_CHAR_EN_LBN 35
+#define	FRF_AZ_EVQ_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_EVF_OFLO_INT_CHAR_EN_LBN 34
+#define	FRF_AZ_EVF_OFLO_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_ILL_ADR_INT_CHAR_EN_LBN 33
+#define	FRF_AZ_ILL_ADR_INT_CHAR_EN_WIDTH 1
+#define	FRF_AZ_SRM_PERR_INT_CHAR_EN_LBN 32
+#define	FRF_AZ_SRM_PERR_INT_CHAR_EN_WIDTH 1
+#define	FRF_CZ_SRAM_PERR_INT_P_CHAR_LBN 12
+#define	FRF_CZ_SRAM_PERR_INT_P_CHAR_WIDTH 1
+#define	FRF_AB_PCI_BUSERR_INT_CHAR_LBN 11
+#define	FRF_AB_PCI_BUSERR_INT_CHAR_WIDTH 1
+#define	FRF_CZ_MBU_PERR_INT_CHAR_LBN 11
+#define	FRF_CZ_MBU_PERR_INT_CHAR_WIDTH 1
+#define	FRF_AZ_SRAM_OOB_INT_CHAR_LBN 10
+#define	FRF_AZ_SRAM_OOB_INT_CHAR_WIDTH 1
+#define	FRF_AZ_BUFID_DC_OOB_INT_CHAR_LBN 9
+#define	FRF_AZ_BUFID_DC_OOB_INT_CHAR_WIDTH 1
+#define	FRF_AZ_MEM_PERR_INT_CHAR_LBN 8
+#define	FRF_AZ_MEM_PERR_INT_CHAR_WIDTH 1
+#define	FRF_AZ_RBUF_OWN_INT_CHAR_LBN 7
+#define	FRF_AZ_RBUF_OWN_INT_CHAR_WIDTH 1
+#define	FRF_AZ_TBUF_OWN_INT_CHAR_LBN 6
+#define	FRF_AZ_TBUF_OWN_INT_CHAR_WIDTH 1
+#define	FRF_AZ_RDESCQ_OWN_INT_CHAR_LBN 5
+#define	FRF_AZ_RDESCQ_OWN_INT_CHAR_WIDTH 1
+#define	FRF_AZ_TDESCQ_OWN_INT_CHAR_LBN 4
+#define	FRF_AZ_TDESCQ_OWN_INT_CHAR_WIDTH 1
+#define	FRF_AZ_EVQ_OWN_INT_CHAR_LBN 3
+#define	FRF_AZ_EVQ_OWN_INT_CHAR_WIDTH 1
+#define	FRF_AZ_EVF_OFLO_INT_CHAR_LBN 2
+#define	FRF_AZ_EVF_OFLO_INT_CHAR_WIDTH 1
+#define	FRF_AZ_ILL_ADR_INT_CHAR_LBN 1
+#define	FRF_AZ_ILL_ADR_INT_CHAR_WIDTH 1
+#define	FRF_AZ_SRM_PERR_INT_CHAR_LBN 0
+#define	FRF_AZ_SRM_PERR_INT_CHAR_WIDTH 1
+
+
+/*
+ * FR_AZ_DP_CTRL_REG(128bit):
+ * Datapath control register
+ */
+#define	FR_AZ_DP_CTRL_REG_OFST 0x00000250
+/* falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_FLS_EVQ_ID_LBN 0
+#define	FRF_AZ_FLS_EVQ_ID_WIDTH 12
+
+
+/*
+ * FR_AZ_MEM_STAT_REG(128bit):
+ * Memory status register
+ */
+#define	FR_AZ_MEM_STAT_REG_OFST 0x00000260
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MEM_PERR_VEC_LBN 53
+#define	FRF_AB_MEM_PERR_VEC_WIDTH 40
+#define	FRF_AB_MEM_PERR_VEC_DW0_LBN 53
+#define	FRF_AB_MEM_PERR_VEC_DW0_WIDTH 32
+#define	FRF_AB_MEM_PERR_VEC_DW1_LBN 85
+#define	FRF_AB_MEM_PERR_VEC_DW1_WIDTH 6
+#define	FRF_AB_MBIST_CORR_LBN 38
+#define	FRF_AB_MBIST_CORR_WIDTH 15
+#define	FRF_AB_MBIST_ERR_LBN 0
+#define	FRF_AB_MBIST_ERR_WIDTH 40
+#define	FRF_AB_MBIST_ERR_DW0_LBN 0
+#define	FRF_AB_MBIST_ERR_DW0_WIDTH 32
+#define	FRF_AB_MBIST_ERR_DW1_LBN 32
+#define	FRF_AB_MBIST_ERR_DW1_WIDTH 6
+#define	FRF_CZ_MEM_PERR_VEC_LBN 0
+#define	FRF_CZ_MEM_PERR_VEC_WIDTH 35
+#define	FRF_CZ_MEM_PERR_VEC_DW0_LBN 0
+#define	FRF_CZ_MEM_PERR_VEC_DW0_WIDTH 32
+#define	FRF_CZ_MEM_PERR_VEC_DW1_LBN 32
+#define	FRF_CZ_MEM_PERR_VEC_DW1_WIDTH 3
+
+
+/*
+ * FR_PORT0_CS_DEBUG_REG(128bit):
+ * Debug register
+ */
+
+#define	FR_AZ_CS_DEBUG_REG_OFST 0x00000270
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GLB_DEBUG2_SEL_LBN 50
+#define	FRF_AB_GLB_DEBUG2_SEL_WIDTH 3
+#define	FRF_AB_DEBUG_BLK_SEL2_LBN 47
+#define	FRF_AB_DEBUG_BLK_SEL2_WIDTH 3
+#define	FRF_AB_DEBUG_BLK_SEL1_LBN 44
+#define	FRF_AB_DEBUG_BLK_SEL1_WIDTH 3
+#define	FRF_AB_DEBUG_BLK_SEL0_LBN 41
+#define	FRF_AB_DEBUG_BLK_SEL0_WIDTH 3
+#define	FRF_CZ_CS_PORT_NUM_LBN 40
+#define	FRF_CZ_CS_PORT_NUM_WIDTH 2
+#define	FRF_AB_MISC_DEBUG_ADDR_LBN 36
+#define	FRF_AB_MISC_DEBUG_ADDR_WIDTH 5
+#define	FRF_CZ_CS_RESERVED_LBN 36
+#define	FRF_CZ_CS_RESERVED_WIDTH 4
+#define	FRF_AB_SERDES_DEBUG_ADDR_LBN 31
+#define	FRF_AB_SERDES_DEBUG_ADDR_WIDTH 5
+#define	FRF_CZ_CS_PORT_FPE_DW0_LBN 1
+#define	FRF_CZ_CS_PORT_FPE_DW0_WIDTH 32
+#define	FRF_CZ_CS_PORT_FPE_DW1_LBN 33
+#define	FRF_CZ_CS_PORT_FPE_DW1_WIDTH 3
+#define	FRF_CZ_CS_PORT_FPE_LBN 1
+#define	FRF_CZ_CS_PORT_FPE_WIDTH 35
+#define	FRF_AB_EM_DEBUG_ADDR_LBN 26
+#define	FRF_AB_EM_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_SR_DEBUG_ADDR_LBN 21
+#define	FRF_AB_SR_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_EV_DEBUG_ADDR_LBN 16
+#define	FRF_AB_EV_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_RX_DEBUG_ADDR_LBN 11
+#define	FRF_AB_RX_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_TX_DEBUG_ADDR_LBN 6
+#define	FRF_AB_TX_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_CS_BIU_DEBUG_ADDR_LBN 1
+#define	FRF_AB_CS_BIU_DEBUG_ADDR_WIDTH 5
+#define	FRF_AZ_CS_DEBUG_EN_LBN 0
+#define	FRF_AZ_CS_DEBUG_EN_WIDTH 1
+
+
+/*
+ * FR_AZ_DRIVER_REG(128bit):
+ * Driver scratch register [0-7]
+ */
+#define	FR_AZ_DRIVER_REG_OFST 0x00000280
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_DRIVER_REG_STEP 16
+#define	FR_AZ_DRIVER_REG_ROWS 8
+
+#define	FRF_AZ_DRIVER_DW0_LBN 0
+#define	FRF_AZ_DRIVER_DW0_WIDTH 32
+
+
+/*
+ * FR_AZ_ALTERA_BUILD_REG(128bit):
+ * Altera build register
+ */
+#define	FR_AZ_ALTERA_BUILD_REG_OFST 0x00000300
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_ALTERA_BUILD_VER_LBN 0
+#define	FRF_AZ_ALTERA_BUILD_VER_WIDTH 32
+
+
+/*
+ * FR_AZ_CSR_SPARE_REG(128bit):
+ * Spare register
+ */
+#define	FR_AZ_CSR_SPARE_REG_OFST 0x00000310
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_MEM_PERR_EN_TX_DATA_LBN 72
+#define	FRF_AZ_MEM_PERR_EN_TX_DATA_WIDTH 2
+#define	FRF_AZ_MEM_PERR_EN_LBN 64
+#define	FRF_AZ_MEM_PERR_EN_WIDTH 38
+#define	FRF_AZ_MEM_PERR_EN_DW0_LBN 64
+#define	FRF_AZ_MEM_PERR_EN_DW0_WIDTH 32
+#define	FRF_AZ_MEM_PERR_EN_DW1_LBN 96
+#define	FRF_AZ_MEM_PERR_EN_DW1_WIDTH 6
+#define	FRF_AZ_CSR_SPARE_BITS_LBN 0
+#define	FRF_AZ_CSR_SPARE_BITS_WIDTH 32
+
+
+/*
+ * FR_BZ_DEBUG_DATA_OUT_REG(128bit):
+ * Live Debug and Debug 2 out ports
+ */
+#define	FR_BZ_DEBUG_DATA_OUT_REG_OFST 0x00000350
+/* falconb0,sienaa0=net_func_bar2 */
+
+#define	FRF_BZ_DEBUG2_PORT_LBN 25
+#define	FRF_BZ_DEBUG2_PORT_WIDTH 15
+#define	FRF_BZ_DEBUG1_PORT_LBN 0
+#define	FRF_BZ_DEBUG1_PORT_WIDTH 25
+
+
+/*
+ * FR_BZ_EVQ_RPTR_REGP0(32bit):
+ * Event queue read pointer register
+ */
+#define	FR_BZ_EVQ_RPTR_REGP0_OFST 0x00000400
+/* falconb0,sienaa0=net_func_bar2 */
+#define	FR_BZ_EVQ_RPTR_REGP0_STEP 8192
+#define	FR_BZ_EVQ_RPTR_REGP0_ROWS 1024
+/*
+ * FR_AA_EVQ_RPTR_REG_KER(32bit):
+ * Event queue read pointer register
+ */
+#define	FR_AA_EVQ_RPTR_REG_KER_OFST 0x00011b00
+/* falcona0=net_func_bar2 */
+#define	FR_AA_EVQ_RPTR_REG_KER_STEP 4
+#define	FR_AA_EVQ_RPTR_REG_KER_ROWS 4
+/*
+ * FR_AZ_EVQ_RPTR_REG(32bit):
+ * Event queue read pointer register
+ */
+#define	FR_AZ_EVQ_RPTR_REG_OFST 0x00fa0000
+/* falconb0=net_func_bar2,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_EVQ_RPTR_REG_STEP 16
+#define	FR_AB_EVQ_RPTR_REG_ROWS 4096
+#define	FR_CZ_EVQ_RPTR_REG_ROWS 1024
+/*
+ * FR_BB_EVQ_RPTR_REGP123(32bit):
+ * Event queue read pointer register
+ */
+#define	FR_BB_EVQ_RPTR_REGP123_OFST 0x01000400
+/* falconb0=net_func_bar2 */
+#define	FR_BB_EVQ_RPTR_REGP123_STEP 8192
+#define	FR_BB_EVQ_RPTR_REGP123_ROWS 3072
+
+#define	FRF_AZ_EVQ_RPTR_VLD_LBN 15
+#define	FRF_AZ_EVQ_RPTR_VLD_WIDTH 1
+#define	FRF_AZ_EVQ_RPTR_LBN 0
+#define	FRF_AZ_EVQ_RPTR_WIDTH 15
+
+
+/*
+ * FR_BZ_TIMER_COMMAND_REGP0(128bit):
+ * Timer Command Registers
+ */
+#define	FR_BZ_TIMER_COMMAND_REGP0_OFST 0x00000420
+/* falconb0,sienaa0=net_func_bar2 */
+#define	FR_BZ_TIMER_COMMAND_REGP0_STEP 8192
+#define	FR_BZ_TIMER_COMMAND_REGP0_ROWS 1024
+/*
+ * FR_AA_TIMER_COMMAND_REG_KER(128bit):
+ * Timer Command Registers
+ */
+#define	FR_AA_TIMER_COMMAND_REG_KER_OFST 0x00000420
+/* falcona0=net_func_bar2 */
+#define	FR_AA_TIMER_COMMAND_REG_KER_STEP 8192
+#define	FR_AA_TIMER_COMMAND_REG_KER_ROWS 4
+/*
+ * FR_AB_TIMER_COMMAND_REGP123(128bit):
+ * Timer Command Registers
+ */
+#define	FR_AB_TIMER_COMMAND_REGP123_OFST 0x01000420
+/* falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AB_TIMER_COMMAND_REGP123_STEP 8192
+#define	FR_AB_TIMER_COMMAND_REGP123_ROWS 3072
+/*
+ * FR_AA_TIMER_COMMAND_REGP0(128bit):
+ * Timer Command Registers
+ */
+#define	FR_AA_TIMER_COMMAND_REGP0_OFST 0x00008420
+/* falcona0=char_func_bar0 */
+#define	FR_AA_TIMER_COMMAND_REGP0_STEP 8192
+#define	FR_AA_TIMER_COMMAND_REGP0_ROWS 1020
+
+#define	FRF_CZ_TC_TIMER_MODE_LBN 14
+#define	FRF_CZ_TC_TIMER_MODE_WIDTH 2
+#define	FRF_AB_TC_TIMER_MODE_LBN 12
+#define	FRF_AB_TC_TIMER_MODE_WIDTH 2
+#define	FRF_CZ_TC_TIMER_VAL_LBN 0
+#define	FRF_CZ_TC_TIMER_VAL_WIDTH 14
+#define	FRF_AB_TC_TIMER_VAL_LBN 0
+#define	FRF_AB_TC_TIMER_VAL_WIDTH 12
+
+
+/*
+ * FR_AZ_DRV_EV_REG(128bit):
+ * Driver generated event register
+ */
+#define	FR_AZ_DRV_EV_REG_OFST 0x00000440
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_DRV_EV_QID_LBN 64
+#define	FRF_AZ_DRV_EV_QID_WIDTH 12
+#define	FRF_AZ_DRV_EV_DATA_LBN 0
+#define	FRF_AZ_DRV_EV_DATA_WIDTH 64
+#define	FRF_AZ_DRV_EV_DATA_DW0_LBN 0
+#define	FRF_AZ_DRV_EV_DATA_DW0_WIDTH 32
+#define	FRF_AZ_DRV_EV_DATA_DW1_LBN 32
+#define	FRF_AZ_DRV_EV_DATA_DW1_WIDTH 32
+
+
+/*
+ * FR_AZ_EVQ_CTL_REG(128bit):
+ * Event queue control register
+ */
+#define	FR_AZ_EVQ_CTL_REG_OFST 0x00000450
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_CZ_RX_EVQ_WAKEUP_MASK_LBN 15
+#define	FRF_CZ_RX_EVQ_WAKEUP_MASK_WIDTH 10
+#define	FRF_BB_RX_EVQ_WAKEUP_MASK_LBN 15
+#define	FRF_BB_RX_EVQ_WAKEUP_MASK_WIDTH 6
+#define	FRF_AZ_EVQ_OWNERR_CTL_LBN 14
+#define	FRF_AZ_EVQ_OWNERR_CTL_WIDTH 1
+#define	FRF_AZ_EVQ_FIFO_AF_TH_LBN 7
+#define	FRF_AZ_EVQ_FIFO_AF_TH_WIDTH 7
+#define	FRF_AZ_EVQ_FIFO_NOTAF_TH_LBN 0
+#define	FRF_AZ_EVQ_FIFO_NOTAF_TH_WIDTH 7
+
+
+/*
+ * FR_AZ_EVQ_CNT1_REG(128bit):
+ * Event counter 1 register
+ */
+#define	FR_AZ_EVQ_CNT1_REG_OFST 0x00000460
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_EVQ_CNT_PRE_FIFO_LBN 120
+#define	FRF_AZ_EVQ_CNT_PRE_FIFO_WIDTH 7
+#define	FRF_AZ_EVQ_CNT_TOBIU_LBN 100
+#define	FRF_AZ_EVQ_CNT_TOBIU_WIDTH 20
+#define	FRF_AZ_EVQ_TX_REQ_CNT_LBN 80
+#define	FRF_AZ_EVQ_TX_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_RX_REQ_CNT_LBN 60
+#define	FRF_AZ_EVQ_RX_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_EM_REQ_CNT_LBN 40
+#define	FRF_AZ_EVQ_EM_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_CSR_REQ_CNT_LBN 20
+#define	FRF_AZ_EVQ_CSR_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_ERR_REQ_CNT_LBN 0
+#define	FRF_AZ_EVQ_ERR_REQ_CNT_WIDTH 20
+
+
+/*
+ * FR_AZ_EVQ_CNT2_REG(128bit):
+ * Event counter 2 register
+ */
+#define	FR_AZ_EVQ_CNT2_REG_OFST 0x00000470
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_EVQ_UPD_REQ_CNT_LBN 104
+#define	FRF_AZ_EVQ_UPD_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_CLR_REQ_CNT_LBN 84
+#define	FRF_AZ_EVQ_CLR_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_RDY_CNT_LBN 80
+#define	FRF_AZ_EVQ_RDY_CNT_WIDTH 4
+#define	FRF_AZ_EVQ_WU_REQ_CNT_LBN 60
+#define	FRF_AZ_EVQ_WU_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_WET_REQ_CNT_LBN 40
+#define	FRF_AZ_EVQ_WET_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_INIT_REQ_CNT_LBN 20
+#define	FRF_AZ_EVQ_INIT_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_TM_REQ_CNT_LBN 0
+#define	FRF_AZ_EVQ_TM_REQ_CNT_WIDTH 20
+
+
+/*
+ * FR_CZ_USR_EV_REG(32bit):
+ * Event mailbox register
+ */
+#define	FR_CZ_USR_EV_REG_OFST 0x00000540
+/* sienaa0=net_func_bar2 */
+#define	FR_CZ_USR_EV_REG_STEP 8192
+#define	FR_CZ_USR_EV_REG_ROWS 1024
+
+#define	FRF_CZ_USR_EV_DATA_LBN 0
+#define	FRF_CZ_USR_EV_DATA_WIDTH 32
+
+
+/*
+ * FR_AZ_BUF_TBL_CFG_REG(128bit):
+ * Buffer table configuration register
+ */
+#define	FR_AZ_BUF_TBL_CFG_REG_OFST 0x00000600
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_BUF_TBL_MODE_LBN 3
+#define	FRF_AZ_BUF_TBL_MODE_WIDTH 1
+
+
+/*
+ * FR_AZ_SRM_RX_DC_CFG_REG(128bit):
+ * SRAM receive descriptor cache configuration register
+ */
+#define	FR_AZ_SRM_RX_DC_CFG_REG_OFST 0x00000610
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_SRM_CLK_TMP_EN_LBN 21
+#define	FRF_AZ_SRM_CLK_TMP_EN_WIDTH 1
+#define	FRF_AZ_SRM_RX_DC_BASE_ADR_LBN 0
+#define	FRF_AZ_SRM_RX_DC_BASE_ADR_WIDTH 21
+
+
+/*
+ * FR_AZ_SRM_TX_DC_CFG_REG(128bit):
+ * SRAM transmit descriptor cache configuration register
+ */
+#define	FR_AZ_SRM_TX_DC_CFG_REG_OFST 0x00000620
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_SRM_TX_DC_BASE_ADR_LBN 0
+#define	FRF_AZ_SRM_TX_DC_BASE_ADR_WIDTH 21
+
+
+/*
+ * FR_AZ_SRM_CFG_REG(128bit):
+ * SRAM configuration register
+ */
+#define	FR_AZ_SRM_CFG_REG_SF_OFST 0x00000380
+/* falcona0,falconb0=eeprom_flash */
+/*
+ * FR_AZ_SRM_CFG_REG(128bit):
+ * SRAM configuration register
+ */
+#define	FR_AZ_SRM_CFG_REG_OFST 0x00000630
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_SRM_OOB_ADR_INTEN_LBN 5
+#define	FRF_AZ_SRM_OOB_ADR_INTEN_WIDTH 1
+#define	FRF_AZ_SRM_OOB_BUF_INTEN_LBN 4
+#define	FRF_AZ_SRM_OOB_BUF_INTEN_WIDTH 1
+#define	FRF_AZ_SRM_INIT_EN_LBN 3
+#define	FRF_AZ_SRM_INIT_EN_WIDTH 1
+#define	FRF_AZ_SRM_NUM_BANK_LBN 2
+#define	FRF_AZ_SRM_NUM_BANK_WIDTH 1
+#define	FRF_AZ_SRM_BANK_SIZE_LBN 0
+#define	FRF_AZ_SRM_BANK_SIZE_WIDTH 2
+
+
+/*
+ * FR_AZ_BUF_TBL_UPD_REG(128bit):
+ * Buffer table update register
+ */
+#define	FR_AZ_BUF_TBL_UPD_REG_OFST 0x00000650
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_BUF_UPD_CMD_LBN 63
+#define	FRF_AZ_BUF_UPD_CMD_WIDTH 1
+#define	FRF_AZ_BUF_CLR_CMD_LBN 62
+#define	FRF_AZ_BUF_CLR_CMD_WIDTH 1
+#define	FRF_AZ_BUF_CLR_END_ID_LBN 32
+#define	FRF_AZ_BUF_CLR_END_ID_WIDTH 20
+#define	FRF_AZ_BUF_CLR_START_ID_LBN 0
+#define	FRF_AZ_BUF_CLR_START_ID_WIDTH 20
+
+
+/*
+ * FR_AZ_SRM_UPD_EVQ_REG(128bit):
+ * Buffer table update register
+ */
+#define	FR_AZ_SRM_UPD_EVQ_REG_OFST 0x00000660
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_SRM_UPD_EVQ_ID_LBN 0
+#define	FRF_AZ_SRM_UPD_EVQ_ID_WIDTH 12
+
+
+/*
+ * FR_AZ_SRAM_PARITY_REG(128bit):
+ * SRAM parity register.
+ */
+#define	FR_AZ_SRAM_PARITY_REG_OFST 0x00000670
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_CZ_BYPASS_ECC_LBN 3
+#define	FRF_CZ_BYPASS_ECC_WIDTH 1
+#define	FRF_CZ_SEC_INT_LBN 2
+#define	FRF_CZ_SEC_INT_WIDTH 1
+#define	FRF_CZ_FORCE_SRAM_DOUBLE_ERR_LBN 1
+#define	FRF_CZ_FORCE_SRAM_DOUBLE_ERR_WIDTH 1
+#define	FRF_CZ_FORCE_SRAM_SINGLE_ERR_LBN 0
+#define	FRF_CZ_FORCE_SRAM_SINGLE_ERR_WIDTH 1
+#define	FRF_AB_FORCE_SRAM_PERR_LBN 0
+#define	FRF_AB_FORCE_SRAM_PERR_WIDTH 1
+
+
+/*
+ * FR_AZ_RX_CFG_REG(128bit):
+ * Receive configuration register
+ */
+#define	FR_AZ_RX_CFG_REG_OFST 0x00000800
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_CZ_RX_HDR_SPLIT_EN_LBN 71
+#define	FRF_CZ_RX_HDR_SPLIT_EN_WIDTH 1
+#define	FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_LBN 62
+#define	FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_WIDTH 9
+#define	FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_LBN 53
+#define	FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_WIDTH 9
+#define	FRF_CZ_RX_PRE_RFF_IPG_LBN 49
+#define	FRF_CZ_RX_PRE_RFF_IPG_WIDTH 4
+#define	FRF_BZ_RX_TCP_SUP_LBN 48
+#define	FRF_BZ_RX_TCP_SUP_WIDTH 1
+#define	FRF_BZ_RX_INGR_EN_LBN 47
+#define	FRF_BZ_RX_INGR_EN_WIDTH 1
+#define	FRF_BZ_RX_IP_HASH_LBN 46
+#define	FRF_BZ_RX_IP_HASH_WIDTH 1
+#define	FRF_BZ_RX_HASH_ALG_LBN 45
+#define	FRF_BZ_RX_HASH_ALG_WIDTH 1
+#define	FRF_BZ_RX_HASH_INSRT_HDR_LBN 44
+#define	FRF_BZ_RX_HASH_INSRT_HDR_WIDTH 1
+#define	FRF_BZ_RX_DESC_PUSH_EN_LBN 43
+#define	FRF_BZ_RX_DESC_PUSH_EN_WIDTH 1
+#define	FRF_BZ_RX_RDW_PATCH_EN_LBN 42
+#define	FRF_BZ_RX_RDW_PATCH_EN_WIDTH 1
+#define	FRF_BB_RX_PCI_BURST_SIZE_LBN 39
+#define	FRF_BB_RX_PCI_BURST_SIZE_WIDTH 3
+#define	FRF_BZ_RX_OWNERR_CTL_LBN 38
+#define	FRF_BZ_RX_OWNERR_CTL_WIDTH 1
+#define	FRF_BZ_RX_XON_TX_TH_LBN 33
+#define	FRF_BZ_RX_XON_TX_TH_WIDTH 5
+#define	FRF_AA_RX_DESC_PUSH_EN_LBN 35
+#define	FRF_AA_RX_DESC_PUSH_EN_WIDTH 1
+#define	FRF_AA_RX_RDW_PATCH_EN_LBN 34
+#define	FRF_AA_RX_RDW_PATCH_EN_WIDTH 1
+#define	FRF_AA_RX_PCI_BURST_SIZE_LBN 31
+#define	FRF_AA_RX_PCI_BURST_SIZE_WIDTH 3
+#define	FRF_BZ_RX_XOFF_TX_TH_LBN 28
+#define	FRF_BZ_RX_XOFF_TX_TH_WIDTH 5
+#define	FRF_AA_RX_OWNERR_CTL_LBN 30
+#define	FRF_AA_RX_OWNERR_CTL_WIDTH 1
+#define	FRF_AA_RX_XON_TX_TH_LBN 25
+#define	FRF_AA_RX_XON_TX_TH_WIDTH 5
+#define	FRF_BZ_RX_USR_BUF_SIZE_LBN 19
+#define	FRF_BZ_RX_USR_BUF_SIZE_WIDTH 9
+#define	FRF_AA_RX_XOFF_TX_TH_LBN 20
+#define	FRF_AA_RX_XOFF_TX_TH_WIDTH 5
+#define	FRF_AA_RX_USR_BUF_SIZE_LBN 11
+#define	FRF_AA_RX_USR_BUF_SIZE_WIDTH 9
+#define	FRF_BZ_RX_XON_MAC_TH_LBN 10
+#define	FRF_BZ_RX_XON_MAC_TH_WIDTH 9
+#define	FRF_AA_RX_XON_MAC_TH_LBN 6
+#define	FRF_AA_RX_XON_MAC_TH_WIDTH 5
+#define	FRF_BZ_RX_XOFF_MAC_TH_LBN 1
+#define	FRF_BZ_RX_XOFF_MAC_TH_WIDTH 9
+#define	FRF_AA_RX_XOFF_MAC_TH_LBN 1
+#define	FRF_AA_RX_XOFF_MAC_TH_WIDTH 5
+#define	FRF_AZ_RX_XOFF_MAC_EN_LBN 0
+#define	FRF_AZ_RX_XOFF_MAC_EN_WIDTH 1
+
+
+/*
+ * FR_AZ_RX_FILTER_CTL_REG(128bit):
+ * Receive filter control registers
+ */
+#define	FR_AZ_RX_FILTER_CTL_REG_OFST 0x00000810
+/* falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT_LBN 94
+#define	FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT_WIDTH 8
+#define	FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT_LBN 86
+#define	FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT_WIDTH 8
+#define	FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES_LBN 85
+#define	FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES_WIDTH 1
+#define	FRF_CZ_RX_VLAN_MATCH_ETHERTYPE_LBN 69
+#define	FRF_CZ_RX_VLAN_MATCH_ETHERTYPE_WIDTH 16
+#define	FRF_CZ_MULTICAST_NOMATCH_Q_ID_LBN 57
+#define	FRF_CZ_MULTICAST_NOMATCH_Q_ID_WIDTH 12
+#define	FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED_LBN 56
+#define	FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED_WIDTH 1
+#define	FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE_LBN 55
+#define	FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE_WIDTH 1
+#define	FRF_CZ_UNICAST_NOMATCH_Q_ID_LBN 43
+#define	FRF_CZ_UNICAST_NOMATCH_Q_ID_WIDTH 12
+#define	FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED_LBN 42
+#define	FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED_WIDTH 1
+#define	FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE_LBN 41
+#define	FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE_WIDTH 1
+#define	FRF_BZ_SCATTER_ENBL_NO_MATCH_Q_LBN 40
+#define	FRF_BZ_SCATTER_ENBL_NO_MATCH_Q_WIDTH 1
+#define	FRF_AZ_UDP_FULL_SRCH_LIMIT_LBN 32
+#define	FRF_AZ_UDP_FULL_SRCH_LIMIT_WIDTH 8
+#define	FRF_AZ_NUM_KER_LBN 24
+#define	FRF_AZ_NUM_KER_WIDTH 2
+#define	FRF_AZ_UDP_WILD_SRCH_LIMIT_LBN 16
+#define	FRF_AZ_UDP_WILD_SRCH_LIMIT_WIDTH 8
+#define	FRF_AZ_TCP_WILD_SRCH_LIMIT_LBN 8
+#define	FRF_AZ_TCP_WILD_SRCH_LIMIT_WIDTH 8
+#define	FRF_AZ_TCP_FULL_SRCH_LIMIT_LBN 0
+#define	FRF_AZ_TCP_FULL_SRCH_LIMIT_WIDTH 8
+
+
+/*
+ * FR_AZ_RX_FLUSH_DESCQ_REG(128bit):
+ * Receive flush descriptor queue register
+ */
+#define	FR_AZ_RX_FLUSH_DESCQ_REG_OFST 0x00000820
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_RX_FLUSH_DESCQ_CMD_LBN 24
+#define	FRF_AZ_RX_FLUSH_DESCQ_CMD_WIDTH 1
+#define	FRF_AZ_RX_FLUSH_DESCQ_LBN 0
+#define	FRF_AZ_RX_FLUSH_DESCQ_WIDTH 12
+
+
+/*
+ * FR_BZ_RX_DESC_UPD_REGP0(128bit):
+ * Receive descriptor update register.
+ */
+#define	FR_BZ_RX_DESC_UPD_REGP0_OFST 0x00000830
+/* falconb0,sienaa0=net_func_bar2 */
+#define	FR_BZ_RX_DESC_UPD_REGP0_STEP 8192
+#define	FR_BZ_RX_DESC_UPD_REGP0_ROWS 1024
+/*
+ * FR_AA_RX_DESC_UPD_REG_KER(128bit):
+ * Receive descriptor update register.
+ */
+#define	FR_AA_RX_DESC_UPD_REG_KER_OFST 0x00000830
+/* falcona0=net_func_bar2 */
+#define	FR_AA_RX_DESC_UPD_REG_KER_STEP 8192
+#define	FR_AA_RX_DESC_UPD_REG_KER_ROWS 4
+/*
+ * FR_AB_RX_DESC_UPD_REGP123(128bit):
+ * Receive descriptor update register.
+ */
+#define	FR_AB_RX_DESC_UPD_REGP123_OFST 0x01000830
+/* falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AB_RX_DESC_UPD_REGP123_STEP 8192
+#define	FR_AB_RX_DESC_UPD_REGP123_ROWS 3072
+/*
+ * FR_AA_RX_DESC_UPD_REGP0(128bit):
+ * Receive descriptor update register.
+ */
+#define	FR_AA_RX_DESC_UPD_REGP0_OFST 0x00008830
+/* falcona0=char_func_bar0 */
+#define	FR_AA_RX_DESC_UPD_REGP0_STEP 8192
+#define	FR_AA_RX_DESC_UPD_REGP0_ROWS 1020
+
+#define	FRF_AZ_RX_DESC_WPTR_LBN 96
+#define	FRF_AZ_RX_DESC_WPTR_WIDTH 12
+#define	FRF_AZ_RX_DESC_PUSH_CMD_LBN 95
+#define	FRF_AZ_RX_DESC_PUSH_CMD_WIDTH 1
+#define	FRF_AZ_RX_DESC_LBN 0
+#define	FRF_AZ_RX_DESC_WIDTH 64
+#define	FRF_AZ_RX_DESC_DW0_LBN 0
+#define	FRF_AZ_RX_DESC_DW0_WIDTH 32
+#define	FRF_AZ_RX_DESC_DW1_LBN 32
+#define	FRF_AZ_RX_DESC_DW1_WIDTH 32
+
+
+/*
+ * FR_AZ_RX_DC_CFG_REG(128bit):
+ * Receive descriptor cache configuration register
+ */
+#define	FR_AZ_RX_DC_CFG_REG_OFST 0x00000840
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_RX_MAX_PF_LBN 2
+#define	FRF_AZ_RX_MAX_PF_WIDTH 2
+#define	FRF_AZ_RX_DC_SIZE_LBN 0
+#define	FRF_AZ_RX_DC_SIZE_WIDTH 2
+#define	FFE_AZ_RX_DC_SIZE_64 3
+#define	FFE_AZ_RX_DC_SIZE_32 2
+#define	FFE_AZ_RX_DC_SIZE_16 1
+#define	FFE_AZ_RX_DC_SIZE_8 0
+
+
+/*
+ * FR_AZ_RX_DC_PF_WM_REG(128bit):
+ * Receive descriptor cache pre-fetch watermark register
+ */
+#define	FR_AZ_RX_DC_PF_WM_REG_OFST 0x00000850
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_RX_DC_PF_HWM_LBN 6
+#define	FRF_AZ_RX_DC_PF_HWM_WIDTH 6
+#define	FRF_AZ_RX_DC_PF_LWM_LBN 0
+#define	FRF_AZ_RX_DC_PF_LWM_WIDTH 6
+
+
+/*
+ * FR_BZ_RX_RSS_TKEY_REG(128bit):
+ * RSS Toeplitz hash key
+ */
+#define	FR_BZ_RX_RSS_TKEY_REG_OFST 0x00000860
+/* falconb0,sienaa0=net_func_bar2 */
+
+#define	FRF_BZ_RX_RSS_TKEY_LBN 96
+#define	FRF_BZ_RX_RSS_TKEY_WIDTH 32
+#define	FRF_BZ_RX_RSS_TKEY_DW3_LBN 96
+#define	FRF_BZ_RX_RSS_TKEY_DW3_WIDTH 32
+#define	FRF_BZ_RX_RSS_TKEY_DW2_LBN 64
+#define	FRF_BZ_RX_RSS_TKEY_DW2_WIDTH 32
+#define	FRF_BZ_RX_RSS_TKEY_DW1_LBN 32
+#define	FRF_BZ_RX_RSS_TKEY_DW1_WIDTH 32
+#define	FRF_BZ_RX_RSS_TKEY_DW0_LBN 0
+#define	FRF_BZ_RX_RSS_TKEY_DW0_WIDTH 32
+
+
+/*
+ * FR_AZ_RX_NODESC_DROP_REG(128bit):
+ * Receive dropped packet counter register
+ */
+#define	FR_AZ_RX_NODESC_DROP_REG_OFST 0x00000880
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_RX_NODESC_DROP_CNT_LBN 0
+#define	FRF_AZ_RX_NODESC_DROP_CNT_WIDTH 16
+
+
+/*
+ * FR_AZ_RX_SELF_RST_REG(128bit):
+ * Receive self reset register
+ */
+#define	FR_AZ_RX_SELF_RST_REG_OFST 0x00000890
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_RX_ISCSI_DIS_LBN 17
+#define	FRF_AZ_RX_ISCSI_DIS_WIDTH 1
+#define	FRF_AB_RX_SW_RST_REG_LBN 16
+#define	FRF_AB_RX_SW_RST_REG_WIDTH 1
+#define	FRF_AB_RX_SELF_RST_EN_LBN 8
+#define	FRF_AB_RX_SELF_RST_EN_WIDTH 1
+#define	FRF_AZ_RX_MAX_PF_LAT_LBN 4
+#define	FRF_AZ_RX_MAX_PF_LAT_WIDTH 4
+#define	FRF_AZ_RX_MAX_LU_LAT_LBN 0
+#define	FRF_AZ_RX_MAX_LU_LAT_WIDTH 4
+
+
+/*
+ * FR_AZ_RX_DEBUG_REG(128bit):
+ * undocumented register
+ */
+#define	FR_AZ_RX_DEBUG_REG_OFST 0x000008a0
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_RX_DEBUG_LBN 0
+#define	FRF_AZ_RX_DEBUG_WIDTH 64
+#define	FRF_AZ_RX_DEBUG_DW0_LBN 0
+#define	FRF_AZ_RX_DEBUG_DW0_WIDTH 32
+#define	FRF_AZ_RX_DEBUG_DW1_LBN 32
+#define	FRF_AZ_RX_DEBUG_DW1_WIDTH 32
+
+
+/*
+ * FR_AZ_RX_PUSH_DROP_REG(128bit):
+ * Receive descriptor push dropped counter register
+ */
+#define	FR_AZ_RX_PUSH_DROP_REG_OFST 0x000008b0
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_RX_PUSH_DROP_CNT_LBN 0
+#define	FRF_AZ_RX_PUSH_DROP_CNT_WIDTH 32
+
+
+/*
+ * FR_CZ_RX_RSS_IPV6_REG1(128bit):
+ * IPv6 RSS Toeplitz hash key low bytes
+ */
+#define	FR_CZ_RX_RSS_IPV6_REG1_OFST 0x000008d0
+/* sienaa0=net_func_bar2 */
+
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN 0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH 128
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_DW0_LBN 0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_DW0_WIDTH 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_DW1_LBN 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_DW1_WIDTH 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_DW2_LBN 64
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_DW2_WIDTH 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_DW3_LBN 96
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_DW3_WIDTH 32
+
+
+/*
+ * FR_CZ_RX_RSS_IPV6_REG2(128bit):
+ * IPv6 RSS Toeplitz hash key middle bytes
+ */
+#define	FR_CZ_RX_RSS_IPV6_REG2_OFST 0x000008e0
+/* sienaa0=net_func_bar2 */
+
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN 0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH 128
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_DW0_LBN 0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_DW0_WIDTH 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_DW1_LBN 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_DW1_WIDTH 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_DW2_LBN 64
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_DW2_WIDTH 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_DW3_LBN 96
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_DW3_WIDTH 32
+
+
+/*
+ * FR_CZ_RX_RSS_IPV6_REG3(128bit):
+ * IPv6 RSS Toeplitz hash key upper bytes and IPv6 RSS settings
+ */
+#define	FR_CZ_RX_RSS_IPV6_REG3_OFST 0x000008f0
+/* sienaa0=net_func_bar2 */
+
+#define	FRF_CZ_RX_RSS_IPV6_THASH_ENABLE_LBN 66
+#define	FRF_CZ_RX_RSS_IPV6_THASH_ENABLE_WIDTH 1
+#define	FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE_LBN 65
+#define	FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE_WIDTH 1
+#define	FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS_LBN 64
+#define	FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS_WIDTH 1
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN 0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH 64
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_HI_DW0_LBN 0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_HI_DW0_WIDTH 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_HI_DW1_LBN 32
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_HI_DW1_WIDTH 32
+
+
+/*
+ * FR_AZ_TX_FLUSH_DESCQ_REG(128bit):
+ * Transmit flush descriptor queue register
+ */
+#define	FR_AZ_TX_FLUSH_DESCQ_REG_OFST 0x00000a00
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_TX_FLUSH_DESCQ_CMD_LBN 12
+#define	FRF_AZ_TX_FLUSH_DESCQ_CMD_WIDTH 1
+#define	FRF_AZ_TX_FLUSH_DESCQ_LBN 0
+#define	FRF_AZ_TX_FLUSH_DESCQ_WIDTH 12
+
+
+/*
+ * FR_BZ_TX_DESC_UPD_REGP0(128bit):
+ * Transmit descriptor update register.
+ */
+#define	FR_BZ_TX_DESC_UPD_REGP0_OFST 0x00000a10
+/* falconb0,sienaa0=net_func_bar2 */
+#define	FR_BZ_TX_DESC_UPD_REGP0_STEP 8192
+#define	FR_BZ_TX_DESC_UPD_REGP0_ROWS 1024
+/*
+ * FR_AA_TX_DESC_UPD_REG_KER(128bit):
+ * Transmit descriptor update register.
+ */
+#define	FR_AA_TX_DESC_UPD_REG_KER_OFST 0x00000a10
+/* falcona0=net_func_bar2 */
+#define	FR_AA_TX_DESC_UPD_REG_KER_STEP 8192
+#define	FR_AA_TX_DESC_UPD_REG_KER_ROWS 8
+/*
+ * FR_AB_TX_DESC_UPD_REGP123(128bit):
+ * Transmit descriptor update register.
+ */
+#define	FR_AB_TX_DESC_UPD_REGP123_OFST 0x01000a10
+/* falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AB_TX_DESC_UPD_REGP123_STEP 8192
+#define	FR_AB_TX_DESC_UPD_REGP123_ROWS 3072
+/*
+ * FR_AA_TX_DESC_UPD_REGP0(128bit):
+ * Transmit descriptor update register.
+ */
+#define	FR_AA_TX_DESC_UPD_REGP0_OFST 0x00008a10
+/* falcona0=char_func_bar0 */
+#define	FR_AA_TX_DESC_UPD_REGP0_STEP 8192
+#define	FR_AA_TX_DESC_UPD_REGP0_ROWS 1020
+
+#define	FRF_AZ_TX_DESC_WPTR_LBN 96
+#define	FRF_AZ_TX_DESC_WPTR_WIDTH 12
+#define	FRF_AZ_TX_DESC_PUSH_CMD_LBN 95
+#define	FRF_AZ_TX_DESC_PUSH_CMD_WIDTH 1
+#define	FRF_AZ_TX_DESC_LBN 0
+#define	FRF_AZ_TX_DESC_WIDTH 95
+#define	FRF_AZ_TX_DESC_DW0_LBN 0
+#define	FRF_AZ_TX_DESC_DW0_WIDTH 32
+#define	FRF_AZ_TX_DESC_DW1_LBN 32
+#define	FRF_AZ_TX_DESC_DW1_WIDTH 32
+#define	FRF_AZ_TX_DESC_DW2_LBN 64
+#define	FRF_AZ_TX_DESC_DW2_WIDTH 31
+
+
+/*
+ * FR_AZ_TX_DC_CFG_REG(128bit):
+ * Transmit descriptor cache configuration register
+ */
+#define	FR_AZ_TX_DC_CFG_REG_OFST 0x00000a20
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_TX_DC_SIZE_LBN 0
+#define	FRF_AZ_TX_DC_SIZE_WIDTH 2
+#define	FFE_AZ_TX_DC_SIZE_32 2
+#define	FFE_AZ_TX_DC_SIZE_16 1
+#define	FFE_AZ_TX_DC_SIZE_8 0
+
+
+/*
+ * FR_AA_TX_CHKSM_CFG_REG(128bit):
+ * Transmit checksum configuration register
+ */
+#define	FR_AA_TX_CHKSM_CFG_REG_OFST 0x00000a30
+/* falcona0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AA_TX_Q_CHKSM_DIS_96_127_LBN 96
+#define	FRF_AA_TX_Q_CHKSM_DIS_96_127_WIDTH 32
+#define	FRF_AA_TX_Q_CHKSM_DIS_64_95_LBN 64
+#define	FRF_AA_TX_Q_CHKSM_DIS_64_95_WIDTH 32
+#define	FRF_AA_TX_Q_CHKSM_DIS_32_63_LBN 32
+#define	FRF_AA_TX_Q_CHKSM_DIS_32_63_WIDTH 32
+#define	FRF_AA_TX_Q_CHKSM_DIS_0_31_LBN 0
+#define	FRF_AA_TX_Q_CHKSM_DIS_0_31_WIDTH 32
+
+
+/*
+ * FR_AZ_TX_CFG_REG(128bit):
+ * Transmit configuration register
+ */
+#define	FR_AZ_TX_CFG_REG_OFST 0x00000a50
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_CZ_TX_CONT_LOOKUP_THRESH_RANGE_LBN 114
+#define	FRF_CZ_TX_CONT_LOOKUP_THRESH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_FILTER_TEST_MODE_BIT_LBN 113
+#define	FRF_CZ_TX_FILTER_TEST_MODE_BIT_WIDTH 1
+#define	FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE_LBN 105
+#define	FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE_LBN 97
+#define	FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE_LBN 89
+#define	FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE_LBN 81
+#define	FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE_LBN 73
+#define	FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE_LBN 65
+#define	FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_FILTER_ALL_VLAN_ETHERTYPES_BIT_LBN 64
+#define	FRF_CZ_TX_FILTER_ALL_VLAN_ETHERTYPES_BIT_WIDTH 1
+#define	FRF_CZ_TX_VLAN_MATCH_ETHERTYPE_RANGE_LBN 48
+#define	FRF_CZ_TX_VLAN_MATCH_ETHERTYPE_RANGE_WIDTH 16
+#define	FRF_CZ_TX_FILTER_EN_BIT_LBN 47
+#define	FRF_CZ_TX_FILTER_EN_BIT_WIDTH 1
+#define	FRF_AZ_TX_IP_ID_P0_OFS_LBN 16
+#define	FRF_AZ_TX_IP_ID_P0_OFS_WIDTH 15
+#define	FRF_AZ_TX_NO_EOP_DISC_EN_LBN 5
+#define	FRF_AZ_TX_NO_EOP_DISC_EN_WIDTH 1
+#define	FRF_AZ_TX_P1_PRI_EN_LBN 4
+#define	FRF_AZ_TX_P1_PRI_EN_WIDTH 1
+#define	FRF_AZ_TX_OWNERR_CTL_LBN 2
+#define	FRF_AZ_TX_OWNERR_CTL_WIDTH 1
+#define	FRF_AA_TX_NON_IP_DROP_DIS_LBN 1
+#define	FRF_AA_TX_NON_IP_DROP_DIS_WIDTH 1
+#define	FRF_AZ_TX_IP_ID_REP_EN_LBN 0
+#define	FRF_AZ_TX_IP_ID_REP_EN_WIDTH 1
+
+
+/*
+ * FR_AZ_TX_PUSH_DROP_REG(128bit):
+ * Transmit push dropped register
+ */
+#define	FR_AZ_TX_PUSH_DROP_REG_OFST 0x00000a60
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_TX_PUSH_DROP_CNT_LBN 0
+#define	FRF_AZ_TX_PUSH_DROP_CNT_WIDTH 32
+
+
+/*
+ * FR_AZ_TX_RESERVED_REG(128bit):
+ * Transmit configuration register
+ */
+#define	FR_AZ_TX_RESERVED_REG_OFST 0x00000a80
+/* falcona0,falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_TX_EVT_CNT_LBN 121
+#define	FRF_AZ_TX_EVT_CNT_WIDTH 7
+#define	FRF_AZ_TX_PREF_AGE_CNT_LBN 119
+#define	FRF_AZ_TX_PREF_AGE_CNT_WIDTH 2
+#define	FRF_AZ_TX_RD_COMP_TMR_LBN 96
+#define	FRF_AZ_TX_RD_COMP_TMR_WIDTH 23
+#define	FRF_AZ_TX_PUSH_EN_LBN 89
+#define	FRF_AZ_TX_PUSH_EN_WIDTH 1
+#define	FRF_AZ_TX_PUSH_CHK_DIS_LBN 88
+#define	FRF_AZ_TX_PUSH_CHK_DIS_WIDTH 1
+#define	FRF_AZ_TX_D_FF_FULL_P0_LBN 85
+#define	FRF_AZ_TX_D_FF_FULL_P0_WIDTH 1
+#define	FRF_AZ_TX_DMAR_ST_P0_LBN 81
+#define	FRF_AZ_TX_DMAR_ST_P0_WIDTH 1
+#define	FRF_AZ_TX_DMAQ_ST_LBN 78
+#define	FRF_AZ_TX_DMAQ_ST_WIDTH 1
+#define	FRF_AZ_TX_RX_SPACER_LBN 64
+#define	FRF_AZ_TX_RX_SPACER_WIDTH 8
+#define	FRF_AZ_TX_DROP_ABORT_EN_LBN 60
+#define	FRF_AZ_TX_DROP_ABORT_EN_WIDTH 1
+#define	FRF_AZ_TX_SOFT_EVT_EN_LBN 59
+#define	FRF_AZ_TX_SOFT_EVT_EN_WIDTH 1
+#define	FRF_AZ_TX_PS_EVT_DIS_LBN 58
+#define	FRF_AZ_TX_PS_EVT_DIS_WIDTH 1
+#define	FRF_AZ_TX_RX_SPACER_EN_LBN 57
+#define	FRF_AZ_TX_RX_SPACER_EN_WIDTH 1
+#define	FRF_AZ_TX_XP_TIMER_LBN 52
+#define	FRF_AZ_TX_XP_TIMER_WIDTH 5
+#define	FRF_AZ_TX_PREF_SPACER_LBN 44
+#define	FRF_AZ_TX_PREF_SPACER_WIDTH 8
+#define	FRF_AZ_TX_PREF_WD_TMR_LBN 22
+#define	FRF_AZ_TX_PREF_WD_TMR_WIDTH 22
+#define	FRF_AZ_TX_ONLY1TAG_LBN 21
+#define	FRF_AZ_TX_ONLY1TAG_WIDTH 1
+#define	FRF_AZ_TX_PREF_THRESHOLD_LBN 19
+#define	FRF_AZ_TX_PREF_THRESHOLD_WIDTH 2
+#define	FRF_AZ_TX_ONE_PKT_PER_Q_LBN 18
+#define	FRF_AZ_TX_ONE_PKT_PER_Q_WIDTH 1
+#define	FRF_AZ_TX_DIS_NON_IP_EV_LBN 17
+#define	FRF_AZ_TX_DIS_NON_IP_EV_WIDTH 1
+#define	FRF_AA_TX_DMA_FF_THR_LBN 16
+#define	FRF_AA_TX_DMA_FF_THR_WIDTH 1
+#define	FRF_AZ_TX_DMA_SPACER_LBN 8
+#define	FRF_AZ_TX_DMA_SPACER_WIDTH 8
+#define	FRF_AA_TX_TCP_DIS_LBN 7
+#define	FRF_AA_TX_TCP_DIS_WIDTH 1
+#define	FRF_BZ_TX_FLUSH_MIN_LEN_EN_LBN 7
+#define	FRF_BZ_TX_FLUSH_MIN_LEN_EN_WIDTH 1
+#define	FRF_AA_TX_IP_DIS_LBN 6
+#define	FRF_AA_TX_IP_DIS_WIDTH 1
+#define	FRF_AZ_TX_MAX_CPL_LBN 2
+#define	FRF_AZ_TX_MAX_CPL_WIDTH 2
+#define	FFE_AZ_TX_MAX_CPL_16 3
+#define	FFE_AZ_TX_MAX_CPL_8 2
+#define	FFE_AZ_TX_MAX_CPL_4 1
+#define	FFE_AZ_TX_MAX_CPL_NOLIMIT 0
+#define	FRF_AZ_TX_MAX_PREF_LBN 0
+#define	FRF_AZ_TX_MAX_PREF_WIDTH 2
+#define	FFE_AZ_TX_MAX_PREF_32 3
+#define	FFE_AZ_TX_MAX_PREF_16 2
+#define	FFE_AZ_TX_MAX_PREF_8 1
+#define	FFE_AZ_TX_MAX_PREF_OFF 0
+
+
+/*
+ * FR_BZ_TX_PACE_REG(128bit):
+ * Transmit pace control register
+ */
+#define	FR_BZ_TX_PACE_REG_OFST 0x00000a90
+/* falconb0,sienaa0=net_func_bar2 */
+/*
+ * FR_AA_TX_PACE_REG(128bit):
+ * Transmit pace control register
+ */
+#define	FR_AA_TX_PACE_REG_OFST 0x00f80000
+/* falcona0=char_func_bar0 */
+
+#define	FRF_AZ_TX_PACE_SB_NOT_AF_LBN 19
+#define	FRF_AZ_TX_PACE_SB_NOT_AF_WIDTH 10
+#define	FRF_AZ_TX_PACE_SB_AF_LBN 9
+#define	FRF_AZ_TX_PACE_SB_AF_WIDTH 10
+#define	FRF_AZ_TX_PACE_FB_BASE_LBN 5
+#define	FRF_AZ_TX_PACE_FB_BASE_WIDTH 4
+#define	FRF_AZ_TX_PACE_BIN_TH_LBN 0
+#define	FRF_AZ_TX_PACE_BIN_TH_WIDTH 5
+
+
+/*
+ * FR_AZ_TX_PACE_DROP_QID_REG(128bit):
+ * PACE Drop QID Counter
+ */
+#define	FR_AZ_TX_PACE_DROP_QID_REG_OFST 0x00000aa0
+/* falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_TX_PACE_QID_DRP_CNT_LBN 0
+#define	FRF_AZ_TX_PACE_QID_DRP_CNT_WIDTH 16
+
+
+/*
+ * FR_AB_TX_VLAN_REG(128bit):
+ * Transmit VLAN tag register
+ */
+#define	FR_AB_TX_VLAN_REG_OFST 0x00000ae0
+/* falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_TX_VLAN_EN_LBN 127
+#define	FRF_AB_TX_VLAN_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN7_PORT1_EN_LBN 125
+#define	FRF_AB_TX_VLAN7_PORT1_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN7_PORT0_EN_LBN 124
+#define	FRF_AB_TX_VLAN7_PORT0_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN7_LBN 112
+#define	FRF_AB_TX_VLAN7_WIDTH 12
+#define	FRF_AB_TX_VLAN6_PORT1_EN_LBN 109
+#define	FRF_AB_TX_VLAN6_PORT1_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN6_PORT0_EN_LBN 108
+#define	FRF_AB_TX_VLAN6_PORT0_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN6_LBN 96
+#define	FRF_AB_TX_VLAN6_WIDTH 12
+#define	FRF_AB_TX_VLAN5_PORT1_EN_LBN 93
+#define	FRF_AB_TX_VLAN5_PORT1_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN5_PORT0_EN_LBN 92
+#define	FRF_AB_TX_VLAN5_PORT0_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN5_LBN 80
+#define	FRF_AB_TX_VLAN5_WIDTH 12
+#define	FRF_AB_TX_VLAN4_PORT1_EN_LBN 77
+#define	FRF_AB_TX_VLAN4_PORT1_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN4_PORT0_EN_LBN 76
+#define	FRF_AB_TX_VLAN4_PORT0_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN4_LBN 64
+#define	FRF_AB_TX_VLAN4_WIDTH 12
+#define	FRF_AB_TX_VLAN3_PORT1_EN_LBN 61
+#define	FRF_AB_TX_VLAN3_PORT1_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN3_PORT0_EN_LBN 60
+#define	FRF_AB_TX_VLAN3_PORT0_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN3_LBN 48
+#define	FRF_AB_TX_VLAN3_WIDTH 12
+#define	FRF_AB_TX_VLAN2_PORT1_EN_LBN 45
+#define	FRF_AB_TX_VLAN2_PORT1_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN2_PORT0_EN_LBN 44
+#define	FRF_AB_TX_VLAN2_PORT0_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN2_LBN 32
+#define	FRF_AB_TX_VLAN2_WIDTH 12
+#define	FRF_AB_TX_VLAN1_PORT1_EN_LBN 29
+#define	FRF_AB_TX_VLAN1_PORT1_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN1_PORT0_EN_LBN 28
+#define	FRF_AB_TX_VLAN1_PORT0_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN1_LBN 16
+#define	FRF_AB_TX_VLAN1_WIDTH 12
+#define	FRF_AB_TX_VLAN0_PORT1_EN_LBN 13
+#define	FRF_AB_TX_VLAN0_PORT1_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN0_PORT0_EN_LBN 12
+#define	FRF_AB_TX_VLAN0_PORT0_EN_WIDTH 1
+#define	FRF_AB_TX_VLAN0_LBN 0
+#define	FRF_AB_TX_VLAN0_WIDTH 12
+
+
+/*
+ * FR_AZ_TX_IPFIL_PORTEN_REG(128bit):
+ * Transmit filter control register
+ */
+#define	FR_AZ_TX_IPFIL_PORTEN_REG_OFST 0x00000af0
+/* falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AZ_TX_MADR0_FIL_EN_LBN 64
+#define	FRF_AZ_TX_MADR0_FIL_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL31_PORT_EN_LBN 62
+#define	FRF_AB_TX_IPFIL31_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL30_PORT_EN_LBN 60
+#define	FRF_AB_TX_IPFIL30_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL29_PORT_EN_LBN 58
+#define	FRF_AB_TX_IPFIL29_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL28_PORT_EN_LBN 56
+#define	FRF_AB_TX_IPFIL28_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL27_PORT_EN_LBN 54
+#define	FRF_AB_TX_IPFIL27_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL26_PORT_EN_LBN 52
+#define	FRF_AB_TX_IPFIL26_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL25_PORT_EN_LBN 50
+#define	FRF_AB_TX_IPFIL25_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL24_PORT_EN_LBN 48
+#define	FRF_AB_TX_IPFIL24_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL23_PORT_EN_LBN 46
+#define	FRF_AB_TX_IPFIL23_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL22_PORT_EN_LBN 44
+#define	FRF_AB_TX_IPFIL22_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL21_PORT_EN_LBN 42
+#define	FRF_AB_TX_IPFIL21_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL20_PORT_EN_LBN 40
+#define	FRF_AB_TX_IPFIL20_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL19_PORT_EN_LBN 38
+#define	FRF_AB_TX_IPFIL19_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL18_PORT_EN_LBN 36
+#define	FRF_AB_TX_IPFIL18_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL17_PORT_EN_LBN 34
+#define	FRF_AB_TX_IPFIL17_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL16_PORT_EN_LBN 32
+#define	FRF_AB_TX_IPFIL16_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL15_PORT_EN_LBN 30
+#define	FRF_AB_TX_IPFIL15_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL14_PORT_EN_LBN 28
+#define	FRF_AB_TX_IPFIL14_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL13_PORT_EN_LBN 26
+#define	FRF_AB_TX_IPFIL13_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL12_PORT_EN_LBN 24
+#define	FRF_AB_TX_IPFIL12_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL11_PORT_EN_LBN 22
+#define	FRF_AB_TX_IPFIL11_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL10_PORT_EN_LBN 20
+#define	FRF_AB_TX_IPFIL10_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL9_PORT_EN_LBN 18
+#define	FRF_AB_TX_IPFIL9_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL8_PORT_EN_LBN 16
+#define	FRF_AB_TX_IPFIL8_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL7_PORT_EN_LBN 14
+#define	FRF_AB_TX_IPFIL7_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL6_PORT_EN_LBN 12
+#define	FRF_AB_TX_IPFIL6_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL5_PORT_EN_LBN 10
+#define	FRF_AB_TX_IPFIL5_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL4_PORT_EN_LBN 8
+#define	FRF_AB_TX_IPFIL4_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL3_PORT_EN_LBN 6
+#define	FRF_AB_TX_IPFIL3_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL2_PORT_EN_LBN 4
+#define	FRF_AB_TX_IPFIL2_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL1_PORT_EN_LBN 2
+#define	FRF_AB_TX_IPFIL1_PORT_EN_WIDTH 1
+#define	FRF_AB_TX_IPFIL0_PORT_EN_LBN 0
+#define	FRF_AB_TX_IPFIL0_PORT_EN_WIDTH 1
+
+
+/*
+ * FR_AB_TX_IPFIL_TBL(128bit):
+ * Transmit IP source address filter table
+ */
+#define	FR_AB_TX_IPFIL_TBL_OFST 0x00000b00
+/* falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AB_TX_IPFIL_TBL_STEP 16
+#define	FR_AB_TX_IPFIL_TBL_ROWS 16
+
+#define	FRF_AB_TX_IPFIL_MASK_1_LBN 96
+#define	FRF_AB_TX_IPFIL_MASK_1_WIDTH 32
+#define	FRF_AB_TX_IP_SRC_ADR_1_LBN 64
+#define	FRF_AB_TX_IP_SRC_ADR_1_WIDTH 32
+#define	FRF_AB_TX_IPFIL_MASK_0_LBN 32
+#define	FRF_AB_TX_IPFIL_MASK_0_WIDTH 32
+#define	FRF_AB_TX_IP_SRC_ADR_0_LBN 0
+#define	FRF_AB_TX_IP_SRC_ADR_0_WIDTH 32
+
+
+/*
+ * FR_AB_MD_TXD_REG(128bit):
+ * PHY management transmit data register
+ */
+#define	FR_AB_MD_TXD_REG_OFST 0x00000c00
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MD_TXD_LBN 0
+#define	FRF_AB_MD_TXD_WIDTH 16
+
+
+/*
+ * FR_AB_MD_RXD_REG(128bit):
+ * PHY management receive data register
+ */
+#define	FR_AB_MD_RXD_REG_OFST 0x00000c10
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MD_RXD_LBN 0
+#define	FRF_AB_MD_RXD_WIDTH 16
+
+
+/*
+ * FR_AB_MD_CS_REG(128bit):
+ * PHY management configuration & status register
+ */
+#define	FR_AB_MD_CS_REG_OFST 0x00000c20
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MD_RD_EN_LBN 15
+#define	FRF_AB_MD_RD_EN_WIDTH 1
+#define	FRF_AB_MD_WR_EN_LBN 14
+#define	FRF_AB_MD_WR_EN_WIDTH 1
+#define	FRF_AB_MD_ADDR_CMD_LBN 13
+#define	FRF_AB_MD_ADDR_CMD_WIDTH 1
+#define	FRF_AB_MD_PT_LBN 7
+#define	FRF_AB_MD_PT_WIDTH 3
+#define	FRF_AB_MD_PL_LBN 6
+#define	FRF_AB_MD_PL_WIDTH 1
+#define	FRF_AB_MD_INT_CLR_LBN 5
+#define	FRF_AB_MD_INT_CLR_WIDTH 1
+#define	FRF_AB_MD_GC_LBN 4
+#define	FRF_AB_MD_GC_WIDTH 1
+#define	FRF_AB_MD_PRSP_LBN 3
+#define	FRF_AB_MD_PRSP_WIDTH 1
+#define	FRF_AB_MD_RIC_LBN 2
+#define	FRF_AB_MD_RIC_WIDTH 1
+#define	FRF_AB_MD_RDC_LBN 1
+#define	FRF_AB_MD_RDC_WIDTH 1
+#define	FRF_AB_MD_WRC_LBN 0
+#define	FRF_AB_MD_WRC_WIDTH 1
+
+
+/*
+ * FR_AB_MD_PHY_ADR_REG(128bit):
+ * PHY management PHY address register
+ */
+#define	FR_AB_MD_PHY_ADR_REG_OFST 0x00000c30
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MD_PHY_ADR_LBN 0
+#define	FRF_AB_MD_PHY_ADR_WIDTH 16
+
+
+/*
+ * FR_AB_MD_ID_REG(128bit):
+ * PHY management ID register
+ */
+#define	FR_AB_MD_ID_REG_OFST 0x00000c40
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MD_PRT_ADR_LBN 11
+#define	FRF_AB_MD_PRT_ADR_WIDTH 5
+#define	FRF_AB_MD_DEV_ADR_LBN 6
+#define	FRF_AB_MD_DEV_ADR_WIDTH 5
+
+
+/*
+ * FR_AB_MD_STAT_REG(128bit):
+ * PHY management status & mask register
+ */
+#define	FR_AB_MD_STAT_REG_OFST 0x00000c50
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MD_PINT_LBN 4
+#define	FRF_AB_MD_PINT_WIDTH 1
+#define	FRF_AB_MD_DONE_LBN 3
+#define	FRF_AB_MD_DONE_WIDTH 1
+#define	FRF_AB_MD_BSERR_LBN 2
+#define	FRF_AB_MD_BSERR_WIDTH 1
+#define	FRF_AB_MD_LNFL_LBN 1
+#define	FRF_AB_MD_LNFL_WIDTH 1
+#define	FRF_AB_MD_BSY_LBN 0
+#define	FRF_AB_MD_BSY_WIDTH 1
+
+
+/*
+ * FR_AB_MAC_STAT_DMA_REG(128bit):
+ * Port MAC statistical counter DMA register
+ */
+#define	FR_AB_MAC_STAT_DMA_REG_OFST 0x00000c60
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MAC_STAT_DMA_CMD_LBN 48
+#define	FRF_AB_MAC_STAT_DMA_CMD_WIDTH 1
+#define	FRF_AB_MAC_STAT_DMA_ADR_LBN 0
+#define	FRF_AB_MAC_STAT_DMA_ADR_WIDTH 48
+#define	FRF_AB_MAC_STAT_DMA_ADR_DW0_LBN 0
+#define	FRF_AB_MAC_STAT_DMA_ADR_DW0_WIDTH 32
+#define	FRF_AB_MAC_STAT_DMA_ADR_DW1_LBN 32
+#define	FRF_AB_MAC_STAT_DMA_ADR_DW1_WIDTH 16
+
+
+/*
+ * FR_AB_MAC_CTRL_REG(128bit):
+ * Port MAC control register
+ */
+#define	FR_AB_MAC_CTRL_REG_OFST 0x00000c80
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MAC_XOFF_VAL_LBN 16
+#define	FRF_AB_MAC_XOFF_VAL_WIDTH 16
+#define	FRF_BB_TXFIFO_DRAIN_EN_LBN 7
+#define	FRF_BB_TXFIFO_DRAIN_EN_WIDTH 1
+#define	FRF_AB_MAC_XG_DISTXCRC_LBN 5
+#define	FRF_AB_MAC_XG_DISTXCRC_WIDTH 1
+#define	FRF_AB_MAC_BCAD_ACPT_LBN 4
+#define	FRF_AB_MAC_BCAD_ACPT_WIDTH 1
+#define	FRF_AB_MAC_UC_PROM_LBN 3
+#define	FRF_AB_MAC_UC_PROM_WIDTH 1
+#define	FRF_AB_MAC_LINK_STATUS_LBN 2
+#define	FRF_AB_MAC_LINK_STATUS_WIDTH 1
+#define	FRF_AB_MAC_SPEED_LBN 0
+#define	FRF_AB_MAC_SPEED_WIDTH 2
+#define	FRF_AB_MAC_SPEED_10M 0
+#define	FRF_AB_MAC_SPEED_100M 1
+#define	FRF_AB_MAC_SPEED_1G 2
+#define	FRF_AB_MAC_SPEED_10G 3
+
+/*
+ * FR_BB_GEN_MODE_REG(128bit):
+ * General Purpose mode register (external interrupt mask)
+ */
+#define	FR_BB_GEN_MODE_REG_OFST 0x00000c90
+/* falconb0=net_func_bar2 */
+
+#define	FRF_BB_XFP_PHY_INT_POL_SEL_LBN 3
+#define	FRF_BB_XFP_PHY_INT_POL_SEL_WIDTH 1
+#define	FRF_BB_XG_PHY_INT_POL_SEL_LBN 2
+#define	FRF_BB_XG_PHY_INT_POL_SEL_WIDTH 1
+#define	FRF_BB_XFP_PHY_INT_MASK_LBN 1
+#define	FRF_BB_XFP_PHY_INT_MASK_WIDTH 1
+#define	FRF_BB_XG_PHY_INT_MASK_LBN 0
+#define	FRF_BB_XG_PHY_INT_MASK_WIDTH 1
+
+
+/*
+ * FR_AB_MAC_MC_HASH_REG0(128bit):
+ * Multicast address hash table
+ */
+#define	FR_AB_MAC_MC_HASH0_REG_OFST 0x00000ca0
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MAC_MCAST_HASH0_LBN 0
+#define	FRF_AB_MAC_MCAST_HASH0_WIDTH 128
+#define	FRF_AB_MAC_MCAST_HASH0_DW0_LBN 0
+#define	FRF_AB_MAC_MCAST_HASH0_DW0_WIDTH 32
+#define	FRF_AB_MAC_MCAST_HASH0_DW1_LBN 32
+#define	FRF_AB_MAC_MCAST_HASH0_DW1_WIDTH 32
+#define	FRF_AB_MAC_MCAST_HASH0_DW2_LBN 64
+#define	FRF_AB_MAC_MCAST_HASH0_DW2_WIDTH 32
+#define	FRF_AB_MAC_MCAST_HASH0_DW3_LBN 96
+#define	FRF_AB_MAC_MCAST_HASH0_DW3_WIDTH 32
+
+
+/*
+ * FR_AB_MAC_MC_HASH_REG1(128bit):
+ * Multicast address hash table
+ */
+#define	FR_AB_MAC_MC_HASH1_REG_OFST 0x00000cb0
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_MAC_MCAST_HASH1_LBN 0
+#define	FRF_AB_MAC_MCAST_HASH1_WIDTH 128
+#define	FRF_AB_MAC_MCAST_HASH1_DW0_LBN 0
+#define	FRF_AB_MAC_MCAST_HASH1_DW0_WIDTH 32
+#define	FRF_AB_MAC_MCAST_HASH1_DW1_LBN 32
+#define	FRF_AB_MAC_MCAST_HASH1_DW1_WIDTH 32
+#define	FRF_AB_MAC_MCAST_HASH1_DW2_LBN 64
+#define	FRF_AB_MAC_MCAST_HASH1_DW2_WIDTH 32
+#define	FRF_AB_MAC_MCAST_HASH1_DW3_LBN 96
+#define	FRF_AB_MAC_MCAST_HASH1_DW3_WIDTH 32
+
+
+/*
+ * FR_AB_GM_CFG1_REG(32bit):
+ * GMAC configuration register 1
+ */
+#define	FR_AB_GM_CFG1_REG_OFST 0x00000e00
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GM_SW_RST_LBN 31
+#define	FRF_AB_GM_SW_RST_WIDTH 1
+#define	FRF_AB_GM_SIM_RST_LBN 30
+#define	FRF_AB_GM_SIM_RST_WIDTH 1
+#define	FRF_AB_GM_RST_RX_MAC_CTL_LBN 19
+#define	FRF_AB_GM_RST_RX_MAC_CTL_WIDTH 1
+#define	FRF_AB_GM_RST_TX_MAC_CTL_LBN 18
+#define	FRF_AB_GM_RST_TX_MAC_CTL_WIDTH 1
+#define	FRF_AB_GM_RST_RX_FUNC_LBN 17
+#define	FRF_AB_GM_RST_RX_FUNC_WIDTH 1
+#define	FRF_AB_GM_RST_TX_FUNC_LBN 16
+#define	FRF_AB_GM_RST_TX_FUNC_WIDTH 1
+#define	FRF_AB_GM_LOOP_LBN 8
+#define	FRF_AB_GM_LOOP_WIDTH 1
+#define	FRF_AB_GM_RX_FC_EN_LBN 5
+#define	FRF_AB_GM_RX_FC_EN_WIDTH 1
+#define	FRF_AB_GM_TX_FC_EN_LBN 4
+#define	FRF_AB_GM_TX_FC_EN_WIDTH 1
+#define	FRF_AB_GM_SYNC_RXEN_LBN 3
+#define	FRF_AB_GM_SYNC_RXEN_WIDTH 1
+#define	FRF_AB_GM_RX_EN_LBN 2
+#define	FRF_AB_GM_RX_EN_WIDTH 1
+#define	FRF_AB_GM_SYNC_TXEN_LBN 1
+#define	FRF_AB_GM_SYNC_TXEN_WIDTH 1
+#define	FRF_AB_GM_TX_EN_LBN 0
+#define	FRF_AB_GM_TX_EN_WIDTH 1
+
+
+/*
+ * FR_AB_GM_CFG2_REG(32bit):
+ * GMAC configuration register 2
+ */
+#define	FR_AB_GM_CFG2_REG_OFST 0x00000e10
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GM_PAMBL_LEN_LBN 12
+#define	FRF_AB_GM_PAMBL_LEN_WIDTH 4
+#define	FRF_AB_GM_IF_MODE_LBN 8
+#define	FRF_AB_GM_IF_MODE_WIDTH 2
+#define	FRF_AB_GM_IF_MODE_BYTE_MODE 2
+#define	FRF_AB_GM_IF_MODE_NIBBLE_MODE 1
+#define	FRF_AB_GM_HUGE_FRM_EN_LBN 5
+#define	FRF_AB_GM_HUGE_FRM_EN_WIDTH 1
+#define	FRF_AB_GM_LEN_CHK_LBN 4
+#define	FRF_AB_GM_LEN_CHK_WIDTH 1
+#define	FRF_AB_GM_PAD_CRC_EN_LBN 2
+#define	FRF_AB_GM_PAD_CRC_EN_WIDTH 1
+#define	FRF_AB_GM_CRC_EN_LBN 1
+#define	FRF_AB_GM_CRC_EN_WIDTH 1
+#define	FRF_AB_GM_FD_LBN 0
+#define	FRF_AB_GM_FD_WIDTH 1
+
+
+/*
+ * FR_AB_GM_IPG_REG(32bit):
+ * GMAC IPG register
+ */
+#define	FR_AB_GM_IPG_REG_OFST 0x00000e20
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GM_NONB2B_IPG1_LBN 24
+#define	FRF_AB_GM_NONB2B_IPG1_WIDTH 7
+#define	FRF_AB_GM_NONB2B_IPG2_LBN 16
+#define	FRF_AB_GM_NONB2B_IPG2_WIDTH 7
+#define	FRF_AB_GM_MIN_IPG_ENF_LBN 8
+#define	FRF_AB_GM_MIN_IPG_ENF_WIDTH 8
+#define	FRF_AB_GM_B2B_IPG_LBN 0
+#define	FRF_AB_GM_B2B_IPG_WIDTH 7
+
+
+/*
+ * FR_AB_GM_HD_REG(32bit):
+ * GMAC half duplex register
+ */
+#define	FR_AB_GM_HD_REG_OFST 0x00000e30
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GM_ALT_BOFF_VAL_LBN 20
+#define	FRF_AB_GM_ALT_BOFF_VAL_WIDTH 4
+#define	FRF_AB_GM_ALT_BOFF_EN_LBN 19
+#define	FRF_AB_GM_ALT_BOFF_EN_WIDTH 1
+#define	FRF_AB_GM_BP_NO_BOFF_LBN 18
+#define	FRF_AB_GM_BP_NO_BOFF_WIDTH 1
+#define	FRF_AB_GM_DIS_BOFF_LBN 17
+#define	FRF_AB_GM_DIS_BOFF_WIDTH 1
+#define	FRF_AB_GM_EXDEF_TX_EN_LBN 16
+#define	FRF_AB_GM_EXDEF_TX_EN_WIDTH 1
+#define	FRF_AB_GM_RTRY_LIMIT_LBN 12
+#define	FRF_AB_GM_RTRY_LIMIT_WIDTH 4
+#define	FRF_AB_GM_COL_WIN_LBN 0
+#define	FRF_AB_GM_COL_WIN_WIDTH 10
+
+
+/*
+ * FR_AB_GM_MAX_FLEN_REG(32bit):
+ * GMAC maximum frame length register
+ */
+#define	FR_AB_GM_MAX_FLEN_REG_OFST 0x00000e40
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GM_MAX_FLEN_LBN 0
+#define	FRF_AB_GM_MAX_FLEN_WIDTH 16
+
+
+/*
+ * FR_AB_GM_TEST_REG(32bit):
+ * GMAC test register
+ */
+#define	FR_AB_GM_TEST_REG_OFST 0x00000e70
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GM_MAX_BOFF_LBN 3
+#define	FRF_AB_GM_MAX_BOFF_WIDTH 1
+#define	FRF_AB_GM_REG_TX_FLOW_EN_LBN 2
+#define	FRF_AB_GM_REG_TX_FLOW_EN_WIDTH 1
+#define	FRF_AB_GM_TEST_PAUSE_LBN 1
+#define	FRF_AB_GM_TEST_PAUSE_WIDTH 1
+#define	FRF_AB_GM_SHORT_SLOT_LBN 0
+#define	FRF_AB_GM_SHORT_SLOT_WIDTH 1
+
+
+/*
+ * FR_AB_GM_ADR1_REG(32bit):
+ * GMAC station address register 1
+ */
+#define	FR_AB_GM_ADR1_REG_OFST 0x00000f00
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GM_ADR_B0_LBN 24
+#define	FRF_AB_GM_ADR_B0_WIDTH 8
+#define	FRF_AB_GM_ADR_B1_LBN 16
+#define	FRF_AB_GM_ADR_B1_WIDTH 8
+#define	FRF_AB_GM_ADR_B2_LBN 8
+#define	FRF_AB_GM_ADR_B2_WIDTH 8
+#define	FRF_AB_GM_ADR_B3_LBN 0
+#define	FRF_AB_GM_ADR_B3_WIDTH 8
+
+
+/*
+ * FR_AB_GM_ADR2_REG(32bit):
+ * GMAC station address register 2
+ */
+#define	FR_AB_GM_ADR2_REG_OFST 0x00000f10
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GM_ADR_B4_LBN 24
+#define	FRF_AB_GM_ADR_B4_WIDTH 8
+#define	FRF_AB_GM_ADR_B5_LBN 16
+#define	FRF_AB_GM_ADR_B5_WIDTH 8
+
+
+/*
+ * FR_AB_GMF_CFG0_REG(32bit):
+ * GMAC FIFO configuration register 0
+ */
+#define	FR_AB_GMF_CFG0_REG_OFST 0x00000f20
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GMF_FTFENRPLY_LBN 20
+#define	FRF_AB_GMF_FTFENRPLY_WIDTH 1
+#define	FRF_AB_GMF_STFENRPLY_LBN 19
+#define	FRF_AB_GMF_STFENRPLY_WIDTH 1
+#define	FRF_AB_GMF_FRFENRPLY_LBN 18
+#define	FRF_AB_GMF_FRFENRPLY_WIDTH 1
+#define	FRF_AB_GMF_SRFENRPLY_LBN 17
+#define	FRF_AB_GMF_SRFENRPLY_WIDTH 1
+#define	FRF_AB_GMF_WTMENRPLY_LBN 16
+#define	FRF_AB_GMF_WTMENRPLY_WIDTH 1
+#define	FRF_AB_GMF_FTFENREQ_LBN 12
+#define	FRF_AB_GMF_FTFENREQ_WIDTH 1
+#define	FRF_AB_GMF_STFENREQ_LBN 11
+#define	FRF_AB_GMF_STFENREQ_WIDTH 1
+#define	FRF_AB_GMF_FRFENREQ_LBN 10
+#define	FRF_AB_GMF_FRFENREQ_WIDTH 1
+#define	FRF_AB_GMF_SRFENREQ_LBN 9
+#define	FRF_AB_GMF_SRFENREQ_WIDTH 1
+#define	FRF_AB_GMF_WTMENREQ_LBN 8
+#define	FRF_AB_GMF_WTMENREQ_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTFT_LBN 4
+#define	FRF_AB_GMF_HSTRSTFT_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTST_LBN 3
+#define	FRF_AB_GMF_HSTRSTST_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTFR_LBN 2
+#define	FRF_AB_GMF_HSTRSTFR_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTSR_LBN 1
+#define	FRF_AB_GMF_HSTRSTSR_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTWT_LBN 0
+#define	FRF_AB_GMF_HSTRSTWT_WIDTH 1
+
+
+/*
+ * FR_AB_GMF_CFG1_REG(32bit):
+ * GMAC FIFO configuration register 1
+ */
+#define	FR_AB_GMF_CFG1_REG_OFST 0x00000f30
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GMF_CFGFRTH_LBN 16
+#define	FRF_AB_GMF_CFGFRTH_WIDTH 5
+#define	FRF_AB_GMF_CFGXOFFRTX_LBN 0
+#define	FRF_AB_GMF_CFGXOFFRTX_WIDTH 16
+
+
+/*
+ * FR_AB_GMF_CFG2_REG(32bit):
+ * GMAC FIFO configuration register 2
+ */
+#define	FR_AB_GMF_CFG2_REG_OFST 0x00000f40
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GMF_CFGHWM_LBN 16
+#define	FRF_AB_GMF_CFGHWM_WIDTH 6
+#define	FRF_AB_GMF_CFGLWM_LBN 0
+#define	FRF_AB_GMF_CFGLWM_WIDTH 6
+
+
+/*
+ * FR_AB_GMF_CFG3_REG(32bit):
+ * GMAC FIFO configuration register 3
+ */
+#define	FR_AB_GMF_CFG3_REG_OFST 0x00000f50
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GMF_CFGHWMFT_LBN 16
+#define	FRF_AB_GMF_CFGHWMFT_WIDTH 6
+#define	FRF_AB_GMF_CFGFTTH_LBN 0
+#define	FRF_AB_GMF_CFGFTTH_WIDTH 6
+
+
+/*
+ * FR_AB_GMF_CFG4_REG(32bit):
+ * GMAC FIFO configuration register 4
+ */
+#define	FR_AB_GMF_CFG4_REG_OFST 0x00000f60
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GMF_HSTFLTRFRM_LBN 0
+#define	FRF_AB_GMF_HSTFLTRFRM_WIDTH 18
+
+
+/*
+ * FR_AB_GMF_CFG5_REG(32bit):
+ * GMAC FIFO configuration register 5
+ */
+#define	FR_AB_GMF_CFG5_REG_OFST 0x00000f70
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_GMF_CFGHDPLX_LBN 22
+#define	FRF_AB_GMF_CFGHDPLX_WIDTH 1
+#define	FRF_AB_GMF_SRFULL_LBN 21
+#define	FRF_AB_GMF_SRFULL_WIDTH 1
+#define	FRF_AB_GMF_HSTSRFULLCLR_LBN 20
+#define	FRF_AB_GMF_HSTSRFULLCLR_WIDTH 1
+#define	FRF_AB_GMF_CFGBYTMODE_LBN 19
+#define	FRF_AB_GMF_CFGBYTMODE_WIDTH 1
+#define	FRF_AB_GMF_HSTDRPLT64_LBN 18
+#define	FRF_AB_GMF_HSTDRPLT64_WIDTH 1
+#define	FRF_AB_GMF_HSTFLTRFRMDC_LBN 0
+#define	FRF_AB_GMF_HSTFLTRFRMDC_WIDTH 18
+
+
+/*
+ * FR_BB_TX_SRC_MAC_TBL(128bit):
+ * Transmit IP source address filter table
+ */
+#define	FR_BB_TX_SRC_MAC_TBL_OFST 0x00001000
+/* falconb0=net_func_bar2 */
+#define	FR_BB_TX_SRC_MAC_TBL_STEP 16
+#define	FR_BB_TX_SRC_MAC_TBL_ROWS 16
+
+#define	FRF_BB_TX_SRC_MAC_ADR_1_LBN 64
+#define	FRF_BB_TX_SRC_MAC_ADR_1_WIDTH 48
+#define	FRF_BB_TX_SRC_MAC_ADR_1_DW0_LBN 64
+#define	FRF_BB_TX_SRC_MAC_ADR_1_DW0_WIDTH 32
+#define	FRF_BB_TX_SRC_MAC_ADR_1_DW1_LBN 96
+#define	FRF_BB_TX_SRC_MAC_ADR_1_DW1_WIDTH 16
+#define	FRF_BB_TX_SRC_MAC_ADR_0_LBN 0
+#define	FRF_BB_TX_SRC_MAC_ADR_0_WIDTH 48
+#define	FRF_BB_TX_SRC_MAC_ADR_0_DW0_LBN 0
+#define	FRF_BB_TX_SRC_MAC_ADR_0_DW0_WIDTH 32
+#define	FRF_BB_TX_SRC_MAC_ADR_0_DW1_LBN 32
+#define	FRF_BB_TX_SRC_MAC_ADR_0_DW1_WIDTH 16
+
+
+/*
+ * FR_BB_TX_SRC_MAC_CTL_REG(128bit):
+ * Transmit MAC source address filter control
+ */
+#define	FR_BB_TX_SRC_MAC_CTL_REG_OFST 0x00001100
+/* falconb0=net_func_bar2 */
+
+#define	FRF_BB_TX_SRC_DROP_CTR_LBN 16
+#define	FRF_BB_TX_SRC_DROP_CTR_WIDTH 16
+#define	FRF_BB_TX_SRC_FLTR_EN_LBN 15
+#define	FRF_BB_TX_SRC_FLTR_EN_WIDTH 1
+#define	FRF_BB_TX_DROP_CTR_CLR_LBN 12
+#define	FRF_BB_TX_DROP_CTR_CLR_WIDTH 1
+#define	FRF_BB_TX_MAC_QID_SEL_LBN 0
+#define	FRF_BB_TX_MAC_QID_SEL_WIDTH 3
+
+
+/*
+ * FR_AB_XM_ADR_LO_REG(128bit):
+ * XGMAC address register low
+ */
+#define	FR_AB_XM_ADR_LO_REG_OFST 0x00001200
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_ADR_LO_LBN 0
+#define	FRF_AB_XM_ADR_LO_WIDTH 32
+
+
+/*
+ * FR_AB_XM_ADR_HI_REG(128bit):
+ * XGMAC address register high
+ */
+#define	FR_AB_XM_ADR_HI_REG_OFST 0x00001210
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_ADR_HI_LBN 0
+#define	FRF_AB_XM_ADR_HI_WIDTH 16
+
+
+/*
+ * FR_AB_XM_GLB_CFG_REG(128bit):
+ * XGMAC global configuration
+ */
+#define	FR_AB_XM_GLB_CFG_REG_OFST 0x00001220
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_RMTFLT_GEN_LBN 17
+#define	FRF_AB_XM_RMTFLT_GEN_WIDTH 1
+#define	FRF_AB_XM_DEBUG_MODE_LBN 16
+#define	FRF_AB_XM_DEBUG_MODE_WIDTH 1
+#define	FRF_AB_XM_RX_STAT_EN_LBN 11
+#define	FRF_AB_XM_RX_STAT_EN_WIDTH 1
+#define	FRF_AB_XM_TX_STAT_EN_LBN 10
+#define	FRF_AB_XM_TX_STAT_EN_WIDTH 1
+#define	FRF_AB_XM_RX_JUMBO_MODE_LBN 6
+#define	FRF_AB_XM_RX_JUMBO_MODE_WIDTH 1
+#define	FRF_AB_XM_WAN_MODE_LBN 5
+#define	FRF_AB_XM_WAN_MODE_WIDTH 1
+#define	FRF_AB_XM_INTCLR_MODE_LBN 3
+#define	FRF_AB_XM_INTCLR_MODE_WIDTH 1
+#define	FRF_AB_XM_CORE_RST_LBN 0
+#define	FRF_AB_XM_CORE_RST_WIDTH 1
+
+
+/*
+ * FR_AB_XM_TX_CFG_REG(128bit):
+ * XGMAC transmit configuration
+ */
+#define	FR_AB_XM_TX_CFG_REG_OFST 0x00001230
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_TX_PROG_LBN 24
+#define	FRF_AB_XM_TX_PROG_WIDTH 1
+#define	FRF_AB_XM_IPG_LBN 16
+#define	FRF_AB_XM_IPG_WIDTH 4
+#define	FRF_AB_XM_FCNTL_LBN 10
+#define	FRF_AB_XM_FCNTL_WIDTH 1
+#define	FRF_AB_XM_TXCRC_LBN 8
+#define	FRF_AB_XM_TXCRC_WIDTH 1
+#define	FRF_AB_XM_EDRC_LBN 6
+#define	FRF_AB_XM_EDRC_WIDTH 1
+#define	FRF_AB_XM_AUTO_PAD_LBN 5
+#define	FRF_AB_XM_AUTO_PAD_WIDTH 1
+#define	FRF_AB_XM_TX_PRMBL_LBN 2
+#define	FRF_AB_XM_TX_PRMBL_WIDTH 1
+#define	FRF_AB_XM_TXEN_LBN 1
+#define	FRF_AB_XM_TXEN_WIDTH 1
+#define	FRF_AB_XM_TX_RST_LBN 0
+#define	FRF_AB_XM_TX_RST_WIDTH 1
+
+
+/*
+ * FR_AB_XM_RX_CFG_REG(128bit):
+ * XGMAC receive configuration
+ */
+#define	FR_AB_XM_RX_CFG_REG_OFST 0x00001240
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_PASS_LENERR_LBN 26
+#define	FRF_AB_XM_PASS_LENERR_WIDTH 1
+#define	FRF_AB_XM_PASS_CRC_ERR_LBN 25
+#define	FRF_AB_XM_PASS_CRC_ERR_WIDTH 1
+#define	FRF_AB_XM_PASS_PRMBLE_ERR_LBN 24
+#define	FRF_AB_XM_PASS_PRMBLE_ERR_WIDTH 1
+#define	FRF_AB_XM_REJ_BCAST_LBN 20
+#define	FRF_AB_XM_REJ_BCAST_WIDTH 1
+#define	FRF_AB_XM_ACPT_ALL_MCAST_LBN 11
+#define	FRF_AB_XM_ACPT_ALL_MCAST_WIDTH 1
+#define	FRF_AB_XM_ACPT_ALL_UCAST_LBN 9
+#define	FRF_AB_XM_ACPT_ALL_UCAST_WIDTH 1
+#define	FRF_AB_XM_AUTO_DEPAD_LBN 8
+#define	FRF_AB_XM_AUTO_DEPAD_WIDTH 1
+#define	FRF_AB_XM_RXCRC_LBN 3
+#define	FRF_AB_XM_RXCRC_WIDTH 1
+#define	FRF_AB_XM_RX_PRMBL_LBN 2
+#define	FRF_AB_XM_RX_PRMBL_WIDTH 1
+#define	FRF_AB_XM_RXEN_LBN 1
+#define	FRF_AB_XM_RXEN_WIDTH 1
+#define	FRF_AB_XM_RX_RST_LBN 0
+#define	FRF_AB_XM_RX_RST_WIDTH 1
+
+
+/*
+ * FR_AB_XM_MGT_INT_MASK(128bit):
+ * documentation to be written for sum_XM_MGT_INT_MASK
+ */
+#define	FR_AB_XM_MGT_INT_MASK_OFST 0x00001250
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_MSK_STA_INTR_LBN 16
+#define	FRF_AB_XM_MSK_STA_INTR_WIDTH 1
+#define	FRF_AB_XM_MSK_STAT_CNTR_HF_LBN 9
+#define	FRF_AB_XM_MSK_STAT_CNTR_HF_WIDTH 1
+#define	FRF_AB_XM_MSK_STAT_CNTR_OF_LBN 8
+#define	FRF_AB_XM_MSK_STAT_CNTR_OF_WIDTH 1
+#define	FRF_AB_XM_MSK_PRMBLE_ERR_LBN 2
+#define	FRF_AB_XM_MSK_PRMBLE_ERR_WIDTH 1
+#define	FRF_AB_XM_MSK_RMTFLT_LBN 1
+#define	FRF_AB_XM_MSK_RMTFLT_WIDTH 1
+#define	FRF_AB_XM_MSK_LCLFLT_LBN 0
+#define	FRF_AB_XM_MSK_LCLFLT_WIDTH 1
+
+
+/*
+ * FR_AB_XM_FC_REG(128bit):
+ * XGMAC flow control register
+ */
+#define	FR_AB_XM_FC_REG_OFST 0x00001270
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_PAUSE_TIME_LBN 16
+#define	FRF_AB_XM_PAUSE_TIME_WIDTH 16
+#define	FRF_AB_XM_RX_MAC_STAT_LBN 11
+#define	FRF_AB_XM_RX_MAC_STAT_WIDTH 1
+#define	FRF_AB_XM_TX_MAC_STAT_LBN 10
+#define	FRF_AB_XM_TX_MAC_STAT_WIDTH 1
+#define	FRF_AB_XM_MCNTL_PASS_LBN 8
+#define	FRF_AB_XM_MCNTL_PASS_WIDTH 2
+#define	FRF_AB_XM_REJ_CNTL_UCAST_LBN 6
+#define	FRF_AB_XM_REJ_CNTL_UCAST_WIDTH 1
+#define	FRF_AB_XM_REJ_CNTL_MCAST_LBN 5
+#define	FRF_AB_XM_REJ_CNTL_MCAST_WIDTH 1
+#define	FRF_AB_XM_ZPAUSE_LBN 2
+#define	FRF_AB_XM_ZPAUSE_WIDTH 1
+#define	FRF_AB_XM_XMIT_PAUSE_LBN 1
+#define	FRF_AB_XM_XMIT_PAUSE_WIDTH 1
+#define	FRF_AB_XM_DIS_FCNTL_LBN 0
+#define	FRF_AB_XM_DIS_FCNTL_WIDTH 1
+
+
+/*
+ * FR_AB_XM_PAUSE_TIME_REG(128bit):
+ * XGMAC pause time register
+ */
+#define	FR_AB_XM_PAUSE_TIME_REG_OFST 0x00001290
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_TX_PAUSE_CNT_LBN 16
+#define	FRF_AB_XM_TX_PAUSE_CNT_WIDTH 16
+#define	FRF_AB_XM_RX_PAUSE_CNT_LBN 0
+#define	FRF_AB_XM_RX_PAUSE_CNT_WIDTH 16
+
+
+/*
+ * FR_AB_XM_TX_PARAM_REG(128bit):
+ * XGMAC transmit parameter register
+ */
+#define	FR_AB_XM_TX_PARAM_REG_OFST 0x000012d0
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_TX_JUMBO_MODE_LBN 31
+#define	FRF_AB_XM_TX_JUMBO_MODE_WIDTH 1
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_HI_LBN 19
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_HI_WIDTH 11
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_LO_LBN 16
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_LO_WIDTH 3
+#define	FRF_AB_XM_PAD_CHAR_LBN 0
+#define	FRF_AB_XM_PAD_CHAR_WIDTH 8
+
+
+/*
+ * FR_AB_XM_RX_PARAM_REG(128bit):
+ * XGMAC receive parameter register
+ */
+#define	FR_AB_XM_RX_PARAM_REG_OFST 0x000012e0
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_HI_LBN 3
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_HI_WIDTH 11
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_LO_LBN 0
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_LO_WIDTH 3
+
+
+/*
+ * FR_AB_XM_MGT_INT_MSK_REG(128bit):
+ * XGMAC management interrupt mask register
+ */
+#define	FR_AB_XM_MGT_INT_REG_OFST 0x000012f0
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XM_STAT_CNTR_OF_LBN 9
+#define	FRF_AB_XM_STAT_CNTR_OF_WIDTH 1
+#define	FRF_AB_XM_STAT_CNTR_HF_LBN 8
+#define	FRF_AB_XM_STAT_CNTR_HF_WIDTH 1
+#define	FRF_AB_XM_PRMBLE_ERR_LBN 2
+#define	FRF_AB_XM_PRMBLE_ERR_WIDTH 1
+#define	FRF_AB_XM_RMTFLT_LBN 1
+#define	FRF_AB_XM_RMTFLT_WIDTH 1
+#define	FRF_AB_XM_LCLFLT_LBN 0
+#define	FRF_AB_XM_LCLFLT_WIDTH 1
+
+
+/*
+ * FR_AB_XX_PWR_RST_REG(128bit):
+ * XGXS/XAUI powerdown/reset register
+ */
+#define	FR_AB_XX_PWR_RST_REG_OFST 0x00001300
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XX_PWRDND_SIG_LBN 31
+#define	FRF_AB_XX_PWRDND_SIG_WIDTH 1
+#define	FRF_AB_XX_PWRDNC_SIG_LBN 30
+#define	FRF_AB_XX_PWRDNC_SIG_WIDTH 1
+#define	FRF_AB_XX_PWRDNB_SIG_LBN 29
+#define	FRF_AB_XX_PWRDNB_SIG_WIDTH 1
+#define	FRF_AB_XX_PWRDNA_SIG_LBN 28
+#define	FRF_AB_XX_PWRDNA_SIG_WIDTH 1
+#define	FRF_AB_XX_SIM_MODE_LBN 27
+#define	FRF_AB_XX_SIM_MODE_WIDTH 1
+#define	FRF_AB_XX_RSTPLLCD_SIG_LBN 25
+#define	FRF_AB_XX_RSTPLLCD_SIG_WIDTH 1
+#define	FRF_AB_XX_RSTPLLAB_SIG_LBN 24
+#define	FRF_AB_XX_RSTPLLAB_SIG_WIDTH 1
+#define	FRF_AB_XX_RESETD_SIG_LBN 23
+#define	FRF_AB_XX_RESETD_SIG_WIDTH 1
+#define	FRF_AB_XX_RESETC_SIG_LBN 22
+#define	FRF_AB_XX_RESETC_SIG_WIDTH 1
+#define	FRF_AB_XX_RESETB_SIG_LBN 21
+#define	FRF_AB_XX_RESETB_SIG_WIDTH 1
+#define	FRF_AB_XX_RESETA_SIG_LBN 20
+#define	FRF_AB_XX_RESETA_SIG_WIDTH 1
+#define	FRF_AB_XX_RSTXGXSRX_SIG_LBN 18
+#define	FRF_AB_XX_RSTXGXSRX_SIG_WIDTH 1
+#define	FRF_AB_XX_RSTXGXSTX_SIG_LBN 17
+#define	FRF_AB_XX_RSTXGXSTX_SIG_WIDTH 1
+#define	FRF_AB_XX_SD_RST_ACT_LBN 16
+#define	FRF_AB_XX_SD_RST_ACT_WIDTH 1
+#define	FRF_AB_XX_PWRDND_EN_LBN 15
+#define	FRF_AB_XX_PWRDND_EN_WIDTH 1
+#define	FRF_AB_XX_PWRDNC_EN_LBN 14
+#define	FRF_AB_XX_PWRDNC_EN_WIDTH 1
+#define	FRF_AB_XX_PWRDNB_EN_LBN 13
+#define	FRF_AB_XX_PWRDNB_EN_WIDTH 1
+#define	FRF_AB_XX_PWRDNA_EN_LBN 12
+#define	FRF_AB_XX_PWRDNA_EN_WIDTH 1
+#define	FRF_AB_XX_RSTPLLCD_EN_LBN 9
+#define	FRF_AB_XX_RSTPLLCD_EN_WIDTH 1
+#define	FRF_AB_XX_RSTPLLAB_EN_LBN 8
+#define	FRF_AB_XX_RSTPLLAB_EN_WIDTH 1
+#define	FRF_AB_XX_RESETD_EN_LBN 7
+#define	FRF_AB_XX_RESETD_EN_WIDTH 1
+#define	FRF_AB_XX_RESETC_EN_LBN 6
+#define	FRF_AB_XX_RESETC_EN_WIDTH 1
+#define	FRF_AB_XX_RESETB_EN_LBN 5
+#define	FRF_AB_XX_RESETB_EN_WIDTH 1
+#define	FRF_AB_XX_RESETA_EN_LBN 4
+#define	FRF_AB_XX_RESETA_EN_WIDTH 1
+#define	FRF_AB_XX_RSTXGXSRX_EN_LBN 2
+#define	FRF_AB_XX_RSTXGXSRX_EN_WIDTH 1
+#define	FRF_AB_XX_RSTXGXSTX_EN_LBN 1
+#define	FRF_AB_XX_RSTXGXSTX_EN_WIDTH 1
+#define	FRF_AB_XX_RST_XX_EN_LBN 0
+#define	FRF_AB_XX_RST_XX_EN_WIDTH 1
+
+
+/*
+ * FR_AB_XX_SD_CTL_REG(128bit):
+ * XGXS/XAUI powerdown/reset control register
+ */
+#define	FR_AB_XX_SD_CTL_REG_OFST 0x00001310
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XX_TERMADJ1_LBN 17
+#define	FRF_AB_XX_TERMADJ1_WIDTH 1
+#define	FRF_AB_XX_TERMADJ0_LBN 16
+#define	FRF_AB_XX_TERMADJ0_WIDTH 1
+#define	FRF_AB_XX_HIDRVD_LBN 15
+#define	FRF_AB_XX_HIDRVD_WIDTH 1
+#define	FRF_AB_XX_LODRVD_LBN 14
+#define	FRF_AB_XX_LODRVD_WIDTH 1
+#define	FRF_AB_XX_HIDRVC_LBN 13
+#define	FRF_AB_XX_HIDRVC_WIDTH 1
+#define	FRF_AB_XX_LODRVC_LBN 12
+#define	FRF_AB_XX_LODRVC_WIDTH 1
+#define	FRF_AB_XX_HIDRVB_LBN 11
+#define	FRF_AB_XX_HIDRVB_WIDTH 1
+#define	FRF_AB_XX_LODRVB_LBN 10
+#define	FRF_AB_XX_LODRVB_WIDTH 1
+#define	FRF_AB_XX_HIDRVA_LBN 9
+#define	FRF_AB_XX_HIDRVA_WIDTH 1
+#define	FRF_AB_XX_LODRVA_LBN 8
+#define	FRF_AB_XX_LODRVA_WIDTH 1
+#define	FRF_AB_XX_LPBKD_LBN 3
+#define	FRF_AB_XX_LPBKD_WIDTH 1
+#define	FRF_AB_XX_LPBKC_LBN 2
+#define	FRF_AB_XX_LPBKC_WIDTH 1
+#define	FRF_AB_XX_LPBKB_LBN 1
+#define	FRF_AB_XX_LPBKB_WIDTH 1
+#define	FRF_AB_XX_LPBKA_LBN 0
+#define	FRF_AB_XX_LPBKA_WIDTH 1
+
+
+/*
+ * FR_AB_XX_TXDRV_CTL_REG(128bit):
+ * XAUI SerDes transmit drive control register
+ */
+#define	FR_AB_XX_TXDRV_CTL_REG_OFST 0x00001320
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XX_DEQD_LBN 28
+#define	FRF_AB_XX_DEQD_WIDTH 4
+#define	FRF_AB_XX_DEQC_LBN 24
+#define	FRF_AB_XX_DEQC_WIDTH 4
+#define	FRF_AB_XX_DEQB_LBN 20
+#define	FRF_AB_XX_DEQB_WIDTH 4
+#define	FRF_AB_XX_DEQA_LBN 16
+#define	FRF_AB_XX_DEQA_WIDTH 4
+#define	FRF_AB_XX_DTXD_LBN 12
+#define	FRF_AB_XX_DTXD_WIDTH 4
+#define	FRF_AB_XX_DTXC_LBN 8
+#define	FRF_AB_XX_DTXC_WIDTH 4
+#define	FRF_AB_XX_DTXB_LBN 4
+#define	FRF_AB_XX_DTXB_WIDTH 4
+#define	FRF_AB_XX_DTXA_LBN 0
+#define	FRF_AB_XX_DTXA_WIDTH 4
+
+
+/*
+ * FR_AB_XX_PRBS_CTL_REG(128bit):
+ * documentation to be written for sum_XX_PRBS_CTL_REG
+ */
+#define	FR_AB_XX_PRBS_CTL_REG_OFST 0x00001330
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XX_CH3_RX_PRBS_SEL_LBN 30
+#define	FRF_AB_XX_CH3_RX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH3_RX_PRBS_INV_LBN 29
+#define	FRF_AB_XX_CH3_RX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH3_RX_PRBS_CHKEN_LBN 28
+#define	FRF_AB_XX_CH3_RX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH2_RX_PRBS_SEL_LBN 26
+#define	FRF_AB_XX_CH2_RX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH2_RX_PRBS_INV_LBN 25
+#define	FRF_AB_XX_CH2_RX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH2_RX_PRBS_CHKEN_LBN 24
+#define	FRF_AB_XX_CH2_RX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH1_RX_PRBS_SEL_LBN 22
+#define	FRF_AB_XX_CH1_RX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH1_RX_PRBS_INV_LBN 21
+#define	FRF_AB_XX_CH1_RX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH1_RX_PRBS_CHKEN_LBN 20
+#define	FRF_AB_XX_CH1_RX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH0_RX_PRBS_SEL_LBN 18
+#define	FRF_AB_XX_CH0_RX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH0_RX_PRBS_INV_LBN 17
+#define	FRF_AB_XX_CH0_RX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH0_RX_PRBS_CHKEN_LBN 16
+#define	FRF_AB_XX_CH0_RX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH3_TX_PRBS_SEL_LBN 14
+#define	FRF_AB_XX_CH3_TX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH3_TX_PRBS_INV_LBN 13
+#define	FRF_AB_XX_CH3_TX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH3_TX_PRBS_CHKEN_LBN 12
+#define	FRF_AB_XX_CH3_TX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH2_TX_PRBS_SEL_LBN 10
+#define	FRF_AB_XX_CH2_TX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH2_TX_PRBS_INV_LBN 9
+#define	FRF_AB_XX_CH2_TX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH2_TX_PRBS_CHKEN_LBN 8
+#define	FRF_AB_XX_CH2_TX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH1_TX_PRBS_SEL_LBN 6
+#define	FRF_AB_XX_CH1_TX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH1_TX_PRBS_INV_LBN 5
+#define	FRF_AB_XX_CH1_TX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH1_TX_PRBS_CHKEN_LBN 4
+#define	FRF_AB_XX_CH1_TX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH0_TX_PRBS_SEL_LBN 2
+#define	FRF_AB_XX_CH0_TX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH0_TX_PRBS_INV_LBN 1
+#define	FRF_AB_XX_CH0_TX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH0_TX_PRBS_CHKEN_LBN 0
+#define	FRF_AB_XX_CH0_TX_PRBS_CHKEN_WIDTH 1
+
+
+/*
+ * FR_AB_XX_PRBS_CHK_REG(128bit):
+ * documentation to be written for sum_XX_PRBS_CHK_REG
+ */
+#define	FR_AB_XX_PRBS_CHK_REG_OFST 0x00001340
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XX_REV_LB_EN_LBN 16
+#define	FRF_AB_XX_REV_LB_EN_WIDTH 1
+#define	FRF_AB_XX_CH3_DEG_DET_LBN 15
+#define	FRF_AB_XX_CH3_DEG_DET_WIDTH 1
+#define	FRF_AB_XX_CH3_LFSR_LOCK_IND_LBN 14
+#define	FRF_AB_XX_CH3_LFSR_LOCK_IND_WIDTH 1
+#define	FRF_AB_XX_CH3_PRBS_FRUN_LBN 13
+#define	FRF_AB_XX_CH3_PRBS_FRUN_WIDTH 1
+#define	FRF_AB_XX_CH3_ERR_CHK_LBN 12
+#define	FRF_AB_XX_CH3_ERR_CHK_WIDTH 1
+#define	FRF_AB_XX_CH2_DEG_DET_LBN 11
+#define	FRF_AB_XX_CH2_DEG_DET_WIDTH 1
+#define	FRF_AB_XX_CH2_LFSR_LOCK_IND_LBN 10
+#define	FRF_AB_XX_CH2_LFSR_LOCK_IND_WIDTH 1
+#define	FRF_AB_XX_CH2_PRBS_FRUN_LBN 9
+#define	FRF_AB_XX_CH2_PRBS_FRUN_WIDTH 1
+#define	FRF_AB_XX_CH2_ERR_CHK_LBN 8
+#define	FRF_AB_XX_CH2_ERR_CHK_WIDTH 1
+#define	FRF_AB_XX_CH1_DEG_DET_LBN 7
+#define	FRF_AB_XX_CH1_DEG_DET_WIDTH 1
+#define	FRF_AB_XX_CH1_LFSR_LOCK_IND_LBN 6
+#define	FRF_AB_XX_CH1_LFSR_LOCK_IND_WIDTH 1
+#define	FRF_AB_XX_CH1_PRBS_FRUN_LBN 5
+#define	FRF_AB_XX_CH1_PRBS_FRUN_WIDTH 1
+#define	FRF_AB_XX_CH1_ERR_CHK_LBN 4
+#define	FRF_AB_XX_CH1_ERR_CHK_WIDTH 1
+#define	FRF_AB_XX_CH0_DEG_DET_LBN 3
+#define	FRF_AB_XX_CH0_DEG_DET_WIDTH 1
+#define	FRF_AB_XX_CH0_LFSR_LOCK_IND_LBN 2
+#define	FRF_AB_XX_CH0_LFSR_LOCK_IND_WIDTH 1
+#define	FRF_AB_XX_CH0_PRBS_FRUN_LBN 1
+#define	FRF_AB_XX_CH0_PRBS_FRUN_WIDTH 1
+#define	FRF_AB_XX_CH0_ERR_CHK_LBN 0
+#define	FRF_AB_XX_CH0_ERR_CHK_WIDTH 1
+
+
+/*
+ * FR_AB_XX_PRBS_ERR_REG(128bit):
+ * documentation to be written for sum_XX_PRBS_ERR_REG
+ */
+#define	FR_AB_XX_PRBS_ERR_REG_OFST 0x00001350
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XX_CH3_PRBS_ERR_CNT_LBN 24
+#define	FRF_AB_XX_CH3_PRBS_ERR_CNT_WIDTH 8
+#define	FRF_AB_XX_CH2_PRBS_ERR_CNT_LBN 16
+#define	FRF_AB_XX_CH2_PRBS_ERR_CNT_WIDTH 8
+#define	FRF_AB_XX_CH1_PRBS_ERR_CNT_LBN 8
+#define	FRF_AB_XX_CH1_PRBS_ERR_CNT_WIDTH 8
+#define	FRF_AB_XX_CH0_PRBS_ERR_CNT_LBN 0
+#define	FRF_AB_XX_CH0_PRBS_ERR_CNT_WIDTH 8
+
+
+/*
+ * FR_AB_XX_CORE_STAT_REG(128bit):
+ * XAUI XGXS core status register
+ */
+#define	FR_AB_XX_CORE_STAT_REG_OFST 0x00001360
+/* falcona0,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+
+#define	FRF_AB_XX_FORCE_SIG3_LBN 31
+#define	FRF_AB_XX_FORCE_SIG3_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG3_VAL_LBN 30
+#define	FRF_AB_XX_FORCE_SIG3_VAL_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG2_LBN 29
+#define	FRF_AB_XX_FORCE_SIG2_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG2_VAL_LBN 28
+#define	FRF_AB_XX_FORCE_SIG2_VAL_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG1_LBN 27
+#define	FRF_AB_XX_FORCE_SIG1_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG1_VAL_LBN 26
+#define	FRF_AB_XX_FORCE_SIG1_VAL_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG0_LBN 25
+#define	FRF_AB_XX_FORCE_SIG0_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG0_VAL_LBN 24
+#define	FRF_AB_XX_FORCE_SIG0_VAL_WIDTH 1
+#define	FRF_AB_XX_XGXS_LB_EN_LBN 23
+#define	FRF_AB_XX_XGXS_LB_EN_WIDTH 1
+#define	FRF_AB_XX_XGMII_LB_EN_LBN 22
+#define	FRF_AB_XX_XGMII_LB_EN_WIDTH 1
+#define	FRF_AB_XX_MATCH_FAULT_LBN 21
+#define	FRF_AB_XX_MATCH_FAULT_WIDTH 1
+#define	FRF_AB_XX_ALIGN_DONE_LBN 20
+#define	FRF_AB_XX_ALIGN_DONE_WIDTH 1
+#define	FRF_AB_XX_SYNC_STAT3_LBN 19
+#define	FRF_AB_XX_SYNC_STAT3_WIDTH 1
+#define	FRF_AB_XX_SYNC_STAT2_LBN 18
+#define	FRF_AB_XX_SYNC_STAT2_WIDTH 1
+#define	FRF_AB_XX_SYNC_STAT1_LBN 17
+#define	FRF_AB_XX_SYNC_STAT1_WIDTH 1
+#define	FRF_AB_XX_SYNC_STAT0_LBN 16
+#define	FRF_AB_XX_SYNC_STAT0_WIDTH 1
+#define	FRF_AB_XX_COMMA_DET_CH3_LBN 15
+#define	FRF_AB_XX_COMMA_DET_CH3_WIDTH 1
+#define	FRF_AB_XX_COMMA_DET_CH2_LBN 14
+#define	FRF_AB_XX_COMMA_DET_CH2_WIDTH 1
+#define	FRF_AB_XX_COMMA_DET_CH1_LBN 13
+#define	FRF_AB_XX_COMMA_DET_CH1_WIDTH 1
+#define	FRF_AB_XX_COMMA_DET_CH0_LBN 12
+#define	FRF_AB_XX_COMMA_DET_CH0_WIDTH 1
+#define	FRF_AB_XX_CGRP_ALIGN_CH3_LBN 11
+#define	FRF_AB_XX_CGRP_ALIGN_CH3_WIDTH 1
+#define	FRF_AB_XX_CGRP_ALIGN_CH2_LBN 10
+#define	FRF_AB_XX_CGRP_ALIGN_CH2_WIDTH 1
+#define	FRF_AB_XX_CGRP_ALIGN_CH1_LBN 9
+#define	FRF_AB_XX_CGRP_ALIGN_CH1_WIDTH 1
+#define	FRF_AB_XX_CGRP_ALIGN_CH0_LBN 8
+#define	FRF_AB_XX_CGRP_ALIGN_CH0_WIDTH 1
+#define	FRF_AB_XX_CHAR_ERR_CH3_LBN 7
+#define	FRF_AB_XX_CHAR_ERR_CH3_WIDTH 1
+#define	FRF_AB_XX_CHAR_ERR_CH2_LBN 6
+#define	FRF_AB_XX_CHAR_ERR_CH2_WIDTH 1
+#define	FRF_AB_XX_CHAR_ERR_CH1_LBN 5
+#define	FRF_AB_XX_CHAR_ERR_CH1_WIDTH 1
+#define	FRF_AB_XX_CHAR_ERR_CH0_LBN 4
+#define	FRF_AB_XX_CHAR_ERR_CH0_WIDTH 1
+#define	FRF_AB_XX_DISPERR_CH3_LBN 3
+#define	FRF_AB_XX_DISPERR_CH3_WIDTH 1
+#define	FRF_AB_XX_DISPERR_CH2_LBN 2
+#define	FRF_AB_XX_DISPERR_CH2_WIDTH 1
+#define	FRF_AB_XX_DISPERR_CH1_LBN 1
+#define	FRF_AB_XX_DISPERR_CH1_WIDTH 1
+#define	FRF_AB_XX_DISPERR_CH0_LBN 0
+#define	FRF_AB_XX_DISPERR_CH0_WIDTH 1
+
+
+/*
+ * FR_AA_RX_DESC_PTR_TBL_KER(128bit):
+ * Receive descriptor pointer table
+ */
+#define	FR_AA_RX_DESC_PTR_TBL_KER_OFST 0x00011800
+/* falcona0=net_func_bar2 */
+#define	FR_AA_RX_DESC_PTR_TBL_KER_STEP 16
+#define	FR_AA_RX_DESC_PTR_TBL_KER_ROWS 4
+/*
+ * FR_AZ_RX_DESC_PTR_TBL(128bit):
+ * Receive descriptor pointer table
+ */
+#define	FR_AZ_RX_DESC_PTR_TBL_OFST 0x00f40000
+/* sienaa0=net_func_bar2,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_RX_DESC_PTR_TBL_STEP 16
+#define	FR_CZ_RX_DESC_PTR_TBL_ROWS 1024
+#define	FR_AB_RX_DESC_PTR_TBL_ROWS 4096
+
+#define	FRF_CZ_RX_HDR_SPLIT_LBN 90
+#define	FRF_CZ_RX_HDR_SPLIT_WIDTH 1
+#define	FRF_AZ_RX_RESET_LBN 89
+#define	FRF_AZ_RX_RESET_WIDTH 1
+#define	FRF_AZ_RX_ISCSI_DDIG_EN_LBN 88
+#define	FRF_AZ_RX_ISCSI_DDIG_EN_WIDTH 1
+#define	FRF_AZ_RX_ISCSI_HDIG_EN_LBN 87
+#define	FRF_AZ_RX_ISCSI_HDIG_EN_WIDTH 1
+#define	FRF_AZ_RX_DESC_PREF_ACT_LBN 86
+#define	FRF_AZ_RX_DESC_PREF_ACT_WIDTH 1
+#define	FRF_AZ_RX_DC_HW_RPTR_LBN 80
+#define	FRF_AZ_RX_DC_HW_RPTR_WIDTH 6
+#define	FRF_AZ_RX_DESCQ_HW_RPTR_LBN 68
+#define	FRF_AZ_RX_DESCQ_HW_RPTR_WIDTH 12
+#define	FRF_AZ_RX_DESCQ_SW_WPTR_LBN 56
+#define	FRF_AZ_RX_DESCQ_SW_WPTR_WIDTH 12
+#define	FRF_AZ_RX_DESCQ_BUF_BASE_ID_LBN 36
+#define	FRF_AZ_RX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define	FRF_AZ_RX_DESCQ_EVQ_ID_LBN 24
+#define	FRF_AZ_RX_DESCQ_EVQ_ID_WIDTH 12
+#define	FRF_AZ_RX_DESCQ_OWNER_ID_LBN 10
+#define	FRF_AZ_RX_DESCQ_OWNER_ID_WIDTH 14
+#define	FRF_AZ_RX_DESCQ_LABEL_LBN 5
+#define	FRF_AZ_RX_DESCQ_LABEL_WIDTH 5
+#define	FRF_AZ_RX_DESCQ_SIZE_LBN 3
+#define	FRF_AZ_RX_DESCQ_SIZE_WIDTH 2
+#define	FFE_AZ_RX_DESCQ_SIZE_4K 3
+#define	FFE_AZ_RX_DESCQ_SIZE_2K 2
+#define	FFE_AZ_RX_DESCQ_SIZE_1K 1
+#define	FFE_AZ_RX_DESCQ_SIZE_512 0
+#define	FRF_AZ_RX_DESCQ_TYPE_LBN 2
+#define	FRF_AZ_RX_DESCQ_TYPE_WIDTH 1
+#define	FRF_AZ_RX_DESCQ_JUMBO_LBN 1
+#define	FRF_AZ_RX_DESCQ_JUMBO_WIDTH 1
+#define	FRF_AZ_RX_DESCQ_EN_LBN 0
+#define	FRF_AZ_RX_DESCQ_EN_WIDTH 1
+
+
+/*
+ * FR_AA_TX_DESC_PTR_TBL_KER(128bit):
+ * Transmit descriptor pointer
+ */
+#define	FR_AA_TX_DESC_PTR_TBL_KER_OFST 0x00011900
+/* falcona0=net_func_bar2 */
+#define	FR_AA_TX_DESC_PTR_TBL_KER_STEP 16
+#define	FR_AA_TX_DESC_PTR_TBL_KER_ROWS 8
+/*
+ * FR_AZ_TX_DESC_PTR_TBL(128bit):
+ * Transmit descriptor pointer
+ */
+#define	FR_AZ_TX_DESC_PTR_TBL_OFST 0x00f50000
+/* falconb0=net_func_bar2,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_TX_DESC_PTR_TBL_STEP 16
+#define	FR_AB_TX_DESC_PTR_TBL_ROWS 4096
+#define	FR_CZ_TX_DESC_PTR_TBL_ROWS 1024
+
+#define	FRF_CZ_TX_DPT_Q_MASK_WIDTH_LBN 94
+#define	FRF_CZ_TX_DPT_Q_MASK_WIDTH_WIDTH 2
+#define	FRF_CZ_TX_DPT_ETH_FILT_EN_LBN 93
+#define	FRF_CZ_TX_DPT_ETH_FILT_EN_WIDTH 1
+#define	FRF_CZ_TX_DPT_IP_FILT_EN_LBN 92
+#define	FRF_CZ_TX_DPT_IP_FILT_EN_WIDTH 1
+#define	FRF_BZ_TX_NON_IP_DROP_DIS_LBN 91
+#define	FRF_BZ_TX_NON_IP_DROP_DIS_WIDTH 1
+#define	FRF_BZ_TX_IP_CHKSM_DIS_LBN 90
+#define	FRF_BZ_TX_IP_CHKSM_DIS_WIDTH 1
+#define	FRF_BZ_TX_TCP_CHKSM_DIS_LBN 89
+#define	FRF_BZ_TX_TCP_CHKSM_DIS_WIDTH 1
+#define	FRF_AZ_TX_DESCQ_EN_LBN 88
+#define	FRF_AZ_TX_DESCQ_EN_WIDTH 1
+#define	FRF_AZ_TX_ISCSI_DDIG_EN_LBN 87
+#define	FRF_AZ_TX_ISCSI_DDIG_EN_WIDTH 1
+#define	FRF_AZ_TX_ISCSI_HDIG_EN_LBN 86
+#define	FRF_AZ_TX_ISCSI_HDIG_EN_WIDTH 1
+#define	FRF_AZ_TX_DC_HW_RPTR_LBN 80
+#define	FRF_AZ_TX_DC_HW_RPTR_WIDTH 6
+#define	FRF_AZ_TX_DESCQ_HW_RPTR_LBN 68
+#define	FRF_AZ_TX_DESCQ_HW_RPTR_WIDTH 12
+#define	FRF_AZ_TX_DESCQ_SW_WPTR_LBN 56
+#define	FRF_AZ_TX_DESCQ_SW_WPTR_WIDTH 12
+#define	FRF_AZ_TX_DESCQ_BUF_BASE_ID_LBN 36
+#define	FRF_AZ_TX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define	FRF_AZ_TX_DESCQ_EVQ_ID_LBN 24
+#define	FRF_AZ_TX_DESCQ_EVQ_ID_WIDTH 12
+#define	FRF_AZ_TX_DESCQ_OWNER_ID_LBN 10
+#define	FRF_AZ_TX_DESCQ_OWNER_ID_WIDTH 14
+#define	FRF_AZ_TX_DESCQ_LABEL_LBN 5
+#define	FRF_AZ_TX_DESCQ_LABEL_WIDTH 5
+#define	FRF_AZ_TX_DESCQ_SIZE_LBN 3
+#define	FRF_AZ_TX_DESCQ_SIZE_WIDTH 2
+#define	FFE_AZ_TX_DESCQ_SIZE_4K 3
+#define	FFE_AZ_TX_DESCQ_SIZE_2K 2
+#define	FFE_AZ_TX_DESCQ_SIZE_1K 1
+#define	FFE_AZ_TX_DESCQ_SIZE_512 0
+#define	FRF_AZ_TX_DESCQ_TYPE_LBN 1
+#define	FRF_AZ_TX_DESCQ_TYPE_WIDTH 2
+#define	FRF_AZ_TX_DESCQ_FLUSH_LBN 0
+#define	FRF_AZ_TX_DESCQ_FLUSH_WIDTH 1
+
+
+/*
+ * FR_AA_EVQ_PTR_TBL_KER(128bit):
+ * Event queue pointer table
+ */
+#define	FR_AA_EVQ_PTR_TBL_KER_OFST 0x00011a00
+/* falcona0=net_func_bar2 */
+#define	FR_AA_EVQ_PTR_TBL_KER_STEP 16
+#define	FR_AA_EVQ_PTR_TBL_KER_ROWS 4
+/*
+ * FR_AZ_EVQ_PTR_TBL(128bit):
+ * Event queue pointer table
+ */
+#define	FR_AZ_EVQ_PTR_TBL_OFST 0x00f60000
+/* sienaa0=net_func_bar2,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_EVQ_PTR_TBL_STEP 16
+#define	FR_CZ_EVQ_PTR_TBL_ROWS 1024
+#define	FR_AB_EVQ_PTR_TBL_ROWS 4096
+
+#define	FRF_BZ_EVQ_RPTR_IGN_LBN 40
+#define	FRF_BZ_EVQ_RPTR_IGN_WIDTH 1
+#define	FRF_AZ_EVQ_WKUP_OR_INT_EN_LBN 39
+#define	FRF_AZ_EVQ_WKUP_OR_INT_EN_WIDTH 1
+#define	FRF_AZ_EVQ_NXT_WPTR_LBN 24
+#define	FRF_AZ_EVQ_NXT_WPTR_WIDTH 15
+#define	FRF_AZ_EVQ_EN_LBN 23
+#define	FRF_AZ_EVQ_EN_WIDTH 1
+#define	FRF_AZ_EVQ_SIZE_LBN 20
+#define	FRF_AZ_EVQ_SIZE_WIDTH 3
+#define	FFE_AZ_EVQ_SIZE_32K 6
+#define	FFE_AZ_EVQ_SIZE_16K 5
+#define	FFE_AZ_EVQ_SIZE_8K 4
+#define	FFE_AZ_EVQ_SIZE_4K 3
+#define	FFE_AZ_EVQ_SIZE_2K 2
+#define	FFE_AZ_EVQ_SIZE_1K 1
+#define	FFE_AZ_EVQ_SIZE_512 0
+#define	FRF_AZ_EVQ_BUF_BASE_ID_LBN 0
+#define	FRF_AZ_EVQ_BUF_BASE_ID_WIDTH 20
+
+
+/*
+ * FR_AA_BUF_HALF_TBL_KER(64bit):
+ * Buffer table in half buffer table mode direct access by driver
+ */
+#define	FR_AA_BUF_HALF_TBL_KER_OFST 0x00018000
+/* falcona0=net_func_bar2 */
+#define	FR_AA_BUF_HALF_TBL_KER_STEP 8
+#define	FR_AA_BUF_HALF_TBL_KER_ROWS 4096
+/*
+ * FR_AZ_BUF_HALF_TBL(64bit):
+ * Buffer table in half buffer table mode direct access by driver
+ */
+#define	FR_AZ_BUF_HALF_TBL_OFST 0x00800000
+/* sienaa0=net_func_bar2,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_BUF_HALF_TBL_STEP 8
+#define	FR_CZ_BUF_HALF_TBL_ROWS 147456
+#define	FR_AB_BUF_HALF_TBL_ROWS 524288
+
+#define	FRF_AZ_BUF_ADR_HBUF_ODD_LBN 44
+#define	FRF_AZ_BUF_ADR_HBUF_ODD_WIDTH 20
+#define	FRF_AZ_BUF_OWNER_ID_HBUF_ODD_LBN 32
+#define	FRF_AZ_BUF_OWNER_ID_HBUF_ODD_WIDTH 12
+#define	FRF_AZ_BUF_ADR_HBUF_EVEN_LBN 12
+#define	FRF_AZ_BUF_ADR_HBUF_EVEN_WIDTH 20
+#define	FRF_AZ_BUF_OWNER_ID_HBUF_EVEN_LBN 0
+#define	FRF_AZ_BUF_OWNER_ID_HBUF_EVEN_WIDTH 12
+
+
+/*
+ * FR_AA_BUF_FULL_TBL_KER(64bit):
+ * Buffer table in full buffer table mode direct access by driver
+ */
+#define	FR_AA_BUF_FULL_TBL_KER_OFST 0x00018000
+/* falcona0=net_func_bar2 */
+#define	FR_AA_BUF_FULL_TBL_KER_STEP 8
+#define	FR_AA_BUF_FULL_TBL_KER_ROWS 4096
+/*
+ * FR_AZ_BUF_FULL_TBL(64bit):
+ * Buffer table in full buffer table mode direct access by driver
+ */
+#define	FR_AZ_BUF_FULL_TBL_OFST 0x00800000
+/* sienaa0=net_func_bar2,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_BUF_FULL_TBL_STEP 8
+
+#define	FR_CZ_BUF_FULL_TBL_ROWS 147456
+#define	FR_AB_BUF_FULL_TBL_ROWS 917504
+
+#define	FRF_AZ_BUF_FULL_UNUSED_LBN 51
+#define	FRF_AZ_BUF_FULL_UNUSED_WIDTH 13
+#define	FRF_AZ_IP_DAT_BUF_SIZE_LBN 50
+#define	FRF_AZ_IP_DAT_BUF_SIZE_WIDTH 1
+#define	FRF_AZ_BUF_ADR_REGION_LBN 48
+#define	FRF_AZ_BUF_ADR_REGION_WIDTH 2
+#define	FFE_AZ_BUF_ADR_REGN3 3
+#define	FFE_AZ_BUF_ADR_REGN2 2
+#define	FFE_AZ_BUF_ADR_REGN1 1
+#define	FFE_AZ_BUF_ADR_REGN0 0
+#define	FRF_AZ_BUF_ADR_FBUF_LBN 14
+#define	FRF_AZ_BUF_ADR_FBUF_WIDTH 34
+#define	FRF_AZ_BUF_ADR_FBUF_DW0_LBN 14
+#define	FRF_AZ_BUF_ADR_FBUF_DW0_WIDTH 32
+#define	FRF_AZ_BUF_ADR_FBUF_DW1_LBN 46
+#define	FRF_AZ_BUF_ADR_FBUF_DW1_WIDTH 2
+#define	FRF_AZ_BUF_OWNER_ID_FBUF_LBN 0
+#define	FRF_AZ_BUF_OWNER_ID_FBUF_WIDTH 14
+
+
+/*
+ * FR_AZ_RX_FILTER_TBL0(128bit):
+ * TCP/IPv4 Receive filter table
+ */
+#define	FR_AZ_RX_FILTER_TBL0_OFST 0x00f00000
+/* falconb0,sienaa0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_RX_FILTER_TBL0_STEP 32
+#define	FR_AZ_RX_FILTER_TBL0_ROWS 8192
+/*
+ * FR_AB_RX_FILTER_TBL1(128bit):
+ * TCP/IPv4 Receive filter table
+ */
+#define	FR_AB_RX_FILTER_TBL1_OFST 0x00f00010
+/* falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AB_RX_FILTER_TBL1_STEP 32
+#define	FR_AB_RX_FILTER_TBL1_ROWS 8192
+
+#define	FRF_BZ_RSS_EN_LBN 110
+#define	FRF_BZ_RSS_EN_WIDTH 1
+#define	FRF_BZ_SCATTER_EN_LBN 109
+#define	FRF_BZ_SCATTER_EN_WIDTH 1
+#define	FRF_AZ_TCP_UDP_LBN 108
+#define	FRF_AZ_TCP_UDP_WIDTH 1
+#define	FRF_AZ_RXQ_ID_LBN 96
+#define	FRF_AZ_RXQ_ID_WIDTH 12
+#define	FRF_AZ_DEST_IP_LBN 64
+#define	FRF_AZ_DEST_IP_WIDTH 32
+#define	FRF_AZ_DEST_PORT_TCP_LBN 48
+#define	FRF_AZ_DEST_PORT_TCP_WIDTH 16
+#define	FRF_AZ_SRC_IP_LBN 16
+#define	FRF_AZ_SRC_IP_WIDTH 32
+#define	FRF_AZ_SRC_TCP_DEST_UDP_LBN 0
+#define	FRF_AZ_SRC_TCP_DEST_UDP_WIDTH 16
+
+
+/*
+ * FR_CZ_RX_MAC_FILTER_TBL0(128bit):
+ * Receive Ethernet filter table
+ */
+#define	FR_CZ_RX_MAC_FILTER_TBL0_OFST 0x00f00010
+/* sienaa0=net_func_bar2 */
+#define	FR_CZ_RX_MAC_FILTER_TBL0_STEP 32
+#define	FR_CZ_RX_MAC_FILTER_TBL0_ROWS 512
+
+#define	FRF_CZ_RMFT_RSS_EN_LBN 75
+#define	FRF_CZ_RMFT_RSS_EN_WIDTH 1
+#define	FRF_CZ_RMFT_SCATTER_EN_LBN 74
+#define	FRF_CZ_RMFT_SCATTER_EN_WIDTH 1
+#define	FRF_CZ_RMFT_IP_OVERRIDE_LBN 73
+#define	FRF_CZ_RMFT_IP_OVERRIDE_WIDTH 1
+#define	FRF_CZ_RMFT_RXQ_ID_LBN 61
+#define	FRF_CZ_RMFT_RXQ_ID_WIDTH 12
+#define	FRF_CZ_RMFT_WILDCARD_MATCH_LBN 60
+#define	FRF_CZ_RMFT_WILDCARD_MATCH_WIDTH 1
+#define	FRF_CZ_RMFT_DEST_MAC_LBN 12
+#define	FRF_CZ_RMFT_DEST_MAC_WIDTH 48
+#define	FRF_CZ_RMFT_DEST_MAC_DW0_LBN 12
+#define	FRF_CZ_RMFT_DEST_MAC_DW0_WIDTH 32
+#define	FRF_CZ_RMFT_DEST_MAC_DW1_LBN 44
+#define	FRF_CZ_RMFT_DEST_MAC_DW1_WIDTH 16
+#define	FRF_CZ_RMFT_VLAN_ID_LBN 0
+#define	FRF_CZ_RMFT_VLAN_ID_WIDTH 12
+
+
+/*
+ * FR_AZ_TIMER_TBL(128bit):
+ * Timer table
+ */
+#define	FR_AZ_TIMER_TBL_OFST 0x00f70000
+/* sienaa0=net_func_bar2,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_TIMER_TBL_STEP 16
+#define	FR_CZ_TIMER_TBL_ROWS 1024
+#define	FR_AB_TIMER_TBL_ROWS 4096
+
+#define	FRF_CZ_TIMER_Q_EN_LBN 33
+#define	FRF_CZ_TIMER_Q_EN_WIDTH 1
+#define	FRF_CZ_INT_ARMD_LBN 32
+#define	FRF_CZ_INT_ARMD_WIDTH 1
+#define	FRF_CZ_INT_PEND_LBN 31
+#define	FRF_CZ_INT_PEND_WIDTH 1
+#define	FRF_CZ_HOST_NOTIFY_MODE_LBN 30
+#define	FRF_CZ_HOST_NOTIFY_MODE_WIDTH 1
+#define	FRF_CZ_RELOAD_TIMER_VAL_LBN 16
+#define	FRF_CZ_RELOAD_TIMER_VAL_WIDTH 14
+#define	FRF_CZ_TIMER_MODE_LBN 14
+#define	FRF_CZ_TIMER_MODE_WIDTH 2
+#define	FFE_CZ_TIMER_MODE_INT_HLDOFF 3
+#define	FFE_CZ_TIMER_MODE_TRIG_START 2
+#define	FFE_CZ_TIMER_MODE_IMMED_START 1
+#define	FFE_CZ_TIMER_MODE_DIS 0
+#define	FRF_AB_TIMER_MODE_LBN 12
+#define	FRF_AB_TIMER_MODE_WIDTH 2
+#define	FFE_AB_TIMER_MODE_INT_HLDOFF 2
+#define	FFE_AB_TIMER_MODE_TRIG_START 2
+#define	FFE_AB_TIMER_MODE_IMMED_START 1
+#define	FFE_AB_TIMER_MODE_DIS 0
+#define	FRF_CZ_TIMER_VAL_LBN 0
+#define	FRF_CZ_TIMER_VAL_WIDTH 14
+#define	FRF_AB_TIMER_VAL_LBN 0
+#define	FRF_AB_TIMER_VAL_WIDTH 12
+
+
+/*
+ * FR_BZ_TX_PACE_TBL(128bit):
+ * Transmit pacing table
+ */
+#define	FR_BZ_TX_PACE_TBL_OFST 0x00f80000
+/* sienaa0=net_func_bar2,falconb0=net_func_bar2 */
+#define	FR_AZ_TX_PACE_TBL_STEP 16
+#define	FR_CZ_TX_PACE_TBL_ROWS 1024
+#define	FR_BB_TX_PACE_TBL_ROWS 4096
+/*
+ * FR_AA_TX_PACE_TBL(128bit):
+ * Transmit pacing table
+ */
+#define	FR_AA_TX_PACE_TBL_OFST 0x00f80040
+/* falcona0=char_func_bar0 */
+/* FR_AZ_TX_PACE_TBL_STEP 16 */
+#define	FR_AA_TX_PACE_TBL_ROWS 4092
+
+#define	FRF_AZ_TX_PACE_LBN 0
+#define	FRF_AZ_TX_PACE_WIDTH 5
+
+
+/*
+ * FR_BZ_RX_INDIRECTION_TBL(7bit):
+ * RX Indirection Table
+ */
+#define	FR_BZ_RX_INDIRECTION_TBL_OFST 0x00fb0000
+/* falconb0,sienaa0=net_func_bar2 */
+#define	FR_BZ_RX_INDIRECTION_TBL_STEP 16
+#define	FR_BZ_RX_INDIRECTION_TBL_ROWS 128
+
+#define	FRF_BZ_IT_QUEUE_LBN 0
+#define	FRF_BZ_IT_QUEUE_WIDTH 6
+
+
+/*
+ * FR_CZ_TX_FILTER_TBL0(128bit):
+ * TCP/IPv4 Transmit filter table
+ */
+#define	FR_CZ_TX_FILTER_TBL0_OFST 0x00fc0000
+/* sienaa0=net_func_bar2 */
+#define	FR_CZ_TX_FILTER_TBL0_STEP 16
+#define	FR_CZ_TX_FILTER_TBL0_ROWS 8192
+
+#define	FRF_CZ_TIFT_TCP_UDP_LBN 108
+#define	FRF_CZ_TIFT_TCP_UDP_WIDTH 1
+#define	FRF_CZ_TIFT_TXQ_ID_LBN 96
+#define	FRF_CZ_TIFT_TXQ_ID_WIDTH 12
+#define	FRF_CZ_TIFT_DEST_IP_LBN 64
+#define	FRF_CZ_TIFT_DEST_IP_WIDTH 32
+#define	FRF_CZ_TIFT_DEST_PORT_TCP_LBN 48
+#define	FRF_CZ_TIFT_DEST_PORT_TCP_WIDTH 16
+#define	FRF_CZ_TIFT_SRC_IP_LBN 16
+#define	FRF_CZ_TIFT_SRC_IP_WIDTH 32
+#define	FRF_CZ_TIFT_SRC_TCP_DEST_UDP_LBN 0
+#define	FRF_CZ_TIFT_SRC_TCP_DEST_UDP_WIDTH 16
+
+
+/*
+ * FR_CZ_TX_MAC_FILTER_TBL0(128bit):
+ * Transmit Ethernet filter table
+ */
+#define	FR_CZ_TX_MAC_FILTER_TBL0_OFST 0x00fe0000
+/* sienaa0=net_func_bar2 */
+#define	FR_CZ_TX_MAC_FILTER_TBL0_STEP 16
+#define	FR_CZ_TX_MAC_FILTER_TBL0_ROWS 512
+
+#define	FRF_CZ_TMFT_TXQ_ID_LBN 61
+#define	FRF_CZ_TMFT_TXQ_ID_WIDTH 12
+#define	FRF_CZ_TMFT_WILDCARD_MATCH_LBN 60
+#define	FRF_CZ_TMFT_WILDCARD_MATCH_WIDTH 1
+#define	FRF_CZ_TMFT_SRC_MAC_LBN 12
+#define	FRF_CZ_TMFT_SRC_MAC_WIDTH 48
+#define	FRF_CZ_TMFT_SRC_MAC_DW0_LBN 12
+#define	FRF_CZ_TMFT_SRC_MAC_DW0_WIDTH 32
+#define	FRF_CZ_TMFT_SRC_MAC_DW1_LBN 44
+#define	FRF_CZ_TMFT_SRC_MAC_DW1_WIDTH 16
+#define	FRF_CZ_TMFT_VLAN_ID_LBN 0
+#define	FRF_CZ_TMFT_VLAN_ID_WIDTH 12
+
+
+/*
+ * FR_CZ_MC_TREG_SMEM(32bit):
+ * MC Shared Memory
+ */
+#define	FR_CZ_MC_TREG_SMEM_OFST 0x00ff0000
+/* sienaa0=net_func_bar2 */
+#define	FR_CZ_MC_TREG_SMEM_STEP 4
+#define	FR_CZ_MC_TREG_SMEM_ROWS 512
+
+#define	FRF_CZ_MC_TREG_SMEM_ROW_LBN 0
+#define	FRF_CZ_MC_TREG_SMEM_ROW_WIDTH 32
+
+
+/*
+ * FR_BB_MSIX_VECTOR_TABLE(128bit):
+ * MSIX Vector Table
+ */
+#define	FR_BB_MSIX_VECTOR_TABLE_OFST 0x00ff0000
+/* falconb0=net_func_bar2 */
+#define	FR_BZ_MSIX_VECTOR_TABLE_STEP 16
+#define	FR_BB_MSIX_VECTOR_TABLE_ROWS 64
+/*
+ * FR_CZ_MSIX_VECTOR_TABLE(128bit):
+ * MSIX Vector Table
+ */
+#define	FR_CZ_MSIX_VECTOR_TABLE_OFST 0x00000000
+/* sienaa0=pci_f0_bar4 */
+/* FR_BZ_MSIX_VECTOR_TABLE_STEP 16 */
+#define	FR_CZ_MSIX_VECTOR_TABLE_ROWS 1024
+
+#define	FRF_BZ_MSIX_VECTOR_RESERVED_LBN 97
+#define	FRF_BZ_MSIX_VECTOR_RESERVED_WIDTH 31
+#define	FRF_BZ_MSIX_VECTOR_MASK_LBN 96
+#define	FRF_BZ_MSIX_VECTOR_MASK_WIDTH 1
+#define	FRF_BZ_MSIX_MESSAGE_DATA_LBN 64
+#define	FRF_BZ_MSIX_MESSAGE_DATA_WIDTH 32
+#define	FRF_BZ_MSIX_MESSAGE_ADDRESS_HI_LBN 32
+#define	FRF_BZ_MSIX_MESSAGE_ADDRESS_HI_WIDTH 32
+#define	FRF_BZ_MSIX_MESSAGE_ADDRESS_LO_LBN 0
+#define	FRF_BZ_MSIX_MESSAGE_ADDRESS_LO_WIDTH 32
+
+
+/*
+ * FR_BB_MSIX_PBA_TABLE(32bit):
+ * MSIX Pending Bit Array
+ */
+#define	FR_BB_MSIX_PBA_TABLE_OFST 0x00ff2000
+/* falconb0=net_func_bar2 */
+#define	FR_BZ_MSIX_PBA_TABLE_STEP 4
+#define	FR_BB_MSIX_PBA_TABLE_ROWS 2
+/*
+ * FR_CZ_MSIX_PBA_TABLE(32bit):
+ * MSIX Pending Bit Array
+ */
+#define	FR_CZ_MSIX_PBA_TABLE_OFST 0x00008000
+/* sienaa0=pci_f0_bar4 */
+/* FR_BZ_MSIX_PBA_TABLE_STEP 4 */
+#define	FR_CZ_MSIX_PBA_TABLE_ROWS 32
+
+#define	FRF_BZ_MSIX_PBA_PEND_DWORD_LBN 0
+#define	FRF_BZ_MSIX_PBA_PEND_DWORD_WIDTH 32
+
+
+/*
+ * FR_AZ_SRM_DBG_REG(64bit):
+ * SRAM debug access
+ */
+#define	FR_AZ_SRM_DBG_REG_OFST 0x03000000
+/* sienaa0=net_func_bar2,falconb0=net_func_bar2,falcona0=char_func_bar0 */
+#define	FR_AZ_SRM_DBG_REG_STEP 8
+
+#define	FR_CZ_SRM_DBG_REG_ROWS 262144
+#define	FR_AB_SRM_DBG_REG_ROWS 2097152
+
+#define	FRF_AZ_SRM_DBG_LBN 0
+#define	FRF_AZ_SRM_DBG_WIDTH 64
+#define	FRF_AZ_SRM_DBG_DW0_LBN 0
+#define	FRF_AZ_SRM_DBG_DW0_WIDTH 32
+#define	FRF_AZ_SRM_DBG_DW1_LBN 32
+#define	FRF_AZ_SRM_DBG_DW1_WIDTH 32
+
+
+/*
+ * FR_AA_INT_ACK_CHAR(32bit):
+ * CHAR interrupt acknowledge register
+ */
+#define	FR_AA_INT_ACK_CHAR_OFST 0x00000060
+/* falcona0=char_func_bar0 */
+
+#define	FRF_AA_INT_ACK_CHAR_FIELD_LBN 0
+#define	FRF_AA_INT_ACK_CHAR_FIELD_WIDTH 32
+
+
+/* FS_DRIVER_EV */
+#define	FSF_AZ_DRIVER_EV_SUBCODE_LBN 56
+#define	FSF_AZ_DRIVER_EV_SUBCODE_WIDTH 4
+#define	FSE_AZ_TX_DSC_ERROR_EV 15
+#define	FSE_AZ_RX_DSC_ERROR_EV 14
+#define	FSE_AZ_RX_RECOVER_EV 11
+#define	FSE_AZ_TIMER_EV 10
+#define	FSE_AZ_TX_PKT_NON_TCP_UDP 9
+#define	FSE_AZ_WAKE_UP_EV 6
+#define	FSE_AZ_SRM_UPD_DONE_EV 5
+#define	FSE_AZ_EVQ_NOT_EN_EV 3
+#define	FSE_AZ_EVQ_INIT_DONE_EV 2
+#define	FSE_AZ_RX_DESCQ_FLS_DONE_EV 1
+#define	FSE_AZ_TX_DESCQ_FLS_DONE_EV 0
+#define	FSF_AZ_DRIVER_EV_SUBDATA_LBN 0
+#define	FSF_AZ_DRIVER_EV_SUBDATA_WIDTH 14
+
+
+/* FS_EVENT_ENTRY */
+#define	FSF_AZ_EV_CODE_LBN 60
+#define	FSF_AZ_EV_CODE_WIDTH 4
+#define	FSE_AZ_EV_CODE_USER_EV 8
+#define	FSE_AZ_EV_CODE_DRV_GEN_EV 7
+#define	FSE_AZ_EV_CODE_GLOBAL_EV 6
+#define	FSE_AZ_EV_CODE_DRIVER_EV 5
+#define	FSE_AZ_EV_CODE_TX_EV 2
+#define	FSE_AZ_EV_CODE_RX_EV 0
+#define	FSF_AZ_EV_DATA_LBN 0
+#define	FSF_AZ_EV_DATA_WIDTH 60
+#define	FSF_AZ_EV_DATA_DW0_LBN 0
+#define	FSF_AZ_EV_DATA_DW0_WIDTH 32
+#define	FSF_AZ_EV_DATA_DW1_LBN 32
+#define	FSF_AZ_EV_DATA_DW1_WIDTH 28
+
+
+/* FS_GLOBAL_EV */
+#define	FSF_AA_GLB_EV_RX_RECOVERY_LBN 12
+#define	FSF_AA_GLB_EV_RX_RECOVERY_WIDTH 1
+#define	FSF_BZ_GLB_EV_XG_MNT_INTR_LBN 11
+#define	FSF_BZ_GLB_EV_XG_MNT_INTR_WIDTH 1
+#define	FSF_AZ_GLB_EV_XFP_PHY0_INTR_LBN 10
+#define	FSF_AZ_GLB_EV_XFP_PHY0_INTR_WIDTH 1
+#define	FSF_AZ_GLB_EV_XG_PHY0_INTR_LBN 9
+#define	FSF_AZ_GLB_EV_XG_PHY0_INTR_WIDTH 1
+#define	FSF_AZ_GLB_EV_G_PHY0_INTR_LBN 7
+#define	FSF_AZ_GLB_EV_G_PHY0_INTR_WIDTH 1
+
+
+/* FS_RX_EV */
+#define	FSF_CZ_RX_EV_PKT_NOT_PARSED_LBN 58
+#define	FSF_CZ_RX_EV_PKT_NOT_PARSED_WIDTH 1
+#define	FSF_CZ_RX_EV_IPV6_PKT_LBN 57
+#define	FSF_CZ_RX_EV_IPV6_PKT_WIDTH 1
+#define	FSF_AZ_RX_EV_PKT_OK_LBN 56
+#define	FSF_AZ_RX_EV_PKT_OK_WIDTH 1
+#define	FSF_AZ_RX_EV_PAUSE_FRM_ERR_LBN 55
+#define	FSF_AZ_RX_EV_PAUSE_FRM_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_BUF_OWNER_ID_ERR_LBN 54
+#define	FSF_AZ_RX_EV_BUF_OWNER_ID_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_IP_FRAG_ERR_LBN 53
+#define	FSF_AZ_RX_EV_IP_FRAG_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR_LBN 52
+#define	FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51
+#define	FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_ETH_CRC_ERR_LBN 50
+#define	FSF_AZ_RX_EV_ETH_CRC_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_FRM_TRUNC_LBN 49
+#define	FSF_AZ_RX_EV_FRM_TRUNC_WIDTH 1
+#define	FSF_AZ_RX_EV_TOBE_DISC_LBN 47
+#define	FSF_AZ_RX_EV_TOBE_DISC_WIDTH 1
+#define	FSF_AZ_RX_EV_PKT_TYPE_LBN 44
+#define	FSF_AZ_RX_EV_PKT_TYPE_WIDTH 3
+#define	FSE_AZ_RX_EV_PKT_TYPE_VLAN_JUMBO 5
+#define	FSE_AZ_RX_EV_PKT_TYPE_VLAN_LLC 4
+#define	FSE_AZ_RX_EV_PKT_TYPE_VLAN 3
+#define	FSE_AZ_RX_EV_PKT_TYPE_JUMBO 2
+#define	FSE_AZ_RX_EV_PKT_TYPE_LLC 1
+#define	FSE_AZ_RX_EV_PKT_TYPE_ETH 0
+#define	FSF_AZ_RX_EV_HDR_TYPE_LBN 42
+#define	FSF_AZ_RX_EV_HDR_TYPE_WIDTH 2
+#define	FSE_AZ_RX_EV_HDR_TYPE_OTHER 3
+#define	FSE_AZ_RX_EV_HDR_TYPE_IPV4_OTHER 2
+#define	FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_OTHER 2
+#define	FSE_AZ_RX_EV_HDR_TYPE_IPV4_UDP 1
+#define	FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_UDP 1
+#define	FSE_AZ_RX_EV_HDR_TYPE_IPV4_TCP 0
+#define	FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_TCP 0
+#define	FSF_AZ_RX_EV_DESC_Q_EMPTY_LBN 41
+#define	FSF_AZ_RX_EV_DESC_Q_EMPTY_WIDTH 1
+#define	FSF_AZ_RX_EV_MCAST_HASH_MATCH_LBN 40
+#define	FSF_AZ_RX_EV_MCAST_HASH_MATCH_WIDTH 1
+#define	FSF_AZ_RX_EV_MCAST_PKT_LBN 39
+#define	FSF_AZ_RX_EV_MCAST_PKT_WIDTH 1
+#define	FSF_AA_RX_EV_RECOVERY_FLAG_LBN 37
+#define	FSF_AA_RX_EV_RECOVERY_FLAG_WIDTH 1
+#define	FSF_AZ_RX_EV_Q_LABEL_LBN 32
+#define	FSF_AZ_RX_EV_Q_LABEL_WIDTH 5
+#define	FSF_AZ_RX_EV_JUMBO_CONT_LBN 31
+#define	FSF_AZ_RX_EV_JUMBO_CONT_WIDTH 1
+#define	FSF_AZ_RX_EV_PORT_LBN 30
+#define	FSF_AZ_RX_EV_PORT_WIDTH 1
+#define	FSF_AZ_RX_EV_BYTE_CNT_LBN 16
+#define	FSF_AZ_RX_EV_BYTE_CNT_WIDTH 14
+#define	FSF_AZ_RX_EV_SOP_LBN 15
+#define	FSF_AZ_RX_EV_SOP_WIDTH 1
+#define	FSF_AZ_RX_EV_ISCSI_PKT_OK_LBN 14
+#define	FSF_AZ_RX_EV_ISCSI_PKT_OK_WIDTH 1
+#define	FSF_AZ_RX_EV_ISCSI_DDIG_ERR_LBN 13
+#define	FSF_AZ_RX_EV_ISCSI_DDIG_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_ISCSI_HDIG_ERR_LBN 12
+#define	FSF_AZ_RX_EV_ISCSI_HDIG_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_DESC_PTR_LBN 0
+#define	FSF_AZ_RX_EV_DESC_PTR_WIDTH 12
+
+
+/* FS_RX_KER_DESC */
+#define	FSF_AZ_RX_KER_BUF_SIZE_LBN 48
+#define	FSF_AZ_RX_KER_BUF_SIZE_WIDTH 14
+#define	FSF_AZ_RX_KER_BUF_REGION_LBN 46
+#define	FSF_AZ_RX_KER_BUF_REGION_WIDTH 2
+#define	FSF_AZ_RX_KER_BUF_ADDR_LBN 0
+#define	FSF_AZ_RX_KER_BUF_ADDR_WIDTH 46
+#define	FSF_AZ_RX_KER_BUF_ADDR_DW0_LBN 0
+#define	FSF_AZ_RX_KER_BUF_ADDR_DW0_WIDTH 32
+#define	FSF_AZ_RX_KER_BUF_ADDR_DW1_LBN 32
+#define	FSF_AZ_RX_KER_BUF_ADDR_DW1_WIDTH 14
+
+
+/* FS_RX_USER_DESC */
+#define	FSF_AZ_RX_USER_2BYTE_OFFSET_LBN 20
+#define	FSF_AZ_RX_USER_2BYTE_OFFSET_WIDTH 12
+#define	FSF_AZ_RX_USER_BUF_ID_LBN 0
+#define	FSF_AZ_RX_USER_BUF_ID_WIDTH 20
+
+
+/* FS_TX_EV */
+#define	FSF_AZ_TX_EV_PKT_ERR_LBN 38
+#define	FSF_AZ_TX_EV_PKT_ERR_WIDTH 1
+#define	FSF_AZ_TX_EV_PKT_TOO_BIG_LBN 37
+#define	FSF_AZ_TX_EV_PKT_TOO_BIG_WIDTH 1
+#define	FSF_AZ_TX_EV_Q_LABEL_LBN 32
+#define	FSF_AZ_TX_EV_Q_LABEL_WIDTH 5
+#define	FSF_AZ_TX_EV_PORT_LBN 16
+#define	FSF_AZ_TX_EV_PORT_WIDTH 1
+#define	FSF_AZ_TX_EV_WQ_FF_FULL_LBN 15
+#define	FSF_AZ_TX_EV_WQ_FF_FULL_WIDTH 1
+#define	FSF_AZ_TX_EV_BUF_OWNER_ID_ERR_LBN 14
+#define	FSF_AZ_TX_EV_BUF_OWNER_ID_ERR_WIDTH 1
+#define	FSF_AZ_TX_EV_COMP_LBN 12
+#define	FSF_AZ_TX_EV_COMP_WIDTH 1
+#define	FSF_AZ_TX_EV_DESC_PTR_LBN 0
+#define	FSF_AZ_TX_EV_DESC_PTR_WIDTH 12
+
+
+/* FS_TX_KER_DESC */
+#define	FSF_AZ_TX_KER_CONT_LBN 62
+#define	FSF_AZ_TX_KER_CONT_WIDTH 1
+#define	FSF_AZ_TX_KER_BYTE_COUNT_LBN 48
+#define	FSF_AZ_TX_KER_BYTE_COUNT_WIDTH 14
+#define	FSF_AZ_TX_KER_BUF_REGION_LBN 46
+#define	FSF_AZ_TX_KER_BUF_REGION_WIDTH 2
+#define	FSF_AZ_TX_KER_BUF_ADDR_LBN 0
+#define	FSF_AZ_TX_KER_BUF_ADDR_WIDTH 46
+#define	FSF_AZ_TX_KER_BUF_ADDR_DW0_LBN 0
+#define	FSF_AZ_TX_KER_BUF_ADDR_DW0_WIDTH 32
+#define	FSF_AZ_TX_KER_BUF_ADDR_DW1_LBN 32
+#define	FSF_AZ_TX_KER_BUF_ADDR_DW1_WIDTH 14
+
+
+/* FS_TX_USER_DESC */
+#define	FSF_AZ_TX_USER_SW_EV_EN_LBN 48
+#define	FSF_AZ_TX_USER_SW_EV_EN_WIDTH 1
+#define	FSF_AZ_TX_USER_CONT_LBN 46
+#define	FSF_AZ_TX_USER_CONT_WIDTH 1
+#define	FSF_AZ_TX_USER_BYTE_CNT_LBN 33
+#define	FSF_AZ_TX_USER_BYTE_CNT_WIDTH 13
+#define	FSF_AZ_TX_USER_BUF_ID_LBN 13
+#define	FSF_AZ_TX_USER_BUF_ID_WIDTH 20
+#define	FSF_AZ_TX_USER_BYTE_OFS_LBN 0
+#define	FSF_AZ_TX_USER_BYTE_OFS_WIDTH 13
+
+
+/* FS_USER_EV */
+#define	FSF_CZ_USER_QID_LBN 32
+#define	FSF_CZ_USER_QID_WIDTH 10
+#define	FSF_CZ_USER_EV_REG_VALUE_LBN 0
+#define	FSF_CZ_USER_EV_REG_VALUE_WIDTH 32
+
+
+/* FS_NET_IVEC */
+#define	FSF_AZ_NET_IVEC_FATAL_INT_LBN 64
+#define	FSF_AZ_NET_IVEC_FATAL_INT_WIDTH 1
+#define	FSF_AZ_NET_IVEC_INT_Q_LBN 40
+#define	FSF_AZ_NET_IVEC_INT_Q_WIDTH 4
+#define	FSF_AZ_NET_IVEC_INT_FLAG_LBN 32
+#define	FSF_AZ_NET_IVEC_INT_FLAG_WIDTH 1
+#define	FSF_AZ_NET_IVEC_EVQ_FIFO_HF_LBN 1
+#define	FSF_AZ_NET_IVEC_EVQ_FIFO_HF_WIDTH 1
+#define	FSF_AZ_NET_IVEC_EVQ_FIFO_AF_LBN 0
+#define	FSF_AZ_NET_IVEC_EVQ_FIFO_AF_WIDTH 1
+
+
+/* DRIVER_EV */
+/* Sub-fields of an RX flush completion event */
+#define	FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12
+#define	FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_WIDTH 1
+#define	FSF_AZ_DRIVER_EV_RX_DESCQ_ID_LBN 0
+#define	FSF_AZ_DRIVER_EV_RX_DESCQ_ID_WIDTH 12
+
+
+
+/**************************************************************************
+ *
+ * Falcon non-volatile configuration
+ *
+ **************************************************************************
+ */
+
+
+#define FR_AZ_TX_PACE_TBL_OFST FR_BZ_TX_PACE_TBL_OFST
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+
+
+
+#endif /* _SYS_EFX_REGS_H */
--- /dev/null	2013-08-22 18:57:28.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_regs_mcdi.h	2013-08-22 18:57:28.903726381 -0400
@@ -0,0 +1,3054 @@
+/*-
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*! \cidoxg_firmware_mc_cmd */
+
+#ifndef _SIENA_MC_DRIVER_PCOL_H
+#define	_SIENA_MC_DRIVER_PCOL_H
+
+
+/* Values to be written into FMCR_CZ_RESET_STATE_REG to control boot. */
+/* Power-on reset state */
+#define MC_FW_STATE_POR (1)
+/* If this is set in MC_RESET_STATE_REG then it should be
+ * possible to jump into IMEM without loading code from flash. */
+#define MC_FW_WARM_BOOT_OK (2)
+/* The MC main image has started to boot. */
+#define MC_FW_STATE_BOOTING (4)
+/* The Scheduler has started. */
+#define MC_FW_STATE_SCHED (8)
+
+/* Siena MC shared memmory offsets */
+/* The 'doorbell' addresses are hard-wired to alert the MC when written */
+#define	MC_SMEM_P0_DOORBELL_OFST	0x000
+#define	MC_SMEM_P1_DOORBELL_OFST	0x004
+/* The rest of these are firmware-defined */
+#define	MC_SMEM_P0_PDU_OFST		0x008
+#define	MC_SMEM_P1_PDU_OFST		0x108
+#define	MC_SMEM_PDU_LEN			0x100
+#define	MC_SMEM_P0_PTP_TIME_OFST	0x7f0
+#define	MC_SMEM_P0_STATUS_OFST		0x7f8
+#define	MC_SMEM_P1_STATUS_OFST		0x7fc
+
+/* Values to be written to the per-port status dword in shared
+ * memory on reboot and assert */
+#define MC_STATUS_DWORD_REBOOT (0xb007b007)
+#define MC_STATUS_DWORD_ASSERT (0xdeaddead)
+
+/* The current version of the MCDI protocol.
+ *
+ * Note that the ROM burnt into the card only talks V0, so at the very
+ * least every driver must support version 0 and MCDI_PCOL_VERSION
+ */
+#ifdef WITH_MCDI_V2
+#define MCDI_PCOL_VERSION 2
+#else
+#define MCDI_PCOL_VERSION 1
+#endif
+
+/* Unused commands: 0x23, 0x27, 0x30, 0x31 */
+
+/**
+ * MCDI version 1
+ *
+ * Each MCDI request starts with an MCDI_HEADER, which is a 32byte
+ * structure, filled in by the client.
+ *
+ *       0       7  8     16    20     22  23  24    31
+ *      | CODE | R | LEN | SEQ | Rsvd | E | R | XFLAGS |
+ *               |                      |   |
+ *               |                      |   \--- Response
+ *               |                      \------- Error
+ *               \------------------------------ Resync (always set)
+ *
+ * The client writes it's request into MC shared memory, and rings the
+ * doorbell. Each request is completed by either by the MC writting
+ * back into shared memory, or by writting out an event.
+ *
+ * All MCDI commands support completion by shared memory response. Each
+ * request may also contain additional data (accounted for by HEADER.LEN),
+ * and some response's may also contain additional data (again, accounted
+ * for by HEADER.LEN).
+ *
+ * Some MCDI commands support completion by event, in which any associated
+ * response data is included in the event.
+ *
+ * The protocol requires one response to be delivered for every request, a
+ * request should not be sent unless the response for the previous request
+ * has been received (either by polling shared memory, or by receiving
+ * an event).
+ */
+
+/** Request/Response structure */
+#define MCDI_HEADER_OFST 0
+#define MCDI_HEADER_CODE_LBN 0
+#define MCDI_HEADER_CODE_WIDTH 7
+#define MCDI_HEADER_RESYNC_LBN 7
+#define MCDI_HEADER_RESYNC_WIDTH 1
+#define MCDI_HEADER_DATALEN_LBN 8
+#define MCDI_HEADER_DATALEN_WIDTH 8
+#define MCDI_HEADER_SEQ_LBN 16
+#define MCDI_HEADER_RSVD_LBN 20
+#define MCDI_HEADER_RSVD_WIDTH 2
+#define MCDI_HEADER_SEQ_WIDTH 4
+#define MCDI_HEADER_ERROR_LBN 22
+#define MCDI_HEADER_ERROR_WIDTH 1
+#define MCDI_HEADER_RESPONSE_LBN 23
+#define MCDI_HEADER_RESPONSE_WIDTH 1
+#define MCDI_HEADER_XFLAGS_LBN 24
+#define MCDI_HEADER_XFLAGS_WIDTH 8
+/* Request response using event */
+#define MCDI_HEADER_XFLAGS_EVREQ 0x01
+
+/* Maximum number of payload bytes */
+#ifdef WITH_MCDI_V2
+#define MCDI_CTL_SDU_LEN_MAX 0x400
+#else
+#define MCDI_CTL_SDU_LEN_MAX 0xfc
+#endif
+
+/* The MC can generate events for two reasons:
+ *   - To complete a shared memory request if XFLAGS_EVREQ was set
+ *   - As a notification (link state, i2c event), controlled
+ *     via MC_CMD_LOG_CTRL
+ *
+ * Both events share a common structure:
+ *
+ *  0      32     33      36    44     52     60
+ * | Data | Cont | Level | Src | Code | Rsvd |
+ *           |
+ *           \ There is another event pending in this notification
+ *
+ * If Code==CMDDONE, then the fields are further interpreted as:
+ *
+ *   - LEVEL==INFO    Command succeeded
+ *   - LEVEL==ERR     Command failed
+ *
+ *    0     8         16      24     32
+ *   | Seq | Datalen | Errno | Rsvd |
+ *
+ *   These fields are taken directly out of the standard MCDI header, i.e.,
+ *   LEVEL==ERR, Datalen == 0 => Reboot
+ *
+ * Events can be squirted out of the UART (using LOG_CTRL) without a
+ * MCDI header.  An event can be distinguished from a MCDI response by
+ * examining the first byte which is 0xc0.  This corresponds to the
+ * non-existent MCDI command MC_CMD_DEBUG_LOG.
+ *
+ *      0         7        8
+ *     | command | Resync |     = 0xc0
+ *
+ * Since the event is written in big-endian byte order, this works
+ * providing bits 56-63 of the event are 0xc0.
+ *
+ *      56     60  63
+ *     | Rsvd | Code |    = 0xc0
+ *
+ * Which means for convenience the event code is 0xc for all MC
+ * generated events.
+ */
+#define FSE_AZ_EV_CODE_MCDI_EVRESPONSE 0xc
+
+
+/* Non-existent command target */
+#define MC_CMD_ERR_ENOENT 2
+/* assert() has killed the MC */
+#define MC_CMD_ERR_EINTR 4
+/* Caller does not hold required locks */
+#define MC_CMD_ERR_EACCES 13
+/* Resource is currently unavailable (e.g. lock contention) */
+#define MC_CMD_ERR_EBUSY 16
+/* Invalid argument to target */
+#define MC_CMD_ERR_EINVAL 22
+/* Non-recursive resource is already acquired */
+#define MC_CMD_ERR_EDEADLK 35
+/* Operation not implemented */
+#define MC_CMD_ERR_ENOSYS 38
+/* Operation timed out */
+#define MC_CMD_ERR_ETIME 62
+
+#define MC_CMD_ERR_CODE_OFST 0
+
+/* We define 8 "escape" commands to allow
+   for command number space extension */
+
+#define MC_CMD_CMD_SPACE_ESCAPE_0	      0x78
+#define MC_CMD_CMD_SPACE_ESCAPE_1	      0x79
+#define MC_CMD_CMD_SPACE_ESCAPE_2	      0x7A
+#define MC_CMD_CMD_SPACE_ESCAPE_3	      0x7B
+#define MC_CMD_CMD_SPACE_ESCAPE_4	      0x7C
+#define MC_CMD_CMD_SPACE_ESCAPE_5	      0x7D
+#define MC_CMD_CMD_SPACE_ESCAPE_6	      0x7E
+#define MC_CMD_CMD_SPACE_ESCAPE_7	      0x7F
+
+/* Vectors in the boot ROM */
+/* Point to the copycode entry point. */
+#define MC_BOOTROM_COPYCODE_VEC (0x7f4)
+/* Points to the recovery mode entry point. */
+#define MC_BOOTROM_NOFLASH_VEC (0x7f8)
+
+/* The command set exported by the boot ROM (MCDI v0) */
+#define MC_CMD_GET_VERSION_V0_SUPPORTED_FUNCS {		\
+	(1 << MC_CMD_READ32)	|			\
+	(1 << MC_CMD_WRITE32)	|			\
+	(1 << MC_CMD_COPYCODE)	|			\
+	(1 << MC_CMD_GET_VERSION),			\
+	0, 0, 0 }
+
+#define MC_CMD_SENSOR_INFO_OUT_OFFSET_OFST(_x) \
+	(MC_CMD_SENSOR_ENTRY_OFST + (_x))
+
+#define MC_CMD_DBI_WRITE_IN_ADDRESS_OFST(n) (  \
+        (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST+     \
+         MC_CMD_DBIWROP_TYPEDEF_ADDRESS_OFST)+ \
+         ((n)*MC_CMD_DBIWROP_TYPEDEF_LEN))
+
+#define MC_CMD_DBI_WRITE_IN_BYTE_MASK_OFST(n) (  \
+        (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST+     \
+         MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_OFST)+ \
+         ((n)*MC_CMD_DBIWROP_TYPEDEF_LEN))
+
+#define MC_CMD_DBI_WRITE_IN_VALUE_OFST(n) (  \
+        (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST+     \
+         MC_CMD_DBIWROP_TYPEDEF_VALUE_OFST)+ \
+         ((n)*MC_CMD_DBIWROP_TYPEDEF_LEN))
+
+
+#ifdef WITH_MCDI_V2
+
+/* Version 2 adds an optional argument to error returns: the errno value
+ * may be followed by the (0-based) number of the first argument that
+ * could not be processed.
+ */
+#define MC_CMD_ERR_ARG_OFST 4
+
+/* Try again */
+#define MC_CMD_ERR_EAGAIN 11
+/* No space */
+#define MC_CMD_ERR_ENOSPC 28
+
+#endif
+
+/* MCDI_EVENT structuredef */
+#define	MCDI_EVENT_LEN 8
+#define	MCDI_EVENT_CONT_LBN 32
+#define	MCDI_EVENT_CONT_WIDTH 1
+#define	MCDI_EVENT_LEVEL_LBN 33
+#define	MCDI_EVENT_LEVEL_WIDTH 3
+#define	MCDI_EVENT_LEVEL_INFO  0x0 /* enum */
+#define	MCDI_EVENT_LEVEL_WARN 0x1 /* enum */
+#define	MCDI_EVENT_LEVEL_ERR 0x2 /* enum */
+#define	MCDI_EVENT_LEVEL_FATAL 0x3 /* enum */
+#define	MCDI_EVENT_DATA_OFST 0
+#define	MCDI_EVENT_CMDDONE_SEQ_LBN 0
+#define	MCDI_EVENT_CMDDONE_SEQ_WIDTH 8
+#define	MCDI_EVENT_CMDDONE_DATALEN_LBN 8
+#define	MCDI_EVENT_CMDDONE_DATALEN_WIDTH 8
+#define	MCDI_EVENT_CMDDONE_ERRNO_LBN 16
+#define	MCDI_EVENT_CMDDONE_ERRNO_WIDTH 8
+#define	MCDI_EVENT_LINKCHANGE_LP_CAP_LBN 0
+#define	MCDI_EVENT_LINKCHANGE_LP_CAP_WIDTH 16
+#define	MCDI_EVENT_LINKCHANGE_SPEED_LBN 16
+#define	MCDI_EVENT_LINKCHANGE_SPEED_WIDTH 4
+#define	MCDI_EVENT_LINKCHANGE_SPEED_100M  0x1 /* enum */
+#define	MCDI_EVENT_LINKCHANGE_SPEED_1G  0x2 /* enum */
+#define	MCDI_EVENT_LINKCHANGE_SPEED_10G  0x3 /* enum */
+#define	MCDI_EVENT_LINKCHANGE_FCNTL_LBN 20
+#define	MCDI_EVENT_LINKCHANGE_FCNTL_WIDTH 4
+#define	MCDI_EVENT_LINKCHANGE_LINK_FLAGS_LBN 24
+#define	MCDI_EVENT_LINKCHANGE_LINK_FLAGS_WIDTH 8
+#define	MCDI_EVENT_SENSOREVT_MONITOR_LBN 0
+#define	MCDI_EVENT_SENSOREVT_MONITOR_WIDTH 8
+#define	MCDI_EVENT_SENSOREVT_STATE_LBN 8
+#define	MCDI_EVENT_SENSOREVT_STATE_WIDTH 8
+#define	MCDI_EVENT_SENSOREVT_VALUE_LBN 16
+#define	MCDI_EVENT_SENSOREVT_VALUE_WIDTH 16
+#define	MCDI_EVENT_FWALERT_DATA_LBN 8
+#define	MCDI_EVENT_FWALERT_DATA_WIDTH 24
+#define	MCDI_EVENT_FWALERT_REASON_LBN 0
+#define	MCDI_EVENT_FWALERT_REASON_WIDTH 8
+#define	MCDI_EVENT_FWALERT_REASON_SRAM_ACCESS 0x1 /* enum */
+#define	MCDI_EVENT_FLR_VF_LBN 0
+#define	MCDI_EVENT_FLR_VF_WIDTH 8
+#define	MCDI_EVENT_TX_ERR_TXQ_LBN 0
+#define	MCDI_EVENT_TX_ERR_TXQ_WIDTH 12
+#define	MCDI_EVENT_TX_ERR_TYPE_LBN 12
+#define	MCDI_EVENT_TX_ERR_TYPE_WIDTH 4
+#define	MCDI_EVENT_TX_ERR_DL_FAIL 0x1 /* enum */
+#define	MCDI_EVENT_TX_ERR_NO_EOP 0x2 /* enum */
+#define	MCDI_EVENT_TX_ERR_2BIG 0x3 /* enum */
+#define	MCDI_EVENT_TX_ERR_INFO_LBN 16
+#define	MCDI_EVENT_TX_ERR_INFO_WIDTH 16
+#define	MCDI_EVENT_TX_FLUSH_TXQ_LBN 0
+#define	MCDI_EVENT_TX_FLUSH_TXQ_WIDTH 12
+#define	MCDI_EVENT_PTP_ERR_TYPE_LBN 0
+#define	MCDI_EVENT_PTP_ERR_TYPE_WIDTH 8
+#define	MCDI_EVENT_PTP_ERR_PLL_LOST 0x1 /* enum */
+#define	MCDI_EVENT_PTP_ERR_FILTER 0x2 /* enum */
+#define	MCDI_EVENT_PTP_ERR_FIFO 0x3 /* enum */
+#define	MCDI_EVENT_PTP_ERR_QUEUE 0x4 /* enum */
+#define	MCDI_EVENT_DATA_LBN 0
+#define	MCDI_EVENT_DATA_WIDTH 32
+#define	MCDI_EVENT_SRC_LBN 36
+#define	MCDI_EVENT_SRC_WIDTH 8
+#define	MCDI_EVENT_EV_CODE_LBN 60
+#define	MCDI_EVENT_EV_CODE_WIDTH 4
+#define	MCDI_EVENT_CODE_LBN 44
+#define	MCDI_EVENT_CODE_WIDTH 8
+#define	MCDI_EVENT_CODE_BADSSERT 0x1 /* enum */
+#define	MCDI_EVENT_CODE_PMNOTICE 0x2 /* enum */
+#define	MCDI_EVENT_CODE_CMDDONE 0x3 /* enum */
+#define	MCDI_EVENT_CODE_LINKCHANGE 0x4 /* enum */
+#define	MCDI_EVENT_CODE_SENSOREVT 0x5 /* enum */
+#define	MCDI_EVENT_CODE_SCHEDERR 0x6 /* enum */
+#define	MCDI_EVENT_CODE_REBOOT 0x7 /* enum */
+#define	MCDI_EVENT_CODE_MAC_STATS_DMA 0x8 /* enum */
+#define	MCDI_EVENT_CODE_FWALERT 0x9 /* enum */
+#define	MCDI_EVENT_CODE_FLR 0xa /* enum */
+#define	MCDI_EVENT_CODE_TX_ERR 0xb /* enum */
+#define	MCDI_EVENT_CODE_TX_FLUSH  0xc /* enum */
+#define	MCDI_EVENT_CODE_PTP_RX  0xd /* enum */
+#define	MCDI_EVENT_CODE_PTP_FAULT  0xe /* enum */
+#define	MCDI_EVENT_CODE_VCAL_FAIL  0x13 /* enum */
+#define	MCDI_EVENT_CMDDONE_DATA_OFST 0
+#define	MCDI_EVENT_CMDDONE_DATA_LBN 0
+#define	MCDI_EVENT_CMDDONE_DATA_WIDTH 32
+#define	MCDI_EVENT_LINKCHANGE_DATA_OFST 0
+#define	MCDI_EVENT_LINKCHANGE_DATA_LBN 0
+#define	MCDI_EVENT_LINKCHANGE_DATA_WIDTH 32
+#define	MCDI_EVENT_SENSOREVT_DATA_OFST 0
+#define	MCDI_EVENT_SENSOREVT_DATA_LBN 0
+#define	MCDI_EVENT_SENSOREVT_DATA_WIDTH 32
+#define	MCDI_EVENT_MAC_STATS_DMA_GENERATION_OFST 0
+#define	MCDI_EVENT_MAC_STATS_DMA_GENERATION_LBN 0
+#define	MCDI_EVENT_MAC_STATS_DMA_GENERATION_WIDTH 32
+#define	MCDI_EVENT_TX_ERR_DATA_OFST 0
+#define	MCDI_EVENT_TX_ERR_DATA_LBN 0
+#define	MCDI_EVENT_TX_ERR_DATA_WIDTH 32
+#define	MCDI_EVENT_PTP_SECONDS_OFST 0
+#define	MCDI_EVENT_PTP_SECONDS_LBN 0
+#define	MCDI_EVENT_PTP_SECONDS_WIDTH 32
+#define	MCDI_EVENT_PTP_NANOSECONDS_OFST 0
+#define	MCDI_EVENT_PTP_NANOSECONDS_LBN 0
+#define	MCDI_EVENT_PTP_NANOSECONDS_WIDTH 32
+#define	MCDI_EVENT_PTP_UUID_OFST 0
+#define	MCDI_EVENT_PTP_UUID_LBN 0
+#define	MCDI_EVENT_PTP_UUID_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_READ32
+ * Read multiple 32byte words from MC memory.
+ */
+#define	MC_CMD_READ32 0x1
+
+/* MC_CMD_READ32_IN msgrequest */
+#define	MC_CMD_READ32_IN_LEN 8
+#define	MC_CMD_READ32_IN_ADDR_OFST 0
+#define	MC_CMD_READ32_IN_NUMWORDS_OFST 4
+
+/* MC_CMD_READ32_OUT msgresponse */
+#define	MC_CMD_READ32_OUT_LENMIN 4
+#define	MC_CMD_READ32_OUT_LENMAX 252
+#define	MC_CMD_READ32_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_READ32_OUT_BUFFER_OFST 0
+#define	MC_CMD_READ32_OUT_BUFFER_LEN 4
+#define	MC_CMD_READ32_OUT_BUFFER_MINNUM 1
+#define	MC_CMD_READ32_OUT_BUFFER_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_WRITE32
+ * Write multiple 32byte words to MC memory.
+ */
+#define	MC_CMD_WRITE32 0x2
+
+/* MC_CMD_WRITE32_IN msgrequest */
+#define	MC_CMD_WRITE32_IN_LENMIN 8
+#define	MC_CMD_WRITE32_IN_LENMAX 252
+#define	MC_CMD_WRITE32_IN_LEN(num) (4+4*(num))
+#define	MC_CMD_WRITE32_IN_ADDR_OFST 0
+#define	MC_CMD_WRITE32_IN_BUFFER_OFST 4
+#define	MC_CMD_WRITE32_IN_BUFFER_LEN 4
+#define	MC_CMD_WRITE32_IN_BUFFER_MINNUM 1
+#define	MC_CMD_WRITE32_IN_BUFFER_MAXNUM 62
+
+/* MC_CMD_WRITE32_OUT msgresponse */
+#define	MC_CMD_WRITE32_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_COPYCODE
+ * Copy MC code between two locations and jump.
+ */
+#define	MC_CMD_COPYCODE 0x3
+
+/* MC_CMD_COPYCODE_IN msgrequest */
+#define	MC_CMD_COPYCODE_IN_LEN 16
+#define	MC_CMD_COPYCODE_IN_SRC_ADDR_OFST 0
+#define	MC_CMD_COPYCODE_IN_DEST_ADDR_OFST 4
+#define	MC_CMD_COPYCODE_IN_NUMWORDS_OFST 8
+#define	MC_CMD_COPYCODE_IN_JUMP_OFST 12
+#define	MC_CMD_COPYCODE_JUMP_NONE 0x1 /* enum */
+
+/* MC_CMD_COPYCODE_OUT msgresponse */
+#define	MC_CMD_COPYCODE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SET_FUNC 
+ */
+#define	MC_CMD_SET_FUNC  0x4
+
+/* MC_CMD_SET_FUNC_IN msgrequest */
+#define	MC_CMD_SET_FUNC_IN_LEN 4
+#define	MC_CMD_SET_FUNC_IN_FUNC_OFST 0
+
+/* MC_CMD_SET_FUNC_OUT msgresponse */
+#define	MC_CMD_SET_FUNC_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_BOOT_STATUS
+ */
+#define	MC_CMD_GET_BOOT_STATUS 0x5
+
+/* MC_CMD_GET_BOOT_STATUS_IN msgrequest */
+#define	MC_CMD_GET_BOOT_STATUS_IN_LEN 0
+
+/* MC_CMD_GET_BOOT_STATUS_OUT msgresponse */
+#define	MC_CMD_GET_BOOT_STATUS_OUT_LEN 8
+#define	MC_CMD_GET_BOOT_STATUS_OUT_BOOT_OFFSET_OFST 0
+#define	MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_OFST 4
+#define	MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_WATCHDOG_LBN 0
+#define	MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_WATCHDOG_WIDTH 1
+#define	MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_PRIMARY_LBN 1
+#define	MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_PRIMARY_WIDTH 1
+#define	MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_BACKUP_LBN 2
+#define	MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_BACKUP_WIDTH 1
+
+
+/***********************************/
+/* MC_CMD_GET_ASSERTS 
+ * Get and clear any assertion status.
+ */
+#define	MC_CMD_GET_ASSERTS  0x6
+
+/* MC_CMD_GET_ASSERTS_IN msgrequest */
+#define	MC_CMD_GET_ASSERTS_IN_LEN 4
+#define	MC_CMD_GET_ASSERTS_IN_CLEAR_OFST 0
+
+/* MC_CMD_GET_ASSERTS_OUT msgresponse */
+#define	MC_CMD_GET_ASSERTS_OUT_LEN 140
+#define	MC_CMD_GET_ASSERTS_OUT_GLOBAL_FLAGS_OFST 0
+#define	MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS 0x1 /* enum */
+#define	MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL 0x2 /* enum */
+#define	MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL 0x3 /* enum */
+#define	MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED 0x4 /* enum */
+#define	MC_CMD_GET_ASSERTS_OUT_SAVED_PC_OFFS_OFST 4
+#define	MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST 8
+#define	MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_LEN 4
+#define	MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM 31
+#define	MC_CMD_GET_ASSERTS_OUT_THREAD_OFFS_OFST 132
+#define	MC_CMD_GET_ASSERTS_OUT_RESERVED_OFST 136
+
+
+/***********************************/
+/* MC_CMD_LOG_CTRL 
+ * Configure the output stream for various events and messages.
+ */
+#define	MC_CMD_LOG_CTRL  0x7
+
+/* MC_CMD_LOG_CTRL_IN msgrequest */
+#define	MC_CMD_LOG_CTRL_IN_LEN 8
+#define	MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0
+#define	MC_CMD_LOG_CTRL_IN_LOG_DEST_UART 0x1 /* enum */
+#define	MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ 0x2 /* enum */
+#define	MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ_OFST 4
+
+/* MC_CMD_LOG_CTRL_OUT msgresponse */
+#define	MC_CMD_LOG_CTRL_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_VERSION 
+ * Get version information about the MC firmware.
+ */
+#define	MC_CMD_GET_VERSION  0x8
+
+/* MC_CMD_GET_VERSION_IN msgrequest */
+#define	MC_CMD_GET_VERSION_IN_LEN 0
+
+/* MC_CMD_GET_VERSION_V0_OUT msgresponse */
+#define	MC_CMD_GET_VERSION_V0_OUT_LEN 4
+#define	MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0
+#define	MC_CMD_GET_VERSION_OUT_FIRMWARE_ANY 0xffffffff /* enum */
+#define	MC_CMD_GET_VERSION_OUT_FIRMWARE_BOOTROM 0xb0070000 /* enum */
+
+/* MC_CMD_GET_VERSION_OUT msgresponse */
+#define	MC_CMD_GET_VERSION_OUT_LEN 32
+/*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
+/*            Enum values, see field(s): */
+/*               MC_CMD_GET_VERSION_V0_OUT/MC_CMD_GET_VERSION_OUT_FIRMWARE */
+#define	MC_CMD_GET_VERSION_OUT_PCOL_OFST 4
+#define	MC_CMD_GET_VERSION_OUT_SUPPORTED_FUNCS_OFST 8
+#define	MC_CMD_GET_VERSION_OUT_SUPPORTED_FUNCS_LEN 16
+#define	MC_CMD_GET_VERSION_OUT_VERSION_OFST 24
+#define	MC_CMD_GET_VERSION_OUT_VERSION_LEN 8
+#define	MC_CMD_GET_VERSION_OUT_VERSION_LO_OFST 24
+#define	MC_CMD_GET_VERSION_OUT_VERSION_HI_OFST 28
+
+
+/***********************************/
+/* MC_CMD_GET_FPGAREG 
+ * Read multiple bytes from PTP FPGA.
+ */
+#define	MC_CMD_GET_FPGAREG  0x9
+
+/* MC_CMD_GET_FPGAREG_IN msgrequest */
+#define	MC_CMD_GET_FPGAREG_IN_LEN 8
+#define	MC_CMD_GET_FPGAREG_IN_ADDR_OFST 0
+#define	MC_CMD_GET_FPGAREG_IN_NUMBYTES_OFST 4
+
+/* MC_CMD_GET_FPGAREG_OUT msgresponse */
+#define	MC_CMD_GET_FPGAREG_OUT_LENMIN 1
+#define	MC_CMD_GET_FPGAREG_OUT_LENMAX 252
+#define	MC_CMD_GET_FPGAREG_OUT_LEN(num) (0+1*(num))
+#define	MC_CMD_GET_FPGAREG_OUT_BUFFER_OFST 0
+#define	MC_CMD_GET_FPGAREG_OUT_BUFFER_LEN 1
+#define	MC_CMD_GET_FPGAREG_OUT_BUFFER_MINNUM 1
+#define	MC_CMD_GET_FPGAREG_OUT_BUFFER_MAXNUM 252
+
+
+/***********************************/
+/* MC_CMD_PUT_FPGAREG 
+ * Write multiple bytes to PTP FPGA.
+ */
+#define	MC_CMD_PUT_FPGAREG  0xa
+
+/* MC_CMD_PUT_FPGAREG_IN msgrequest */
+#define	MC_CMD_PUT_FPGAREG_IN_LENMIN 5
+#define	MC_CMD_PUT_FPGAREG_IN_LENMAX 252
+#define	MC_CMD_PUT_FPGAREG_IN_LEN(num) (4+1*(num))
+#define	MC_CMD_PUT_FPGAREG_IN_ADDR_OFST 0
+#define	MC_CMD_PUT_FPGAREG_IN_BUFFER_OFST 4
+#define	MC_CMD_PUT_FPGAREG_IN_BUFFER_LEN 1
+#define	MC_CMD_PUT_FPGAREG_IN_BUFFER_MINNUM 1
+#define	MC_CMD_PUT_FPGAREG_IN_BUFFER_MAXNUM 248
+
+/* MC_CMD_PUT_FPGAREG_OUT msgresponse */
+#define	MC_CMD_PUT_FPGAREG_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_PTP 
+ * Perform PTP operation
+ */
+#define	MC_CMD_PTP  0xb
+
+/* MC_CMD_PTP_IN msgrequest */
+#define	MC_CMD_PTP_IN_LEN 1
+#define	MC_CMD_PTP_IN_OP_OFST 0
+#define	MC_CMD_PTP_IN_OP_LEN 1
+#define	MC_CMD_PTP_OP_ENABLE 0x1 /* enum */
+#define	MC_CMD_PTP_OP_DISABLE 0x2 /* enum */
+#define	MC_CMD_PTP_OP_TRANSMIT 0x3 /* enum */
+#define	MC_CMD_PTP_OP_READ_NIC_TIME 0x4 /* enum */
+#define	MC_CMD_PTP_OP_STATUS 0x5 /* enum */
+#define	MC_CMD_PTP_OP_ADJUST 0x6 /* enum */
+#define	MC_CMD_PTP_OP_SYNCHRONIZE 0x7 /* enum */
+#define	MC_CMD_PTP_OP_MANFTEST_BASIC 0x8 /* enum */
+#define	MC_CMD_PTP_OP_MANFTEST_PACKET 0x9 /* enum */
+#define	MC_CMD_PTP_OP_RESET_STATS 0xa /* enum */
+#define	MC_CMD_PTP_OP_DEBUG 0xb /* enum */
+#define	MC_CMD_PTP_OP_MAX 0xc /* enum */
+
+/* MC_CMD_PTP_IN_ENABLE msgrequest */
+#define	MC_CMD_PTP_IN_ENABLE_LEN 16
+#define	MC_CMD_PTP_IN_CMD_OFST 0
+#define	MC_CMD_PTP_IN_PERIPH_ID_OFST 4
+#define	MC_CMD_PTP_IN_ENABLE_QUEUE_OFST 8
+#define	MC_CMD_PTP_IN_ENABLE_MODE_OFST 12
+#define	MC_CMD_PTP_MODE_V1 0x0 /* enum */
+#define	MC_CMD_PTP_MODE_V1_VLAN 0x1 /* enum */
+#define	MC_CMD_PTP_MODE_V2 0x2 /* enum */
+#define	MC_CMD_PTP_MODE_V2_VLAN 0x3 /* enum */
+
+/* MC_CMD_PTP_IN_DISABLE msgrequest */
+#define	MC_CMD_PTP_IN_DISABLE_LEN 8
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_TRANSMIT msgrequest */
+#define	MC_CMD_PTP_IN_TRANSMIT_LENMIN 13
+#define	MC_CMD_PTP_IN_TRANSMIT_LENMAX 252
+#define	MC_CMD_PTP_IN_TRANSMIT_LEN(num) (12+1*(num))
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define	MC_CMD_PTP_IN_TRANSMIT_LENGTH_OFST 8
+#define	MC_CMD_PTP_IN_TRANSMIT_PACKET_OFST 12
+#define	MC_CMD_PTP_IN_TRANSMIT_PACKET_LEN 1
+#define	MC_CMD_PTP_IN_TRANSMIT_PACKET_MINNUM 1
+#define	MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM 240
+
+/* MC_CMD_PTP_IN_READ_NIC_TIME msgrequest */
+#define	MC_CMD_PTP_IN_READ_NIC_TIME_LEN 8
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_STATUS msgrequest */
+#define	MC_CMD_PTP_IN_STATUS_LEN 8
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_ADJUST msgrequest */
+#define	MC_CMD_PTP_IN_ADJUST_LEN 24
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define	MC_CMD_PTP_IN_ADJUST_FREQ_OFST 8
+#define	MC_CMD_PTP_IN_ADJUST_FREQ_LEN 8
+#define	MC_CMD_PTP_IN_ADJUST_FREQ_LO_OFST 8
+#define	MC_CMD_PTP_IN_ADJUST_FREQ_HI_OFST 12
+#define	MC_CMD_PTP_IN_ADJUST_BITS 0x28 /* enum */
+#define	MC_CMD_PTP_IN_ADJUST_SECONDS_OFST 16
+#define	MC_CMD_PTP_IN_ADJUST_NANOSECONDS_OFST 20
+
+/* MC_CMD_PTP_IN_SYNCHRONIZE msgrequest */
+#define	MC_CMD_PTP_IN_SYNCHRONIZE_LEN 20
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define	MC_CMD_PTP_IN_SYNCHRONIZE_NUMTIMESETS_OFST 8
+#define	MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_OFST 12
+#define	MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_LEN 8
+#define	MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_LO_OFST 12
+#define	MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_HI_OFST 16
+
+/* MC_CMD_PTP_IN_MANFTEST_BASIC msgrequest */
+#define	MC_CMD_PTP_IN_MANFTEST_BASIC_LEN 8
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_MANFTEST_PACKET msgrequest */
+#define	MC_CMD_PTP_IN_MANFTEST_PACKET_LEN 12
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define	MC_CMD_PTP_IN_MANFTEST_PACKET_TEST_ENABLE_OFST 8
+
+/* MC_CMD_PTP_IN_RESET_STATS msgrequest */
+#define	MC_CMD_PTP_IN_RESET_STATS_LEN 8
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_DEBUG msgrequest */
+#define	MC_CMD_PTP_IN_DEBUG_LEN 12
+/*            MC_CMD_PTP_IN_CMD_OFST 0 */
+/*            MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define	MC_CMD_PTP_IN_DEBUG_DEBUG_PARAM_OFST 8
+
+/* MC_CMD_PTP_OUT msgresponse */
+#define	MC_CMD_PTP_OUT_LEN 0
+
+/* MC_CMD_PTP_OUT_TRANSMIT msgresponse */
+#define	MC_CMD_PTP_OUT_TRANSMIT_LEN 8
+#define	MC_CMD_PTP_OUT_TRANSMIT_SECONDS_OFST 0
+#define	MC_CMD_PTP_OUT_TRANSMIT_NANOSECONDS_OFST 4
+
+/* MC_CMD_PTP_OUT_READ_NIC_TIME msgresponse */
+#define	MC_CMD_PTP_OUT_READ_NIC_TIME_LEN 8
+#define	MC_CMD_PTP_OUT_READ_NIC_TIME_SECONDS_OFST 0
+#define	MC_CMD_PTP_OUT_READ_NIC_TIME_NANOSECONDS_OFST 4
+
+/* MC_CMD_PTP_OUT_STATUS msgresponse */
+#define	MC_CMD_PTP_OUT_STATUS_LEN 64
+#define	MC_CMD_PTP_OUT_STATUS_CLOCK_FREQ_OFST 0
+#define	MC_CMD_PTP_OUT_STATUS_STATS_TX_OFST 4
+#define	MC_CMD_PTP_OUT_STATUS_STATS_RX_OFST 8
+#define	MC_CMD_PTP_OUT_STATUS_STATS_TS_OFST 12
+#define	MC_CMD_PTP_OUT_STATUS_STATS_FM_OFST 16
+#define	MC_CMD_PTP_OUT_STATUS_STATS_NFM_OFST 20
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFLOW_OFST 24
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_BAD_OFST 28
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MIN_OFST 32
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MAX_OFST 36
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_LAST_OFST 40
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MEAN_OFST 44
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MIN_OFST 48
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MAX_OFST 52
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_LAST_OFST 56
+#define	MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MEAN_OFST 60
+
+/* MC_CMD_PTP_OUT_SYNCHRONIZE msgresponse */
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_LENMIN 20
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_LENMAX 240
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_LEN(num) (0+20*(num))
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_OFST 0
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_LEN 20
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MINNUM 1
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MAXNUM 12
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTSTART_OFST 0
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_SECONDS_OFST 4
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_NANOSECONDS_OFST 8
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTEND_OFST 12
+#define	MC_CMD_PTP_OUT_SYNCHRONIZE_WAITNS_OFST 16
+
+/* MC_CMD_PTP_OUT_MANFTEST_BASIC msgresponse */
+#define	MC_CMD_PTP_OUT_MANFTEST_BASIC_LEN 8
+#define	MC_CMD_PTP_OUT_MANFTEST_BASIC_TEST_RESULT_OFST 0
+#define	MC_CMD_PTP_MANF_SUCCESS 0x0 /* enum */
+#define	MC_CMD_PTP_MANF_FPGA_LOAD 0x1 /* enum */
+#define	MC_CMD_PTP_MANF_FPGA_VERSION 0x2 /* enum */
+#define	MC_CMD_PTP_MANF_FPGA_REGISTERS 0x3 /* enum */
+#define	MC_CMD_PTP_MANF_OSCILLATOR 0x4 /* enum */
+#define	MC_CMD_PTP_MANF_TIMESTAMPS 0x5 /* enum */
+#define	MC_CMD_PTP_MANF_PACKET_COUNT 0x6 /* enum */
+#define	MC_CMD_PTP_MANF_FILTER_COUNT 0x7 /* enum */
+#define	MC_CMD_PTP_MANF_PACKET_ENOUGH 0x8 /* enum */
+#define	MC_CMD_PTP_MANF_GPIO_TRIGGER 0x9 /* enum */
+#define	MC_CMD_PTP_OUT_MANFTEST_BASIC_TEST_EXTOSC_OFST 4
+
+/* MC_CMD_PTP_OUT_MANFTEST_PACKET msgresponse */
+#define	MC_CMD_PTP_OUT_MANFTEST_PACKET_LEN 12
+#define	MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_RESULT_OFST 0
+#define	MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_FPGACOUNT_OFST 4
+#define	MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_FILTERCOUNT_OFST 8
+
+
+/***********************************/
+/* MC_CMD_CSR_READ32 
+ * Read 32bit words from the indirect memory map.
+ */
+#define	MC_CMD_CSR_READ32  0xc
+
+/* MC_CMD_CSR_READ32_IN msgrequest */
+#define	MC_CMD_CSR_READ32_IN_LEN 12
+#define	MC_CMD_CSR_READ32_IN_ADDR_OFST 0
+#define	MC_CMD_CSR_READ32_IN_STEP_OFST 4
+#define	MC_CMD_CSR_READ32_IN_NUMWORDS_OFST 8
+
+/* MC_CMD_CSR_READ32_OUT msgresponse */
+#define	MC_CMD_CSR_READ32_OUT_LENMIN 4
+#define	MC_CMD_CSR_READ32_OUT_LENMAX 252
+#define	MC_CMD_CSR_READ32_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_CSR_READ32_OUT_BUFFER_OFST 0
+#define	MC_CMD_CSR_READ32_OUT_BUFFER_LEN 4
+#define	MC_CMD_CSR_READ32_OUT_BUFFER_MINNUM 1
+#define	MC_CMD_CSR_READ32_OUT_BUFFER_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_CSR_WRITE32 
+ * Write 32bit dwords to the indirect memory map.
+ */
+#define	MC_CMD_CSR_WRITE32  0xd
+
+/* MC_CMD_CSR_WRITE32_IN msgrequest */
+#define	MC_CMD_CSR_WRITE32_IN_LENMIN 12
+#define	MC_CMD_CSR_WRITE32_IN_LENMAX 252
+#define	MC_CMD_CSR_WRITE32_IN_LEN(num) (8+4*(num))
+#define	MC_CMD_CSR_WRITE32_IN_ADDR_OFST 0
+#define	MC_CMD_CSR_WRITE32_IN_STEP_OFST 4
+#define	MC_CMD_CSR_WRITE32_IN_BUFFER_OFST 8
+#define	MC_CMD_CSR_WRITE32_IN_BUFFER_LEN 4
+#define	MC_CMD_CSR_WRITE32_IN_BUFFER_MINNUM 1
+#define	MC_CMD_CSR_WRITE32_IN_BUFFER_MAXNUM 61
+
+/* MC_CMD_CSR_WRITE32_OUT msgresponse */
+#define	MC_CMD_CSR_WRITE32_OUT_LEN 4
+#define	MC_CMD_CSR_WRITE32_OUT_STATUS_OFST 0
+
+
+/***********************************/
+/* MC_CMD_STACKINFO 
+ * Get stack information.
+ */
+#define	MC_CMD_STACKINFO  0xf
+
+/* MC_CMD_STACKINFO_IN msgrequest */
+#define	MC_CMD_STACKINFO_IN_LEN 0
+
+/* MC_CMD_STACKINFO_OUT msgresponse */
+#define	MC_CMD_STACKINFO_OUT_LENMIN 12
+#define	MC_CMD_STACKINFO_OUT_LENMAX 252
+#define	MC_CMD_STACKINFO_OUT_LEN(num) (0+12*(num))
+#define	MC_CMD_STACKINFO_OUT_THREAD_INFO_OFST 0
+#define	MC_CMD_STACKINFO_OUT_THREAD_INFO_LEN 12
+#define	MC_CMD_STACKINFO_OUT_THREAD_INFO_MINNUM 1
+#define	MC_CMD_STACKINFO_OUT_THREAD_INFO_MAXNUM 21
+
+
+/***********************************/
+/* MC_CMD_MDIO_READ 
+ * MDIO register read.
+ */
+#define	MC_CMD_MDIO_READ  0x10
+
+/* MC_CMD_MDIO_READ_IN msgrequest */
+#define	MC_CMD_MDIO_READ_IN_LEN 16
+#define	MC_CMD_MDIO_READ_IN_BUS_OFST 0
+#define	MC_CMD_MDIO_BUS_INTERNAL 0x0 /* enum */
+#define	MC_CMD_MDIO_BUS_EXTERNAL 0x1 /* enum */
+#define	MC_CMD_MDIO_READ_IN_PRTAD_OFST 4
+#define	MC_CMD_MDIO_READ_IN_DEVAD_OFST 8
+#define	MC_CMD_MDIO_CLAUSE22 0x20 /* enum */
+#define	MC_CMD_MDIO_READ_IN_ADDR_OFST 12
+
+/* MC_CMD_MDIO_READ_OUT msgresponse */
+#define	MC_CMD_MDIO_READ_OUT_LEN 8
+#define	MC_CMD_MDIO_READ_OUT_VALUE_OFST 0
+#define	MC_CMD_MDIO_READ_OUT_STATUS_OFST 4
+#define	MC_CMD_MDIO_STATUS_GOOD 0x8 /* enum */
+
+
+/***********************************/
+/* MC_CMD_MDIO_WRITE 
+ * MDIO register write.
+ */
+#define	MC_CMD_MDIO_WRITE  0x11
+
+/* MC_CMD_MDIO_WRITE_IN msgrequest */
+#define	MC_CMD_MDIO_WRITE_IN_LEN 20
+#define	MC_CMD_MDIO_WRITE_IN_BUS_OFST 0
+/*               MC_CMD_MDIO_BUS_INTERNAL 0x0 */
+/*               MC_CMD_MDIO_BUS_EXTERNAL 0x1 */
+#define	MC_CMD_MDIO_WRITE_IN_PRTAD_OFST 4
+#define	MC_CMD_MDIO_WRITE_IN_DEVAD_OFST 8
+/*               MC_CMD_MDIO_CLAUSE22 0x20 */
+#define	MC_CMD_MDIO_WRITE_IN_ADDR_OFST 12
+#define	MC_CMD_MDIO_WRITE_IN_VALUE_OFST 16
+
+/* MC_CMD_MDIO_WRITE_OUT msgresponse */
+#define	MC_CMD_MDIO_WRITE_OUT_LEN 4
+#define	MC_CMD_MDIO_WRITE_OUT_STATUS_OFST 0
+/*               MC_CMD_MDIO_STATUS_GOOD 0x8 */
+
+
+/***********************************/
+/* MC_CMD_DBI_WRITE 
+ * Write DBI register(s).
+ */
+#define	MC_CMD_DBI_WRITE  0x12
+
+/* MC_CMD_DBI_WRITE_IN msgrequest */
+#define	MC_CMD_DBI_WRITE_IN_LENMIN 12
+#define	MC_CMD_DBI_WRITE_IN_LENMAX 252
+#define	MC_CMD_DBI_WRITE_IN_LEN(num) (0+12*(num))
+#define	MC_CMD_DBI_WRITE_IN_DBIWROP_OFST 0
+#define	MC_CMD_DBI_WRITE_IN_DBIWROP_LEN 12
+#define	MC_CMD_DBI_WRITE_IN_DBIWROP_MINNUM 1
+#define	MC_CMD_DBI_WRITE_IN_DBIWROP_MAXNUM 21
+
+/* MC_CMD_DBI_WRITE_OUT msgresponse */
+#define	MC_CMD_DBI_WRITE_OUT_LEN 0
+
+/* MC_CMD_DBIWROP_TYPEDEF structuredef */
+#define	MC_CMD_DBIWROP_TYPEDEF_LEN 12
+#define	MC_CMD_DBIWROP_TYPEDEF_ADDRESS_OFST 0
+#define	MC_CMD_DBIWROP_TYPEDEF_ADDRESS_LBN 0
+#define	MC_CMD_DBIWROP_TYPEDEF_ADDRESS_WIDTH 32
+#define	MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_OFST 4
+#define	MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_LBN 32
+#define	MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_WIDTH 32
+#define	MC_CMD_DBIWROP_TYPEDEF_VALUE_OFST 8
+#define	MC_CMD_DBIWROP_TYPEDEF_VALUE_LBN 64
+#define	MC_CMD_DBIWROP_TYPEDEF_VALUE_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_PORT_READ32 
+ * Read a 32-bit register from the indirect port register map.
+ */
+#define	MC_CMD_PORT_READ32  0x14
+
+/* MC_CMD_PORT_READ32_IN msgrequest */
+#define	MC_CMD_PORT_READ32_IN_LEN 4
+#define	MC_CMD_PORT_READ32_IN_ADDR_OFST 0
+
+/* MC_CMD_PORT_READ32_OUT msgresponse */
+#define	MC_CMD_PORT_READ32_OUT_LEN 8
+#define	MC_CMD_PORT_READ32_OUT_VALUE_OFST 0
+#define	MC_CMD_PORT_READ32_OUT_STATUS_OFST 4
+
+
+/***********************************/
+/* MC_CMD_PORT_WRITE32 
+ * Write a 32-bit register to the indirect port register map.
+ */
+#define	MC_CMD_PORT_WRITE32  0x15
+
+/* MC_CMD_PORT_WRITE32_IN msgrequest */
+#define	MC_CMD_PORT_WRITE32_IN_LEN 8
+#define	MC_CMD_PORT_WRITE32_IN_ADDR_OFST 0
+#define	MC_CMD_PORT_WRITE32_IN_VALUE_OFST 4
+
+/* MC_CMD_PORT_WRITE32_OUT msgresponse */
+#define	MC_CMD_PORT_WRITE32_OUT_LEN 4
+#define	MC_CMD_PORT_WRITE32_OUT_STATUS_OFST 0
+
+
+/***********************************/
+/* MC_CMD_PORT_READ128 
+ * Read a 128-bit register from the indirect port register map.
+ */
+#define	MC_CMD_PORT_READ128  0x16
+
+/* MC_CMD_PORT_READ128_IN msgrequest */
+#define	MC_CMD_PORT_READ128_IN_LEN 4
+#define	MC_CMD_PORT_READ128_IN_ADDR_OFST 0
+
+/* MC_CMD_PORT_READ128_OUT msgresponse */
+#define	MC_CMD_PORT_READ128_OUT_LEN 20
+#define	MC_CMD_PORT_READ128_OUT_VALUE_OFST 0
+#define	MC_CMD_PORT_READ128_OUT_VALUE_LEN 16
+#define	MC_CMD_PORT_READ128_OUT_STATUS_OFST 16
+
+
+/***********************************/
+/* MC_CMD_PORT_WRITE128 
+ * Write a 128-bit register to the indirect port register map.
+ */
+#define	MC_CMD_PORT_WRITE128  0x17
+
+/* MC_CMD_PORT_WRITE128_IN msgrequest */
+#define	MC_CMD_PORT_WRITE128_IN_LEN 20
+#define	MC_CMD_PORT_WRITE128_IN_ADDR_OFST 0
+#define	MC_CMD_PORT_WRITE128_IN_VALUE_OFST 4
+#define	MC_CMD_PORT_WRITE128_IN_VALUE_LEN 16
+
+/* MC_CMD_PORT_WRITE128_OUT msgresponse */
+#define	MC_CMD_PORT_WRITE128_OUT_LEN 4
+#define	MC_CMD_PORT_WRITE128_OUT_STATUS_OFST 0
+
+
+/***********************************/
+/* MC_CMD_GET_BOARD_CFG 
+ * Returns the MC firmware configuration structure.
+ */
+#define	MC_CMD_GET_BOARD_CFG  0x18
+
+/* MC_CMD_GET_BOARD_CFG_IN msgrequest */
+#define	MC_CMD_GET_BOARD_CFG_IN_LEN 0
+
+/* MC_CMD_GET_BOARD_CFG_OUT msgresponse */
+#define	MC_CMD_GET_BOARD_CFG_OUT_LENMIN 96
+#define	MC_CMD_GET_BOARD_CFG_OUT_LENMAX 136
+#define	MC_CMD_GET_BOARD_CFG_OUT_LEN(num) (72+2*(num))
+#define	MC_CMD_GET_BOARD_CFG_OUT_BOARD_TYPE_OFST 0
+#define	MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_OFST 4
+#define	MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_LEN 32
+#define	MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT0_OFST 36
+#define	MC_CMD_CAPABILITIES_SMALL_BUF_TBL_LBN 0x0 /* enum */
+#define	MC_CMD_CAPABILITIES_SMALL_BUF_TBL_WIDTH 0x1 /* enum */
+#define	MC_CMD_CAPABILITIES_TURBO_LBN 0x1 /* enum */
+#define	MC_CMD_CAPABILITIES_TURBO_WIDTH 0x1 /* enum */
+#define	MC_CMD_CAPABILITIES_TURBO_ACTIVE_LBN 0x2 /* enum */
+#define	MC_CMD_CAPABILITIES_TURBO_ACTIVE_WIDTH 0x1 /* enum */
+#define	MC_CMD_CAPABILITIES_PTP_LBN 0x3 /* enum */
+#define	MC_CMD_CAPABILITIES_PTP_WIDTH 0x1 /* enum */
+#define	MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT1_OFST 40
+/*            Enum values, see field(s): */
+/*               CAPABILITIES_PORT0 */
+#define	MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST 44
+#define	MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_LEN 6
+#define	MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST 50
+#define	MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_LEN 6
+#define	MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT0_OFST 56
+#define	MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT1_OFST 60
+#define	MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT0_OFST 64
+#define	MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT1_OFST 68
+#define	MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST 72
+#define	MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN 2
+#define	MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM 12
+#define	MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM 32
+
+
+/***********************************/
+/* MC_CMD_DBI_READX 
+ * Read DBI register(s).
+ */
+#define	MC_CMD_DBI_READX  0x19
+
+/* MC_CMD_DBI_READX_IN msgrequest */
+#define	MC_CMD_DBI_READX_IN_LENMIN 8
+#define	MC_CMD_DBI_READX_IN_LENMAX 248
+#define	MC_CMD_DBI_READX_IN_LEN(num) (0+8*(num))
+#define	MC_CMD_DBI_READX_IN_DBIRDOP_OFST 0
+#define	MC_CMD_DBI_READX_IN_DBIRDOP_LEN 8
+#define	MC_CMD_DBI_READX_IN_DBIRDOP_LO_OFST 0
+#define	MC_CMD_DBI_READX_IN_DBIRDOP_HI_OFST 4
+#define	MC_CMD_DBI_READX_IN_DBIRDOP_MINNUM 1
+#define	MC_CMD_DBI_READX_IN_DBIRDOP_MAXNUM 31
+
+/* MC_CMD_DBI_READX_OUT msgresponse */
+#define	MC_CMD_DBI_READX_OUT_LENMIN 4
+#define	MC_CMD_DBI_READX_OUT_LENMAX 252
+#define	MC_CMD_DBI_READX_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_DBI_READX_OUT_VALUE_OFST 0
+#define	MC_CMD_DBI_READX_OUT_VALUE_LEN 4
+#define	MC_CMD_DBI_READX_OUT_VALUE_MINNUM 1
+#define	MC_CMD_DBI_READX_OUT_VALUE_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_SET_RAND_SEED 
+ * Set the 16byte seed for the MC pseudo-random generator.
+ */
+#define	MC_CMD_SET_RAND_SEED  0x1a
+
+/* MC_CMD_SET_RAND_SEED_IN msgrequest */
+#define	MC_CMD_SET_RAND_SEED_IN_LEN 16
+#define	MC_CMD_SET_RAND_SEED_IN_SEED_OFST 0
+#define	MC_CMD_SET_RAND_SEED_IN_SEED_LEN 16
+
+/* MC_CMD_SET_RAND_SEED_OUT msgresponse */
+#define	MC_CMD_SET_RAND_SEED_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_LTSSM_HIST 
+ * Retrieve the history of the PCIE LTSSM.
+ */
+#define	MC_CMD_LTSSM_HIST  0x1b
+
+/* MC_CMD_LTSSM_HIST_IN msgrequest */
+#define	MC_CMD_LTSSM_HIST_IN_LEN 0
+
+/* MC_CMD_LTSSM_HIST_OUT msgresponse */
+#define	MC_CMD_LTSSM_HIST_OUT_LENMIN 0
+#define	MC_CMD_LTSSM_HIST_OUT_LENMAX 252
+#define	MC_CMD_LTSSM_HIST_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_LTSSM_HIST_OUT_DATA_OFST 0
+#define	MC_CMD_LTSSM_HIST_OUT_DATA_LEN 4
+#define	MC_CMD_LTSSM_HIST_OUT_DATA_MINNUM 0
+#define	MC_CMD_LTSSM_HIST_OUT_DATA_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_DRV_ATTACH 
+ * Inform MCPU that this port is managed on the host.
+ */
+#define	MC_CMD_DRV_ATTACH  0x1c
+
+/* MC_CMD_DRV_ATTACH_IN msgrequest */
+#define	MC_CMD_DRV_ATTACH_IN_LEN 8
+#define	MC_CMD_DRV_ATTACH_IN_NEW_STATE_OFST 0
+#define	MC_CMD_DRV_ATTACH_IN_UPDATE_OFST 4
+
+/* MC_CMD_DRV_ATTACH_OUT msgresponse */
+#define	MC_CMD_DRV_ATTACH_OUT_LEN 4
+#define	MC_CMD_DRV_ATTACH_OUT_OLD_STATE_OFST 0
+
+
+/***********************************/
+/* MC_CMD_NCSI_PROD 
+ * Trigger an NC-SI event.
+ */
+#define	MC_CMD_NCSI_PROD  0x1d
+
+/* MC_CMD_NCSI_PROD_IN msgrequest */
+#define	MC_CMD_NCSI_PROD_IN_LEN 4
+#define	MC_CMD_NCSI_PROD_IN_EVENTS_OFST 0
+#define	MC_CMD_NCSI_PROD_LINKCHANGE 0x0 /* enum */
+#define	MC_CMD_NCSI_PROD_RESET 0x1 /* enum */
+#define	MC_CMD_NCSI_PROD_DRVATTACH 0x2 /* enum */
+#define	MC_CMD_NCSI_PROD_IN_LINKCHANGE_LBN 0
+#define	MC_CMD_NCSI_PROD_IN_LINKCHANGE_WIDTH 1
+#define	MC_CMD_NCSI_PROD_IN_RESET_LBN 1
+#define	MC_CMD_NCSI_PROD_IN_RESET_WIDTH 1
+#define	MC_CMD_NCSI_PROD_IN_DRVATTACH_LBN 2
+#define	MC_CMD_NCSI_PROD_IN_DRVATTACH_WIDTH 1
+
+/* MC_CMD_NCSI_PROD_OUT msgresponse */
+#define	MC_CMD_NCSI_PROD_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SHMUART 
+ * Route UART output to circular buffer in shared memory instead.
+ */
+#define	MC_CMD_SHMUART  0x1f
+
+/* MC_CMD_SHMUART_IN msgrequest */
+#define	MC_CMD_SHMUART_IN_LEN 4
+#define	MC_CMD_SHMUART_IN_FLAG_OFST 0
+
+/* MC_CMD_SHMUART_OUT msgresponse */
+#define	MC_CMD_SHMUART_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_PORT_RESET 
+ * Generic per-port reset.
+ */
+#define	MC_CMD_PORT_RESET  0x20
+
+/* MC_CMD_PORT_RESET_IN msgrequest */
+#define	MC_CMD_PORT_RESET_IN_LEN 0
+
+/* MC_CMD_PORT_RESET_OUT msgresponse */
+#define	MC_CMD_PORT_RESET_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_PCIE_CREDITS 
+ * Read instantaneous and minimum flow control thresholds.
+ */
+#define	MC_CMD_PCIE_CREDITS  0x21
+
+/* MC_CMD_PCIE_CREDITS_IN msgrequest */
+#define	MC_CMD_PCIE_CREDITS_IN_LEN 8
+#define	MC_CMD_PCIE_CREDITS_IN_POLL_PERIOD_OFST 0
+#define	MC_CMD_PCIE_CREDITS_IN_WIPE_OFST 4
+
+/* MC_CMD_PCIE_CREDITS_OUT msgresponse */
+#define	MC_CMD_PCIE_CREDITS_OUT_LEN 16
+#define	MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_HDR_OFST 0
+#define	MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_HDR_LEN 2
+#define	MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_DATA_OFST 2
+#define	MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_DATA_LEN 2
+#define	MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_HDR_OFST 4
+#define	MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_HDR_LEN 2
+#define	MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_DATA_OFST 6
+#define	MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_DATA_LEN 2
+#define	MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_HDR_OFST 8
+#define	MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_HDR_LEN 2
+#define	MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_DATA_OFST 10
+#define	MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_DATA_LEN 2
+#define	MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_HDR_OFST 12
+#define	MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_HDR_LEN 2
+#define	MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_DATA_OFST 14
+#define	MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_DATA_LEN 2
+
+
+/***********************************/
+/* MC_CMD_RXD_MONITOR 
+ * Get histogram of RX queue fill level.
+ */
+#define	MC_CMD_RXD_MONITOR  0x22
+
+/* MC_CMD_RXD_MONITOR_IN msgrequest */
+#define	MC_CMD_RXD_MONITOR_IN_LEN 12
+#define	MC_CMD_RXD_MONITOR_IN_QID_OFST 0
+#define	MC_CMD_RXD_MONITOR_IN_POLL_PERIOD_OFST 4
+#define	MC_CMD_RXD_MONITOR_IN_WIPE_OFST 8
+
+/* MC_CMD_RXD_MONITOR_OUT msgresponse */
+#define	MC_CMD_RXD_MONITOR_OUT_LEN 80
+#define	MC_CMD_RXD_MONITOR_OUT_QID_OFST 0
+#define	MC_CMD_RXD_MONITOR_OUT_RING_FILL_OFST 4
+#define	MC_CMD_RXD_MONITOR_OUT_CACHE_FILL_OFST 8
+#define	MC_CMD_RXD_MONITOR_OUT_RING_LT_1_OFST 12
+#define	MC_CMD_RXD_MONITOR_OUT_RING_LT_2_OFST 16
+#define	MC_CMD_RXD_MONITOR_OUT_RING_LT_4_OFST 20
+#define	MC_CMD_RXD_MONITOR_OUT_RING_LT_8_OFST 24
+#define	MC_CMD_RXD_MONITOR_OUT_RING_LT_16_OFST 28
+#define	MC_CMD_RXD_MONITOR_OUT_RING_LT_32_OFST 32
+#define	MC_CMD_RXD_MONITOR_OUT_RING_LT_64_OFST 36
+#define	MC_CMD_RXD_MONITOR_OUT_RING_LT_128_OFST 40
+#define	MC_CMD_RXD_MONITOR_OUT_RING_LT_256_OFST 44
+#define	MC_CMD_RXD_MONITOR_OUT_RING_GE_256_OFST 48
+#define	MC_CMD_RXD_MONITOR_OUT_CACHE_LT_1_OFST 52
+#define	MC_CMD_RXD_MONITOR_OUT_CACHE_LT_2_OFST 56
+#define	MC_CMD_RXD_MONITOR_OUT_CACHE_LT_4_OFST 60
+#define	MC_CMD_RXD_MONITOR_OUT_CACHE_LT_8_OFST 64
+#define	MC_CMD_RXD_MONITOR_OUT_CACHE_LT_16_OFST 68
+#define	MC_CMD_RXD_MONITOR_OUT_CACHE_LT_32_OFST 72
+#define	MC_CMD_RXD_MONITOR_OUT_CACHE_GE_32_OFST 76
+
+
+/***********************************/
+/* MC_CMD_PUTS 
+ * puts(3) implementation over MCDI
+ */
+#define	MC_CMD_PUTS  0x23
+
+/* MC_CMD_PUTS_IN msgrequest */
+#define	MC_CMD_PUTS_IN_LENMIN 13
+#define	MC_CMD_PUTS_IN_LENMAX 252
+#define	MC_CMD_PUTS_IN_LEN(num) (12+1*(num))
+#define	MC_CMD_PUTS_IN_DEST_OFST 0
+#define	MC_CMD_PUTS_IN_UART_LBN 0
+#define	MC_CMD_PUTS_IN_UART_WIDTH 1
+#define	MC_CMD_PUTS_IN_PORT_LBN 1
+#define	MC_CMD_PUTS_IN_PORT_WIDTH 1
+#define	MC_CMD_PUTS_IN_DHOST_OFST 4
+#define	MC_CMD_PUTS_IN_DHOST_LEN 6
+#define	MC_CMD_PUTS_IN_STRING_OFST 12
+#define	MC_CMD_PUTS_IN_STRING_LEN 1
+#define	MC_CMD_PUTS_IN_STRING_MINNUM 1
+#define	MC_CMD_PUTS_IN_STRING_MAXNUM 240
+
+/* MC_CMD_PUTS_OUT msgresponse */
+#define	MC_CMD_PUTS_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_PHY_CFG 
+ * Report PHY configuration.
+ */
+#define	MC_CMD_GET_PHY_CFG  0x24
+
+/* MC_CMD_GET_PHY_CFG_IN msgrequest */
+#define	MC_CMD_GET_PHY_CFG_IN_LEN 0
+
+/* MC_CMD_GET_PHY_CFG_OUT msgresponse */
+#define	MC_CMD_GET_PHY_CFG_OUT_LEN 72
+#define	MC_CMD_GET_PHY_CFG_OUT_FLAGS_OFST 0
+#define	MC_CMD_GET_PHY_CFG_OUT_PRESENT_LBN 0
+#define	MC_CMD_GET_PHY_CFG_OUT_PRESENT_WIDTH 1
+#define	MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN 1
+#define	MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_WIDTH 1
+#define	MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN 2
+#define	MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_WIDTH 1
+#define	MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN 3
+#define	MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_WIDTH 1
+#define	MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN 4
+#define	MC_CMD_GET_PHY_CFG_OUT_POWEROFF_WIDTH 1
+#define	MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN 5
+#define	MC_CMD_GET_PHY_CFG_OUT_TXDIS_WIDTH 1
+#define	MC_CMD_GET_PHY_CFG_OUT_BIST_LBN 6
+#define	MC_CMD_GET_PHY_CFG_OUT_BIST_WIDTH 1
+#define	MC_CMD_GET_PHY_CFG_OUT_TYPE_OFST 4
+#define	MC_CMD_GET_PHY_CFG_OUT_SUPPORTED_CAP_OFST 8
+#define	MC_CMD_PHY_CAP_10HDX_LBN 1
+#define	MC_CMD_PHY_CAP_10HDX_WIDTH 1
+#define	MC_CMD_PHY_CAP_10FDX_LBN 2
+#define	MC_CMD_PHY_CAP_10FDX_WIDTH 1
+#define	MC_CMD_PHY_CAP_100HDX_LBN 3
+#define	MC_CMD_PHY_CAP_100HDX_WIDTH 1
+#define	MC_CMD_PHY_CAP_100FDX_LBN 4
+#define	MC_CMD_PHY_CAP_100FDX_WIDTH 1
+#define	MC_CMD_PHY_CAP_1000HDX_LBN 5
+#define	MC_CMD_PHY_CAP_1000HDX_WIDTH 1
+#define	MC_CMD_PHY_CAP_1000FDX_LBN 6
+#define	MC_CMD_PHY_CAP_1000FDX_WIDTH 1
+#define	MC_CMD_PHY_CAP_10000FDX_LBN 7
+#define	MC_CMD_PHY_CAP_10000FDX_WIDTH 1
+#define	MC_CMD_PHY_CAP_PAUSE_LBN 8
+#define	MC_CMD_PHY_CAP_PAUSE_WIDTH 1
+#define	MC_CMD_PHY_CAP_ASYM_LBN 9
+#define	MC_CMD_PHY_CAP_ASYM_WIDTH 1
+#define	MC_CMD_PHY_CAP_AN_LBN 10
+#define	MC_CMD_PHY_CAP_AN_WIDTH 1
+#define	MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12
+#define	MC_CMD_GET_PHY_CFG_OUT_PRT_OFST 16
+#define	MC_CMD_GET_PHY_CFG_OUT_STATS_MASK_OFST 20
+#define	MC_CMD_GET_PHY_CFG_OUT_NAME_OFST 24
+#define	MC_CMD_GET_PHY_CFG_OUT_NAME_LEN 20
+#define	MC_CMD_GET_PHY_CFG_OUT_MEDIA_TYPE_OFST 44
+#define	MC_CMD_MEDIA_XAUI 0x1 /* enum */
+#define	MC_CMD_MEDIA_CX4 0x2 /* enum */
+#define	MC_CMD_MEDIA_KX4 0x3 /* enum */
+#define	MC_CMD_MEDIA_XFP 0x4 /* enum */
+#define	MC_CMD_MEDIA_SFP_PLUS 0x5 /* enum */
+#define	MC_CMD_MEDIA_BASE_T 0x6 /* enum */
+#define	MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48
+#define	MC_CMD_MMD_CLAUSE22 0x0 /* enum */
+#define	MC_CMD_MMD_CLAUSE45_PMAPMD 0x1 /* enum */
+#define	MC_CMD_MMD_CLAUSE45_WIS 0x2 /* enum */
+#define	MC_CMD_MMD_CLAUSE45_PCS 0x3 /* enum */
+#define	MC_CMD_MMD_CLAUSE45_PHYXS 0x4 /* enum */
+#define	MC_CMD_MMD_CLAUSE45_DTEXS 0x5 /* enum */
+#define	MC_CMD_MMD_CLAUSE45_TC 0x6 /* enum */
+#define	MC_CMD_MMD_CLAUSE45_AN 0x7 /* enum */
+#define	MC_CMD_MMD_CLAUSE45_C22EXT 0x1d /* enum */
+#define	MC_CMD_MMD_CLAUSE45_VEND1 0x1e /* enum */
+#define	MC_CMD_MMD_CLAUSE45_VEND2 0x1f /* enum */
+#define	MC_CMD_GET_PHY_CFG_OUT_REVISION_OFST 52
+#define	MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN 20
+
+
+/***********************************/
+/* MC_CMD_START_BIST 
+ * Start a BIST test on the PHY.
+ */
+#define	MC_CMD_START_BIST  0x25
+
+/* MC_CMD_START_BIST_IN msgrequest */
+#define	MC_CMD_START_BIST_IN_LEN 4
+#define	MC_CMD_START_BIST_IN_TYPE_OFST 0
+#define	MC_CMD_PHY_BIST_CABLE_SHORT 0x1 /* enum */
+#define	MC_CMD_PHY_BIST_CABLE_LONG 0x2 /* enum */
+#define	MC_CMD_BPX_SERDES_BIST 0x3 /* enum */
+#define	MC_CMD_MC_LOOPBACK_BIST 0x4 /* enum */
+#define	MC_CMD_PHY_BIST 0x5 /* enum */
+
+/* MC_CMD_START_BIST_OUT msgresponse */
+#define	MC_CMD_START_BIST_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_POLL_BIST 
+ * Poll for BIST completion.
+ */
+#define	MC_CMD_POLL_BIST  0x26
+
+/* MC_CMD_POLL_BIST_IN msgrequest */
+#define	MC_CMD_POLL_BIST_IN_LEN 0
+
+/* MC_CMD_POLL_BIST_OUT msgresponse */
+#define	MC_CMD_POLL_BIST_OUT_LEN 8
+#define	MC_CMD_POLL_BIST_OUT_RESULT_OFST 0
+#define	MC_CMD_POLL_BIST_RUNNING 0x1 /* enum */
+#define	MC_CMD_POLL_BIST_PASSED 0x2 /* enum */
+#define	MC_CMD_POLL_BIST_FAILED 0x3 /* enum */
+#define	MC_CMD_POLL_BIST_TIMEOUT 0x4 /* enum */
+#define	MC_CMD_POLL_BIST_OUT_PRIVATE_OFST 4
+
+/* MC_CMD_POLL_BIST_OUT_SFT9001 msgresponse */
+#define	MC_CMD_POLL_BIST_OUT_SFT9001_LEN 36
+/*            MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 */
+/*            Enum values, see field(s): */
+/*               MC_CMD_POLL_BIST_OUT/MC_CMD_POLL_BIST_OUT_RESULT */
+#define	MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A_OFST 4
+#define	MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B_OFST 8
+#define	MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C_OFST 12
+#define	MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D_OFST 16
+#define	MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_A_OFST 20
+#define	MC_CMD_POLL_BIST_SFT9001_PAIR_OK 0x1 /* enum */
+#define	MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN 0x2 /* enum */
+#define	MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT 0x3 /* enum */
+#define	MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT 0x4 /* enum */
+#define	MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY 0x9 /* enum */
+#define	MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_B_OFST 24
+/*            Enum values, see field(s): */
+/*               CABLE_STATUS_A */
+#define	MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_C_OFST 28
+/*            Enum values, see field(s): */
+/*               CABLE_STATUS_A */
+#define	MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_D_OFST 32
+/*            Enum values, see field(s): */
+/*               CABLE_STATUS_A */
+
+/* MC_CMD_POLL_BIST_OUT_MRSFP msgresponse */
+#define	MC_CMD_POLL_BIST_OUT_MRSFP_LEN 8
+/*            MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 */
+/*            Enum values, see field(s): */
+/*               MC_CMD_POLL_BIST_OUT/MC_CMD_POLL_BIST_OUT_RESULT */
+#define	MC_CMD_POLL_BIST_OUT_MRSFP_TEST_OFST 4
+#define	MC_CMD_POLL_BIST_MRSFP_TEST_COMPLETE 0x0 /* enum */
+#define	MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_WRITE 0x1 /* enum */
+#define	MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_IO_EXP 0x2 /* enum */
+#define	MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_MODULE 0x3 /* enum */
+#define	MC_CMD_POLL_BIST_MRSFP_TEST_IO_EXP_I2C_CONFIGURE 0x4 /* enum */
+#define	MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_I2C_NO_CROSSTALK 0x5 /* enum */
+#define	MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_PRESENCE 0x6 /* enum */
+#define	MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_I2C_ACCESS 0x7 /* enum */
+#define	MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_SANE_VALUE 0x8 /* enum */
+
+
+/***********************************/
+/* MC_CMD_FLUSH_RX_QUEUES 
+ * Flush receive queue(s).
+ */
+#define	MC_CMD_FLUSH_RX_QUEUES  0x27
+
+/* MC_CMD_FLUSH_RX_QUEUES_IN msgrequest */
+#define	MC_CMD_FLUSH_RX_QUEUES_IN_LENMIN 4
+#define	MC_CMD_FLUSH_RX_QUEUES_IN_LENMAX 252
+#define	MC_CMD_FLUSH_RX_QUEUES_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_OFST 0
+#define	MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_LEN 4
+#define	MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MINNUM 1
+#define	MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM 63
+
+/* MC_CMD_FLUSH_RX_QUEUES_OUT msgresponse */
+#define	MC_CMD_FLUSH_RX_QUEUES_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_LOOPBACK_MODES 
+ * Get port's loopback modes.
+ */
+#define	MC_CMD_GET_LOOPBACK_MODES  0x28
+
+/* MC_CMD_GET_LOOPBACK_MODES_IN msgrequest */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0
+
+/* MC_CMD_GET_LOOPBACK_MODES_OUT msgresponse */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_OFST 4
+#define	MC_CMD_LOOPBACK_NONE  0x0 /* enum */
+#define	MC_CMD_LOOPBACK_DATA  0x1 /* enum */
+#define	MC_CMD_LOOPBACK_GMAC  0x2 /* enum */
+#define	MC_CMD_LOOPBACK_XGMII 0x3 /* enum */
+#define	MC_CMD_LOOPBACK_XGXS  0x4 /* enum */
+#define	MC_CMD_LOOPBACK_XAUI  0x5 /* enum */
+#define	MC_CMD_LOOPBACK_GMII  0x6 /* enum */
+#define	MC_CMD_LOOPBACK_SGMII  0x7 /* enum */
+#define	MC_CMD_LOOPBACK_XGBR  0x8 /* enum */
+#define	MC_CMD_LOOPBACK_XFI  0x9 /* enum */
+#define	MC_CMD_LOOPBACK_XAUI_FAR  0xa /* enum */
+#define	MC_CMD_LOOPBACK_GMII_FAR  0xb /* enum */
+#define	MC_CMD_LOOPBACK_SGMII_FAR  0xc /* enum */
+#define	MC_CMD_LOOPBACK_XFI_FAR  0xd /* enum */
+#define	MC_CMD_LOOPBACK_GPHY  0xe /* enum */
+#define	MC_CMD_LOOPBACK_PHYXS  0xf /* enum */
+#define	MC_CMD_LOOPBACK_PCS  0x10 /* enum */
+#define	MC_CMD_LOOPBACK_PMAPMD  0x11 /* enum */
+#define	MC_CMD_LOOPBACK_XPORT  0x12 /* enum */
+#define	MC_CMD_LOOPBACK_XGMII_WS  0x13 /* enum */
+#define	MC_CMD_LOOPBACK_XAUI_WS  0x14 /* enum */
+#define	MC_CMD_LOOPBACK_XAUI_WS_FAR  0x15 /* enum */
+#define	MC_CMD_LOOPBACK_XAUI_WS_NEAR  0x16 /* enum */
+#define	MC_CMD_LOOPBACK_GMII_WS  0x17 /* enum */
+#define	MC_CMD_LOOPBACK_XFI_WS  0x18 /* enum */
+#define	MC_CMD_LOOPBACK_XFI_WS_FAR  0x19 /* enum */
+#define	MC_CMD_LOOPBACK_PHYXS_WS  0x1a /* enum */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_LO_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_OFST 12
+/*            Enum values, see field(s): */
+/*               100M */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_LO_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_OFST 20
+/*            Enum values, see field(s): */
+/*               100M */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LO_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_OFST 28
+/*            Enum values, see field(s): */
+/*               100M */
+
+
+/***********************************/
+/* MC_CMD_GET_LINK 
+ * Read the unified MAC/PHY link state.
+ */
+#define	MC_CMD_GET_LINK  0x29
+
+/* MC_CMD_GET_LINK_IN msgrequest */
+#define	MC_CMD_GET_LINK_IN_LEN 0
+
+/* MC_CMD_GET_LINK_OUT msgresponse */
+#define	MC_CMD_GET_LINK_OUT_LEN 28
+#define	MC_CMD_GET_LINK_OUT_CAP_OFST 0
+#define	MC_CMD_GET_LINK_OUT_LP_CAP_OFST 4
+#define	MC_CMD_GET_LINK_OUT_LINK_SPEED_OFST 8
+#define	MC_CMD_GET_LINK_OUT_LOOPBACK_MODE_OFST 12
+/*            Enum values, see field(s): */
+/*               MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */
+#define	MC_CMD_GET_LINK_OUT_FLAGS_OFST 16
+#define	MC_CMD_GET_LINK_OUT_LINK_UP_LBN 0
+#define	MC_CMD_GET_LINK_OUT_LINK_UP_WIDTH 1
+#define	MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN 1
+#define	MC_CMD_GET_LINK_OUT_FULL_DUPLEX_WIDTH 1
+#define	MC_CMD_GET_LINK_OUT_BPX_LINK_LBN 2
+#define	MC_CMD_GET_LINK_OUT_BPX_LINK_WIDTH 1
+#define	MC_CMD_GET_LINK_OUT_PHY_LINK_LBN 3
+#define	MC_CMD_GET_LINK_OUT_PHY_LINK_WIDTH 1
+#define	MC_CMD_GET_LINK_OUT_FCNTL_OFST 20
+#define	MC_CMD_FCNTL_OFF 0x0 /* enum */
+#define	MC_CMD_FCNTL_RESPOND 0x1 /* enum */
+#define	MC_CMD_FCNTL_BIDIR 0x2 /* enum */
+#define	MC_CMD_GET_LINK_OUT_MAC_FAULT_OFST 24
+#define	MC_CMD_MAC_FAULT_XGMII_LOCAL_LBN 0
+#define	MC_CMD_MAC_FAULT_XGMII_LOCAL_WIDTH 1
+#define	MC_CMD_MAC_FAULT_XGMII_REMOTE_LBN 1
+#define	MC_CMD_MAC_FAULT_XGMII_REMOTE_WIDTH 1
+#define	MC_CMD_MAC_FAULT_SGMII_REMOTE_LBN 2
+#define	MC_CMD_MAC_FAULT_SGMII_REMOTE_WIDTH 1
+#define	MC_CMD_MAC_FAULT_PENDING_RECONFIG_LBN 3
+#define	MC_CMD_MAC_FAULT_PENDING_RECONFIG_WIDTH 1
+
+
+/***********************************/
+/* MC_CMD_SET_LINK 
+ * Write the unified MAC/PHY link configuration.
+ */
+#define	MC_CMD_SET_LINK  0x2a
+
+/* MC_CMD_SET_LINK_IN msgrequest */
+#define	MC_CMD_SET_LINK_IN_LEN 16
+#define	MC_CMD_SET_LINK_IN_CAP_OFST 0
+#define	MC_CMD_SET_LINK_IN_FLAGS_OFST 4
+#define	MC_CMD_SET_LINK_IN_LOWPOWER_LBN 0
+#define	MC_CMD_SET_LINK_IN_LOWPOWER_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_POWEROFF_LBN 1
+#define	MC_CMD_SET_LINK_IN_POWEROFF_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_TXDIS_LBN 2
+#define	MC_CMD_SET_LINK_IN_TXDIS_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_LOOPBACK_MODE_OFST 8
+/*            Enum values, see field(s): */
+/*               MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */
+#define	MC_CMD_SET_LINK_IN_LOOPBACK_SPEED_OFST 12
+
+/* MC_CMD_SET_LINK_OUT msgresponse */
+#define	MC_CMD_SET_LINK_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SET_ID_LED 
+ * Set indentification LED state.
+ */
+#define	MC_CMD_SET_ID_LED  0x2b
+
+/* MC_CMD_SET_ID_LED_IN msgrequest */
+#define	MC_CMD_SET_ID_LED_IN_LEN 4
+#define	MC_CMD_SET_ID_LED_IN_STATE_OFST 0
+#define	MC_CMD_LED_OFF  0x0 /* enum */
+#define	MC_CMD_LED_ON  0x1 /* enum */
+#define	MC_CMD_LED_DEFAULT  0x2 /* enum */
+
+/* MC_CMD_SET_ID_LED_OUT msgresponse */
+#define	MC_CMD_SET_ID_LED_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SET_MAC 
+ * Set MAC configuration.
+ */
+#define	MC_CMD_SET_MAC  0x2c
+
+/* MC_CMD_SET_MAC_IN msgrequest */
+#define	MC_CMD_SET_MAC_IN_LEN 24
+#define	MC_CMD_SET_MAC_IN_MTU_OFST 0
+#define	MC_CMD_SET_MAC_IN_DRAIN_OFST 4
+#define	MC_CMD_SET_MAC_IN_ADDR_OFST 8
+#define	MC_CMD_SET_MAC_IN_ADDR_LEN 8
+#define	MC_CMD_SET_MAC_IN_ADDR_LO_OFST 8
+#define	MC_CMD_SET_MAC_IN_ADDR_HI_OFST 12
+#define	MC_CMD_SET_MAC_IN_REJECT_OFST 16
+#define	MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN 0
+#define	MC_CMD_SET_MAC_IN_REJECT_UNCST_WIDTH 1
+#define	MC_CMD_SET_MAC_IN_REJECT_BRDCST_LBN 1
+#define	MC_CMD_SET_MAC_IN_REJECT_BRDCST_WIDTH 1
+#define	MC_CMD_SET_MAC_IN_FCNTL_OFST 20
+/*               MC_CMD_FCNTL_OFF 0x0 */
+/*               MC_CMD_FCNTL_RESPOND 0x1 */
+/*               MC_CMD_FCNTL_BIDIR 0x2 */
+#define	MC_CMD_FCNTL_AUTO 0x3 /* enum */
+
+/* MC_CMD_SET_MAC_OUT msgresponse */
+#define	MC_CMD_SET_MAC_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_PHY_STATS 
+ * Get generic PHY statistics.
+ */
+#define	MC_CMD_PHY_STATS  0x2d
+
+/* MC_CMD_PHY_STATS_IN msgrequest */
+#define	MC_CMD_PHY_STATS_IN_LEN 8
+#define	MC_CMD_PHY_STATS_IN_DMA_ADDR_OFST 0
+#define	MC_CMD_PHY_STATS_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_PHY_STATS_IN_DMA_ADDR_LO_OFST 0
+#define	MC_CMD_PHY_STATS_IN_DMA_ADDR_HI_OFST 4
+
+/* MC_CMD_PHY_STATS_OUT_DMA msgresponse */
+#define	MC_CMD_PHY_STATS_OUT_DMA_LEN 0
+
+/* MC_CMD_PHY_STATS_OUT_NO_DMA msgresponse */
+#define	MC_CMD_PHY_STATS_OUT_NO_DMA_LEN (((MC_CMD_PHY_NSTATS*32))>>3)
+#define	MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_OFST 0
+#define	MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_LEN 4
+#define	MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_PHY_NSTATS
+#define	MC_CMD_OUI  0x0 /* enum */
+#define	MC_CMD_PMA_PMD_LINK_UP  0x1 /* enum */
+#define	MC_CMD_PMA_PMD_RX_FAULT  0x2 /* enum */
+#define	MC_CMD_PMA_PMD_TX_FAULT  0x3 /* enum */
+#define	MC_CMD_PMA_PMD_SIGNAL  0x4 /* enum */
+#define	MC_CMD_PMA_PMD_SNR_A  0x5 /* enum */
+#define	MC_CMD_PMA_PMD_SNR_B  0x6 /* enum */
+#define	MC_CMD_PMA_PMD_SNR_C  0x7 /* enum */
+#define	MC_CMD_PMA_PMD_SNR_D  0x8 /* enum */
+#define	MC_CMD_PCS_LINK_UP  0x9 /* enum */
+#define	MC_CMD_PCS_RX_FAULT  0xa /* enum */
+#define	MC_CMD_PCS_TX_FAULT  0xb /* enum */
+#define	MC_CMD_PCS_BER  0xc /* enum */
+#define	MC_CMD_PCS_BLOCK_ERRORS  0xd /* enum */
+#define	MC_CMD_PHYXS_LINK_UP  0xe /* enum */
+#define	MC_CMD_PHYXS_RX_FAULT  0xf /* enum */
+#define	MC_CMD_PHYXS_TX_FAULT  0x10 /* enum */
+#define	MC_CMD_PHYXS_ALIGN  0x11 /* enum */
+#define	MC_CMD_PHYXS_SYNC  0x12 /* enum */
+#define	MC_CMD_AN_LINK_UP  0x13 /* enum */
+#define	MC_CMD_AN_COMPLETE  0x14 /* enum */
+#define	MC_CMD_AN_10GBT_STATUS  0x15 /* enum */
+#define	MC_CMD_CL22_LINK_UP  0x16 /* enum */
+#define	MC_CMD_PHY_NSTATS  0x17 /* enum */
+
+
+/***********************************/
+/* MC_CMD_MAC_STATS 
+ * Get generic MAC statistics.
+ */
+#define	MC_CMD_MAC_STATS  0x2e
+
+/* MC_CMD_MAC_STATS_IN msgrequest */
+#define	MC_CMD_MAC_STATS_IN_LEN 16
+#define	MC_CMD_MAC_STATS_IN_DMA_ADDR_OFST 0
+#define	MC_CMD_MAC_STATS_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_MAC_STATS_IN_DMA_ADDR_LO_OFST 0
+#define	MC_CMD_MAC_STATS_IN_DMA_ADDR_HI_OFST 4
+#define	MC_CMD_MAC_STATS_IN_CMD_OFST 8
+#define	MC_CMD_MAC_STATS_IN_DMA_LBN 0
+#define	MC_CMD_MAC_STATS_IN_DMA_WIDTH 1
+#define	MC_CMD_MAC_STATS_IN_CLEAR_LBN 1
+#define	MC_CMD_MAC_STATS_IN_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE_LBN 2
+#define	MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE_WIDTH 1
+#define	MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE_LBN 3
+#define	MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE_WIDTH 1
+#define	MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR_LBN 4
+#define	MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT_LBN 5
+#define	MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT_WIDTH 1
+#define	MC_CMD_MAC_STATS_IN_PERIOD_MS_LBN 16
+#define	MC_CMD_MAC_STATS_IN_PERIOD_MS_WIDTH 16
+#define	MC_CMD_MAC_STATS_IN_DMA_LEN_OFST 12
+
+/* MC_CMD_MAC_STATS_OUT_DMA msgresponse */
+#define	MC_CMD_MAC_STATS_OUT_DMA_LEN 0
+
+/* MC_CMD_MAC_STATS_OUT_NO_DMA msgresponse */
+#define	MC_CMD_MAC_STATS_OUT_NO_DMA_LEN (((MC_CMD_MAC_NSTATS*64))>>3)
+#define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_OFST 0
+#define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_LEN 8
+#define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_LO_OFST 0
+#define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_OFST 4
+#define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS
+#define	MC_CMD_MAC_GENERATION_START  0x0 /* enum */
+#define	MC_CMD_MAC_TX_PKTS  0x1 /* enum */
+#define	MC_CMD_MAC_TX_PAUSE_PKTS  0x2 /* enum */
+#define	MC_CMD_MAC_TX_CONTROL_PKTS  0x3 /* enum */
+#define	MC_CMD_MAC_TX_UNICAST_PKTS  0x4 /* enum */
+#define	MC_CMD_MAC_TX_MULTICAST_PKTS  0x5 /* enum */
+#define	MC_CMD_MAC_TX_BROADCAST_PKTS  0x6 /* enum */
+#define	MC_CMD_MAC_TX_BYTES  0x7 /* enum */
+#define	MC_CMD_MAC_TX_BAD_BYTES  0x8 /* enum */
+#define	MC_CMD_MAC_TX_LT64_PKTS  0x9 /* enum */
+#define	MC_CMD_MAC_TX_64_PKTS  0xa /* enum */
+#define	MC_CMD_MAC_TX_65_TO_127_PKTS  0xb /* enum */
+#define	MC_CMD_MAC_TX_128_TO_255_PKTS  0xc /* enum */
+#define	MC_CMD_MAC_TX_256_TO_511_PKTS  0xd /* enum */
+#define	MC_CMD_MAC_TX_512_TO_1023_PKTS  0xe /* enum */
+#define	MC_CMD_MAC_TX_1024_TO_15XX_PKTS  0xf /* enum */
+#define	MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS  0x10 /* enum */
+#define	MC_CMD_MAC_TX_GTJUMBO_PKTS  0x11 /* enum */
+#define	MC_CMD_MAC_TX_BAD_FCS_PKTS  0x12 /* enum */
+#define	MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS  0x13 /* enum */
+#define	MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS  0x14 /* enum */
+#define	MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS  0x15 /* enum */
+#define	MC_CMD_MAC_TX_LATE_COLLISION_PKTS  0x16 /* enum */
+#define	MC_CMD_MAC_TX_DEFERRED_PKTS  0x17 /* enum */
+#define	MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS  0x18 /* enum */
+#define	MC_CMD_MAC_TX_NON_TCPUDP_PKTS  0x19 /* enum */
+#define	MC_CMD_MAC_TX_MAC_SRC_ERR_PKTS  0x1a /* enum */
+#define	MC_CMD_MAC_TX_IP_SRC_ERR_PKTS  0x1b /* enum */
+#define	MC_CMD_MAC_RX_PKTS  0x1c /* enum */
+#define	MC_CMD_MAC_RX_PAUSE_PKTS  0x1d /* enum */
+#define	MC_CMD_MAC_RX_GOOD_PKTS  0x1e /* enum */
+#define	MC_CMD_MAC_RX_CONTROL_PKTS  0x1f /* enum */
+#define	MC_CMD_MAC_RX_UNICAST_PKTS  0x20 /* enum */
+#define	MC_CMD_MAC_RX_MULTICAST_PKTS  0x21 /* enum */
+#define	MC_CMD_MAC_RX_BROADCAST_PKTS  0x22 /* enum */
+#define	MC_CMD_MAC_RX_BYTES  0x23 /* enum */
+#define	MC_CMD_MAC_RX_BAD_BYTES  0x24 /* enum */
+#define	MC_CMD_MAC_RX_64_PKTS  0x25 /* enum */
+#define	MC_CMD_MAC_RX_65_TO_127_PKTS  0x26 /* enum */
+#define	MC_CMD_MAC_RX_128_TO_255_PKTS  0x27 /* enum */
+#define	MC_CMD_MAC_RX_256_TO_511_PKTS  0x28 /* enum */
+#define	MC_CMD_MAC_RX_512_TO_1023_PKTS  0x29 /* enum */
+#define	MC_CMD_MAC_RX_1024_TO_15XX_PKTS  0x2a /* enum */
+#define	MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS  0x2b /* enum */
+#define	MC_CMD_MAC_RX_GTJUMBO_PKTS  0x2c /* enum */
+#define	MC_CMD_MAC_RX_UNDERSIZE_PKTS  0x2d /* enum */
+#define	MC_CMD_MAC_RX_BAD_FCS_PKTS  0x2e /* enum */
+#define	MC_CMD_MAC_RX_OVERFLOW_PKTS  0x2f /* enum */
+#define	MC_CMD_MAC_RX_FALSE_CARRIER_PKTS  0x30 /* enum */
+#define	MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS  0x31 /* enum */
+#define	MC_CMD_MAC_RX_ALIGN_ERROR_PKTS  0x32 /* enum */
+#define	MC_CMD_MAC_RX_LENGTH_ERROR_PKTS  0x33 /* enum */
+#define	MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS  0x34 /* enum */
+#define	MC_CMD_MAC_RX_JABBER_PKTS  0x35 /* enum */
+#define	MC_CMD_MAC_RX_NODESC_DROPS  0x36 /* enum */
+#define	MC_CMD_MAC_RX_LANES01_CHAR_ERR  0x37 /* enum */
+#define	MC_CMD_MAC_RX_LANES23_CHAR_ERR  0x38 /* enum */
+#define	MC_CMD_MAC_RX_LANES01_DISP_ERR  0x39 /* enum */
+#define	MC_CMD_MAC_RX_LANES23_DISP_ERR  0x3a /* enum */
+#define	MC_CMD_MAC_RX_MATCH_FAULT  0x3b /* enum */
+#define	MC_CMD_GMAC_DMABUF_START  0x40 /* enum */
+#define	MC_CMD_GMAC_DMABUF_END    0x5f /* enum */
+#define	MC_CMD_MAC_GENERATION_END 0x60 /* enum */
+#define	MC_CMD_MAC_NSTATS  0x61 /* enum */
+
+
+/***********************************/
+/* MC_CMD_SRIOV 
+ * to be documented
+ */
+#define	MC_CMD_SRIOV  0x30
+
+/* MC_CMD_SRIOV_IN msgrequest */
+#define	MC_CMD_SRIOV_IN_LEN 12
+#define	MC_CMD_SRIOV_IN_ENABLE_OFST 0
+#define	MC_CMD_SRIOV_IN_VI_BASE_OFST 4
+#define	MC_CMD_SRIOV_IN_VF_COUNT_OFST 8
+
+/* MC_CMD_SRIOV_OUT msgresponse */
+#define	MC_CMD_SRIOV_OUT_LEN 8
+#define	MC_CMD_SRIOV_OUT_VI_SCALE_OFST 0
+#define	MC_CMD_SRIOV_OUT_VF_TOTAL_OFST 4
+
+/* MC_CMD_MEMCPY_RECORD_TYPEDEF structuredef */
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_LEN 32
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_OFST 0
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_LBN 0
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_WIDTH 32
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_OFST 4
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_LBN 32
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_WIDTH 32
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_OFST 8
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LEN 8
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LO_OFST 8
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_HI_OFST 12
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LBN 64
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_WIDTH 64
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_OFST 16
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_RID_INLINE 0x100 /* enum */
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_LBN 128
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_WIDTH 32
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_OFST 20
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LEN 8
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LO_OFST 20
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_HI_OFST 24
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LBN 160
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_WIDTH 64
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_OFST 28
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_LBN 224
+#define	MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_MEMCPY 
+ * Perform memory copy operation.
+ */
+#define	MC_CMD_MEMCPY  0x31
+
+/* MC_CMD_MEMCPY_IN msgrequest */
+#define	MC_CMD_MEMCPY_IN_LENMIN 32
+#define	MC_CMD_MEMCPY_IN_LENMAX 224
+#define	MC_CMD_MEMCPY_IN_LEN(num) (0+32*(num))
+#define	MC_CMD_MEMCPY_IN_RECORD_OFST 0
+#define	MC_CMD_MEMCPY_IN_RECORD_LEN 32
+#define	MC_CMD_MEMCPY_IN_RECORD_MINNUM 1
+#define	MC_CMD_MEMCPY_IN_RECORD_MAXNUM 7
+
+/* MC_CMD_MEMCPY_OUT msgresponse */
+#define	MC_CMD_MEMCPY_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_WOL_FILTER_SET 
+ * Set a WoL filter.
+ */
+#define	MC_CMD_WOL_FILTER_SET  0x32
+
+/* MC_CMD_WOL_FILTER_SET_IN msgrequest */
+#define	MC_CMD_WOL_FILTER_SET_IN_LEN 192
+#define	MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0
+#define	MC_CMD_FILTER_MODE_SIMPLE    0x0 /* enum */
+#define	MC_CMD_FILTER_MODE_STRUCTURED 0xffffffff /* enum */
+#define	MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4
+#define	MC_CMD_WOL_TYPE_MAGIC      0x0 /* enum */
+#define	MC_CMD_WOL_TYPE_WIN_MAGIC 0x2 /* enum */
+#define	MC_CMD_WOL_TYPE_IPV4_SYN   0x3 /* enum */
+#define	MC_CMD_WOL_TYPE_IPV6_SYN   0x4 /* enum */
+#define	MC_CMD_WOL_TYPE_BITMAP     0x5 /* enum */
+#define	MC_CMD_WOL_TYPE_LINK       0x6 /* enum */
+#define	MC_CMD_WOL_TYPE_MAX        0x7 /* enum */
+#define	MC_CMD_WOL_FILTER_SET_IN_DATA_OFST 8
+#define	MC_CMD_WOL_FILTER_SET_IN_DATA_LEN 4
+#define	MC_CMD_WOL_FILTER_SET_IN_DATA_NUM 46
+
+/* MC_CMD_WOL_FILTER_SET_IN_MAGIC msgrequest */
+#define	MC_CMD_WOL_FILTER_SET_IN_MAGIC_LEN 16
+/*            MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/*            MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define	MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_OFST 8
+#define	MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_LEN 8
+#define	MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_LO_OFST 8
+#define	MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_HI_OFST 12
+
+/* MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN msgrequest */
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_LEN 20
+/*            MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/*            MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_IP_OFST 8
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_IP_OFST 12
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_OFST 16
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_LEN 2
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_OFST 18
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_LEN 2
+
+/* MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN msgrequest */
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_LEN 44
+/*            MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/*            MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_OFST 8
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_LEN 16
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_OFST 24
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_LEN 16
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_OFST 40
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_LEN 2
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_OFST 42
+#define	MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_LEN 2
+
+/* MC_CMD_WOL_FILTER_SET_IN_BITMAP msgrequest */
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN 187
+/*            MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/*            MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_OFST 8
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_LEN 48
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_BITMAP_OFST 56
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_BITMAP_LEN 128
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_OFST 184
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_LEN 1
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_OFST 185
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_LEN 1
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_OFST 186
+#define	MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_LEN 1
+
+/* MC_CMD_WOL_FILTER_SET_IN_LINK msgrequest */
+#define	MC_CMD_WOL_FILTER_SET_IN_LINK_LEN 12
+/*            MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/*            MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define	MC_CMD_WOL_FILTER_SET_IN_LINK_MASK_OFST 8
+#define	MC_CMD_WOL_FILTER_SET_IN_LINK_UP_LBN 0
+#define	MC_CMD_WOL_FILTER_SET_IN_LINK_UP_WIDTH 1
+#define	MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_LBN 1
+#define	MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_WIDTH 1
+
+/* MC_CMD_WOL_FILTER_SET_OUT msgresponse */
+#define	MC_CMD_WOL_FILTER_SET_OUT_LEN 4
+#define	MC_CMD_WOL_FILTER_SET_OUT_FILTER_ID_OFST 0
+
+
+/***********************************/
+/* MC_CMD_WOL_FILTER_REMOVE 
+ * Remove a WoL filter.
+ */
+#define	MC_CMD_WOL_FILTER_REMOVE  0x33
+
+/* MC_CMD_WOL_FILTER_REMOVE_IN msgrequest */
+#define	MC_CMD_WOL_FILTER_REMOVE_IN_LEN 4
+#define	MC_CMD_WOL_FILTER_REMOVE_IN_FILTER_ID_OFST 0
+
+/* MC_CMD_WOL_FILTER_REMOVE_OUT msgresponse */
+#define	MC_CMD_WOL_FILTER_REMOVE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_WOL_FILTER_RESET 
+ * Reset (i.e. remove all) WoL filters.
+ */
+#define	MC_CMD_WOL_FILTER_RESET  0x34
+
+/* MC_CMD_WOL_FILTER_RESET_IN msgrequest */
+#define	MC_CMD_WOL_FILTER_RESET_IN_LEN 4
+#define	MC_CMD_WOL_FILTER_RESET_IN_MASK_OFST 0
+#define	MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS 0x1 /* enum */
+#define	MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS 0x2 /* enum */
+
+/* MC_CMD_WOL_FILTER_RESET_OUT msgresponse */
+#define	MC_CMD_WOL_FILTER_RESET_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SET_MCAST_HASH 
+ * Set the MCASH hash value.
+ */
+#define	MC_CMD_SET_MCAST_HASH  0x35
+
+/* MC_CMD_SET_MCAST_HASH_IN msgrequest */
+#define	MC_CMD_SET_MCAST_HASH_IN_LEN 32
+#define	MC_CMD_SET_MCAST_HASH_IN_HASH0_OFST 0
+#define	MC_CMD_SET_MCAST_HASH_IN_HASH0_LEN 16
+#define	MC_CMD_SET_MCAST_HASH_IN_HASH1_OFST 16
+#define	MC_CMD_SET_MCAST_HASH_IN_HASH1_LEN 16
+
+/* MC_CMD_SET_MCAST_HASH_OUT msgresponse */
+#define	MC_CMD_SET_MCAST_HASH_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_NVRAM_TYPES 
+ * Get virtual NVRAM partitions information.
+ */
+#define	MC_CMD_NVRAM_TYPES  0x36
+
+/* MC_CMD_NVRAM_TYPES_IN msgrequest */
+#define	MC_CMD_NVRAM_TYPES_IN_LEN 0
+
+/* MC_CMD_NVRAM_TYPES_OUT msgresponse */
+#define	MC_CMD_NVRAM_TYPES_OUT_LEN 4
+#define	MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0
+#define	MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0x0 /* enum */
+#define	MC_CMD_NVRAM_TYPE_MC_FW 0x1 /* enum */
+#define	MC_CMD_NVRAM_TYPE_MC_FW_BACKUP 0x2 /* enum */
+#define	MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 0x3 /* enum */
+#define	MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1 0x4 /* enum */
+#define	MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 0x5 /* enum */
+#define	MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1 0x6 /* enum */
+#define	MC_CMD_NVRAM_TYPE_EXP_ROM 0x7 /* enum */
+#define	MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0 0x8 /* enum */
+#define	MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1 0x9 /* enum */
+#define	MC_CMD_NVRAM_TYPE_PHY_PORT0 0xa /* enum */
+#define	MC_CMD_NVRAM_TYPE_PHY_PORT1 0xb /* enum */
+#define	MC_CMD_NVRAM_TYPE_LOG 0xc /* enum */
+#define	MC_CMD_NVRAM_TYPE_FPGA 0xd /* enum */
+
+
+/***********************************/
+/* MC_CMD_NVRAM_INFO 
+ * Read info about a virtual NVRAM partition.
+ */
+#define	MC_CMD_NVRAM_INFO  0x37
+
+/* MC_CMD_NVRAM_INFO_IN msgrequest */
+#define	MC_CMD_NVRAM_INFO_IN_LEN 4
+#define	MC_CMD_NVRAM_INFO_IN_TYPE_OFST 0
+/*            Enum values, see field(s): */
+/*               MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+
+/* MC_CMD_NVRAM_INFO_OUT msgresponse */
+#define	MC_CMD_NVRAM_INFO_OUT_LEN 24
+#define	MC_CMD_NVRAM_INFO_OUT_TYPE_OFST 0
+/*            Enum values, see field(s): */
+/*               MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define	MC_CMD_NVRAM_INFO_OUT_SIZE_OFST 4
+#define	MC_CMD_NVRAM_INFO_OUT_ERASESIZE_OFST 8
+#define	MC_CMD_NVRAM_INFO_OUT_FLAGS_OFST 12
+#define	MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN 0
+#define	MC_CMD_NVRAM_INFO_OUT_PROTECTED_WIDTH 1
+#define	MC_CMD_NVRAM_INFO_OUT_PHYSDEV_OFST 16
+#define	MC_CMD_NVRAM_INFO_OUT_PHYSADDR_OFST 20
+
+
+/***********************************/
+/* MC_CMD_NVRAM_UPDATE_START 
+ * Start a group of update operations on a virtual NVRAM partition.
+ */
+#define	MC_CMD_NVRAM_UPDATE_START  0x38
+
+/* MC_CMD_NVRAM_UPDATE_START_IN msgrequest */
+#define	MC_CMD_NVRAM_UPDATE_START_IN_LEN 4
+#define	MC_CMD_NVRAM_UPDATE_START_IN_TYPE_OFST 0
+/*            Enum values, see field(s): */
+/*               MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+
+/* MC_CMD_NVRAM_UPDATE_START_OUT msgresponse */
+#define	MC_CMD_NVRAM_UPDATE_START_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_NVRAM_READ 
+ * Read data from a virtual NVRAM partition.
+ */
+#define	MC_CMD_NVRAM_READ  0x39
+
+/* MC_CMD_NVRAM_READ_IN msgrequest */
+#define	MC_CMD_NVRAM_READ_IN_LEN 12
+#define	MC_CMD_NVRAM_READ_IN_TYPE_OFST 0
+/*            Enum values, see field(s): */
+/*               MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define	MC_CMD_NVRAM_READ_IN_OFFSET_OFST 4
+#define	MC_CMD_NVRAM_READ_IN_LENGTH_OFST 8
+
+/* MC_CMD_NVRAM_READ_OUT msgresponse */
+#define	MC_CMD_NVRAM_READ_OUT_LENMIN 1
+#define	MC_CMD_NVRAM_READ_OUT_LENMAX 252
+#define	MC_CMD_NVRAM_READ_OUT_LEN(num) (0+1*(num))
+#define	MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0
+#define	MC_CMD_NVRAM_READ_OUT_READ_BUFFER_LEN 1
+#define	MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MINNUM 1
+#define	MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MAXNUM 252
+
+
+/***********************************/
+/* MC_CMD_NVRAM_WRITE 
+ * Write data to a virtual NVRAM partition.
+ */
+#define	MC_CMD_NVRAM_WRITE  0x3a
+
+/* MC_CMD_NVRAM_WRITE_IN msgrequest */
+#define	MC_CMD_NVRAM_WRITE_IN_LENMIN 13
+#define	MC_CMD_NVRAM_WRITE_IN_LENMAX 252
+#define	MC_CMD_NVRAM_WRITE_IN_LEN(num) (12+1*(num))
+#define	MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0
+/*            Enum values, see field(s): */
+/*               MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define	MC_CMD_NVRAM_WRITE_IN_OFFSET_OFST 4
+#define	MC_CMD_NVRAM_WRITE_IN_LENGTH_OFST 8
+#define	MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12
+#define	MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN 1
+#define	MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MINNUM 1
+#define	MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM 240
+
+/* MC_CMD_NVRAM_WRITE_OUT msgresponse */
+#define	MC_CMD_NVRAM_WRITE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_NVRAM_ERASE 
+ * Erase sector(s) from a virtual NVRAM partition.
+ */
+#define	MC_CMD_NVRAM_ERASE  0x3b
+
+/* MC_CMD_NVRAM_ERASE_IN msgrequest */
+#define	MC_CMD_NVRAM_ERASE_IN_LEN 12
+#define	MC_CMD_NVRAM_ERASE_IN_TYPE_OFST 0
+/*            Enum values, see field(s): */
+/*               MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define	MC_CMD_NVRAM_ERASE_IN_OFFSET_OFST 4
+#define	MC_CMD_NVRAM_ERASE_IN_LENGTH_OFST 8
+
+/* MC_CMD_NVRAM_ERASE_OUT msgresponse */
+#define	MC_CMD_NVRAM_ERASE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_NVRAM_UPDATE_FINISH 
+ * Finish a group of update operations on a virtual NVRAM partition.
+ */
+#define	MC_CMD_NVRAM_UPDATE_FINISH  0x3c
+
+/* MC_CMD_NVRAM_UPDATE_FINISH_IN msgrequest */
+#define	MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 8
+#define	MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0
+/*            Enum values, see field(s): */
+/*               MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define	MC_CMD_NVRAM_UPDATE_FINISH_IN_REBOOT_OFST 4
+
+/* MC_CMD_NVRAM_UPDATE_FINISH_OUT msgresponse */
+#define	MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_REBOOT 
+ * Reboot the MC.
+ */
+#define	MC_CMD_REBOOT  0x3d
+
+/* MC_CMD_REBOOT_IN msgrequest */
+#define	MC_CMD_REBOOT_IN_LEN 4
+#define	MC_CMD_REBOOT_IN_FLAGS_OFST 0
+#define	MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION 0x1 /* enum */
+
+/* MC_CMD_REBOOT_OUT msgresponse */
+#define	MC_CMD_REBOOT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SCHEDINFO 
+ * Request scheduler info.
+ */
+#define	MC_CMD_SCHEDINFO  0x3e
+
+/* MC_CMD_SCHEDINFO_IN msgrequest */
+#define	MC_CMD_SCHEDINFO_IN_LEN 0
+
+/* MC_CMD_SCHEDINFO_OUT msgresponse */
+#define	MC_CMD_SCHEDINFO_OUT_LENMIN 4
+#define	MC_CMD_SCHEDINFO_OUT_LENMAX 252
+#define	MC_CMD_SCHEDINFO_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_SCHEDINFO_OUT_DATA_OFST 0
+#define	MC_CMD_SCHEDINFO_OUT_DATA_LEN 4
+#define	MC_CMD_SCHEDINFO_OUT_DATA_MINNUM 1
+#define	MC_CMD_SCHEDINFO_OUT_DATA_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_REBOOT_MODE 
+ */
+#define	MC_CMD_REBOOT_MODE  0x3f
+
+/* MC_CMD_REBOOT_MODE_IN msgrequest */
+#define	MC_CMD_REBOOT_MODE_IN_LEN 4
+#define	MC_CMD_REBOOT_MODE_IN_VALUE_OFST 0
+#define	MC_CMD_REBOOT_MODE_NORMAL 0x0 /* enum */
+#define	MC_CMD_REBOOT_MODE_SNAPPER 0x3 /* enum */
+
+/* MC_CMD_REBOOT_MODE_OUT msgresponse */
+#define	MC_CMD_REBOOT_MODE_OUT_LEN 4
+#define	MC_CMD_REBOOT_MODE_OUT_VALUE_OFST 0
+
+
+/***********************************/
+/* MC_CMD_SENSOR_INFO 
+ * Returns information about every available sensor.
+ */
+#define	MC_CMD_SENSOR_INFO  0x41
+
+/* MC_CMD_SENSOR_INFO_IN msgrequest */
+#define	MC_CMD_SENSOR_INFO_IN_LEN 0
+
+/* MC_CMD_SENSOR_INFO_OUT msgresponse */
+#define	MC_CMD_SENSOR_INFO_OUT_LENMIN 12
+#define	MC_CMD_SENSOR_INFO_OUT_LENMAX 252
+#define	MC_CMD_SENSOR_INFO_OUT_LEN(num) (4+8*(num))
+#define	MC_CMD_SENSOR_INFO_OUT_MASK_OFST 0
+#define	MC_CMD_SENSOR_CONTROLLER_TEMP  0x0 /* enum */
+#define	MC_CMD_SENSOR_PHY_COMMON_TEMP  0x1 /* enum */
+#define	MC_CMD_SENSOR_CONTROLLER_COOLING  0x2 /* enum */
+#define	MC_CMD_SENSOR_PHY0_TEMP  0x3 /* enum */
+#define	MC_CMD_SENSOR_PHY0_COOLING  0x4 /* enum */
+#define	MC_CMD_SENSOR_PHY1_TEMP  0x5 /* enum */
+#define	MC_CMD_SENSOR_PHY1_COOLING  0x6 /* enum */
+#define	MC_CMD_SENSOR_IN_1V0  0x7 /* enum */
+#define	MC_CMD_SENSOR_IN_1V2  0x8 /* enum */
+#define	MC_CMD_SENSOR_IN_1V8  0x9 /* enum */
+#define	MC_CMD_SENSOR_IN_2V5  0xa /* enum */
+#define	MC_CMD_SENSOR_IN_3V3  0xb /* enum */
+#define	MC_CMD_SENSOR_IN_12V0  0xc /* enum */
+#define	MC_CMD_SENSOR_IN_1V2A  0xd /* enum */
+#define	MC_CMD_SENSOR_IN_VREF  0xe /* enum */
+#define	MC_CMD_SENSOR_ENTRY_OFST 4
+#define	MC_CMD_SENSOR_ENTRY_LEN 8
+#define	MC_CMD_SENSOR_ENTRY_LO_OFST 4
+#define	MC_CMD_SENSOR_ENTRY_HI_OFST 8
+#define	MC_CMD_SENSOR_ENTRY_MINNUM 1
+#define	MC_CMD_SENSOR_ENTRY_MAXNUM 31
+
+/* MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF structuredef */
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_LEN 8
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_OFST 0
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_LEN 2
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_LBN 0
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_WIDTH 16
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_OFST 2
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_LEN 2
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_LBN 16
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_WIDTH 16
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_OFST 4
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_LEN 2
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_LBN 32
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_WIDTH 16
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_OFST 6
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_LEN 2
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_LBN 48
+#define	MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_WIDTH 16
+
+
+/***********************************/
+/* MC_CMD_READ_SENSORS 
+ * Returns the current reading from each sensor.
+ */
+#define	MC_CMD_READ_SENSORS  0x42
+
+/* MC_CMD_READ_SENSORS_IN msgrequest */
+#define	MC_CMD_READ_SENSORS_IN_LEN 8
+#define	MC_CMD_READ_SENSORS_IN_DMA_ADDR_OFST 0
+#define	MC_CMD_READ_SENSORS_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_READ_SENSORS_IN_DMA_ADDR_LO_OFST 0
+#define	MC_CMD_READ_SENSORS_IN_DMA_ADDR_HI_OFST 4
+
+/* MC_CMD_READ_SENSORS_OUT msgresponse */
+#define	MC_CMD_READ_SENSORS_OUT_LEN 0
+
+/* MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF structuredef */
+#define	MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_LEN 3
+#define	MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_OFST 0
+#define	MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_LEN 2
+#define	MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_LBN 0
+#define	MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_WIDTH 16
+#define	MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_OFST 2
+#define	MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_LEN 1
+#define	MC_CMD_SENSOR_STATE_OK  0x0 /* enum */
+#define	MC_CMD_SENSOR_STATE_WARNING  0x1 /* enum */
+#define	MC_CMD_SENSOR_STATE_FATAL  0x2 /* enum */
+#define	MC_CMD_SENSOR_STATE_BROKEN  0x3 /* enum */
+#define	MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_LBN 16
+#define	MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_WIDTH 8
+
+
+/***********************************/
+/* MC_CMD_GET_PHY_STATE 
+ * Report current state of PHY.
+ */
+#define	MC_CMD_GET_PHY_STATE  0x43
+
+/* MC_CMD_GET_PHY_STATE_IN msgrequest */
+#define	MC_CMD_GET_PHY_STATE_IN_LEN 0
+
+/* MC_CMD_GET_PHY_STATE_OUT msgresponse */
+#define	MC_CMD_GET_PHY_STATE_OUT_LEN 4
+#define	MC_CMD_GET_PHY_STATE_OUT_STATE_OFST 0
+#define	MC_CMD_PHY_STATE_OK 0x1 /* enum */
+#define	MC_CMD_PHY_STATE_ZOMBIE 0x2 /* enum */
+
+
+/***********************************/
+/* MC_CMD_SETUP_8021QBB 
+ * 802.1Qbb control.
+ */
+#define	MC_CMD_SETUP_8021QBB  0x44
+
+/* MC_CMD_SETUP_8021QBB_IN msgrequest */
+#define	MC_CMD_SETUP_8021QBB_IN_LEN 32
+#define	MC_CMD_SETUP_8021QBB_IN_TXQS_OFST 0
+#define	MC_CMD_SETUP_8021QBB_IN_TXQS_LEN 32
+
+/* MC_CMD_SETUP_8021QBB_OUT msgresponse */
+#define	MC_CMD_SETUP_8021QBB_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_WOL_FILTER_GET 
+ * Retrieve ID of any WoL filters.
+ */
+#define	MC_CMD_WOL_FILTER_GET  0x45
+
+/* MC_CMD_WOL_FILTER_GET_IN msgrequest */
+#define	MC_CMD_WOL_FILTER_GET_IN_LEN 0
+
+/* MC_CMD_WOL_FILTER_GET_OUT msgresponse */
+#define	MC_CMD_WOL_FILTER_GET_OUT_LEN 4
+#define	MC_CMD_WOL_FILTER_GET_OUT_FILTER_ID_OFST 0
+
+
+/***********************************/
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD 
+ * Add a protocol offload to NIC for lights-out state.
+ */
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD  0x46
+
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN msgrequest */
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LENMIN 8
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LENMAX 252
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LEN(num) (4+4*(num))
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0
+#define	MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP 0x1 /* enum */
+#define	MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS  0x2 /* enum */
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_OFST 4
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_LEN 4
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_MINNUM 1
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_MAXNUM 62
+
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP msgrequest */
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN 14
+/*            MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 */
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC_OFST 4
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC_LEN 6
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_IP_OFST 10
+
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS msgrequest */
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN 42
+/*            MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 */
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC_OFST 4
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC_LEN 6
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6_OFST 10
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6_LEN 16
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6_OFST 26
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6_LEN 16
+
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT msgresponse */
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN 4
+#define	MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID_OFST 0
+
+
+/***********************************/
+/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD 
+ * Remove a protocol offload from NIC for lights-out state.
+ */
+#define	MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD  0x47
+
+/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN msgrequest */
+#define	MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN 8
+#define	MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0
+#define	MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID_OFST 4
+
+/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT msgresponse */
+#define	MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_MAC_RESET_RESTORE 
+ * Restore MAC after block reset.
+ */
+#define	MC_CMD_MAC_RESET_RESTORE  0x48
+
+/* MC_CMD_MAC_RESET_RESTORE_IN msgrequest */
+#define	MC_CMD_MAC_RESET_RESTORE_IN_LEN 0
+
+/* MC_CMD_MAC_RESET_RESTORE_OUT msgresponse */
+#define	MC_CMD_MAC_RESET_RESTORE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TESTASSERT  
+ */
+#define	MC_CMD_TESTASSERT   0x49
+
+/* MC_CMD_TESTASSERT_IN msgrequest */
+#define	MC_CMD_TESTASSERT_IN_LEN 0
+
+/* MC_CMD_TESTASSERT_OUT msgresponse */
+#define	MC_CMD_TESTASSERT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_WORKAROUND 
+ * Enable/Disable a given workaround.
+ */
+#define	MC_CMD_WORKAROUND  0x4a
+
+/* MC_CMD_WORKAROUND_IN msgrequest */
+#define	MC_CMD_WORKAROUND_IN_LEN 8
+#define	MC_CMD_WORKAROUND_IN_TYPE_OFST 0
+#define	MC_CMD_WORKAROUND_BUG17230 0x1 /* enum */
+#define	MC_CMD_WORKAROUND_IN_ENABLED_OFST 4
+
+/* MC_CMD_WORKAROUND_OUT msgresponse */
+#define	MC_CMD_WORKAROUND_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_PHY_MEDIA_INFO 
+ * Read media-specific data from PHY.
+ */
+#define	MC_CMD_GET_PHY_MEDIA_INFO  0x4b
+
+/* MC_CMD_GET_PHY_MEDIA_INFO_IN msgrequest */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_PAGE_OFST 0
+
+/* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5
+#define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 252
+#define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(num) (4+1*(num))
+#define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_LEN 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MINNUM 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MAXNUM 248
+
+
+/***********************************/
+/* MC_CMD_NVRAM_TEST 
+ * Test a particular NVRAM partition.
+ */
+#define	MC_CMD_NVRAM_TEST  0x4c
+
+/* MC_CMD_NVRAM_TEST_IN msgrequest */
+#define	MC_CMD_NVRAM_TEST_IN_LEN 4
+#define	MC_CMD_NVRAM_TEST_IN_TYPE_OFST 0
+/*            Enum values, see field(s): */
+/*               MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+
+/* MC_CMD_NVRAM_TEST_OUT msgresponse */
+#define	MC_CMD_NVRAM_TEST_OUT_LEN 4
+#define	MC_CMD_NVRAM_TEST_OUT_RESULT_OFST 0
+#define	MC_CMD_NVRAM_TEST_PASS 0x0 /* enum */
+#define	MC_CMD_NVRAM_TEST_FAIL 0x1 /* enum */
+#define	MC_CMD_NVRAM_TEST_NOTSUPP 0x2 /* enum */
+
+
+/***********************************/
+/* MC_CMD_MRSFP_TWEAK 
+ * Read status and/or set parameters for the 'mrsfp' driver.
+ */
+#define	MC_CMD_MRSFP_TWEAK  0x4d
+
+/* MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG msgrequest */
+#define	MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_LEN 16
+#define	MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_TXEQ_LEVEL_OFST 0
+#define	MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_TXEQ_DT_CFG_OFST 4
+#define	MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_RXEQ_BOOST_OFST 8
+#define	MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_RXEQ_DT_CFG_OFST 12
+
+/* MC_CMD_MRSFP_TWEAK_IN_READ_ONLY msgrequest */
+#define	MC_CMD_MRSFP_TWEAK_IN_READ_ONLY_LEN 0
+
+/* MC_CMD_MRSFP_TWEAK_OUT msgresponse */
+#define	MC_CMD_MRSFP_TWEAK_OUT_LEN 12
+#define	MC_CMD_MRSFP_TWEAK_OUT_IOEXP_INPUTS_OFST 0
+#define	MC_CMD_MRSFP_TWEAK_OUT_IOEXP_OUTPUTS_OFST 4
+#define	MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OFST 8
+#define	MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OUT 0x0 /* enum */
+#define	MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_IN 0x1 /* enum */
+
+
+/***********************************/
+/* MC_CMD_SENSOR_SET_LIMS 
+ * Adjusts the sensor limits.
+ */
+#define	MC_CMD_SENSOR_SET_LIMS  0x4e
+
+/* MC_CMD_SENSOR_SET_LIMS_IN msgrequest */
+#define	MC_CMD_SENSOR_SET_LIMS_IN_LEN 20
+#define	MC_CMD_SENSOR_SET_LIMS_IN_SENSOR_OFST 0
+/*            Enum values, see field(s): */
+/*               MC_CMD_SENSOR_INFO/MC_CMD_SENSOR_INFO_OUT/MASK */
+#define	MC_CMD_SENSOR_SET_LIMS_IN_LOW0_OFST 4
+#define	MC_CMD_SENSOR_SET_LIMS_IN_HI0_OFST 8
+#define	MC_CMD_SENSOR_SET_LIMS_IN_LOW1_OFST 12
+#define	MC_CMD_SENSOR_SET_LIMS_IN_HI1_OFST 16
+
+/* MC_CMD_SENSOR_SET_LIMS_OUT msgresponse */
+#define	MC_CMD_SENSOR_SET_LIMS_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_RESOURCE_LIMITS 
+ */
+#define	MC_CMD_GET_RESOURCE_LIMITS  0x4f
+
+/* MC_CMD_GET_RESOURCE_LIMITS_IN msgrequest */
+#define	MC_CMD_GET_RESOURCE_LIMITS_IN_LEN 0
+
+/* MC_CMD_GET_RESOURCE_LIMITS_OUT msgresponse */
+#define	MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN 16
+#define	MC_CMD_GET_RESOURCE_LIMITS_OUT_BUFTBL_OFST 0
+#define	MC_CMD_GET_RESOURCE_LIMITS_OUT_EVQ_OFST 4
+#define	MC_CMD_GET_RESOURCE_LIMITS_OUT_RXQ_OFST 8
+#define	MC_CMD_GET_RESOURCE_LIMITS_OUT_TXQ_OFST 12
+
+/* MC_CMD_RESOURCE_SPECIFIER enum */
+#define	MC_CMD_RESOURCE_INSTANCE_ANY 0xffffffff /* enum */
+#define	MC_CMD_RESOURCE_INSTANCE_NONE 0xfffffffe /* enum */
+
+
+/***********************************/
+/* MC_CMD_INIT_EVQ 
+ */
+#define	MC_CMD_INIT_EVQ  0x50
+
+/* MC_CMD_INIT_EVQ_IN msgrequest */
+#define	MC_CMD_INIT_EVQ_IN_LENMIN 36
+#define	MC_CMD_INIT_EVQ_IN_LENMAX 540
+#define	MC_CMD_INIT_EVQ_IN_LEN(num) (28+8*(num))
+#define	MC_CMD_INIT_EVQ_IN_SIZE_OFST 0
+#define	MC_CMD_INIT_EVQ_IN_INSTANCE_OFST 4
+#define	MC_CMD_INIT_EVQ_IN_TMR_LOAD_OFST 8
+#define	MC_CMD_INIT_EVQ_IN_TMR_RELOAD_OFST 12
+#define	MC_CMD_INIT_EVQ_IN_FLAGS_OFST 16
+#define	MC_CMD_INIT_EVQ_IN_FLAG_INTERRUPTING_LBN 0
+#define	MC_CMD_INIT_EVQ_IN_FLAG_INTERRUPTING_WIDTH 1
+#define	MC_CMD_INIT_EVQ_IN_FLAG_RPTR_DOS_LBN 1
+#define	MC_CMD_INIT_EVQ_IN_FLAG_RPTR_DOS_WIDTH 1
+#define	MC_CMD_INIT_EVQ_IN_TMR_MODE_OFST 20
+#define	MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS 0x0 /* enum */
+#define	MC_CMD_INIT_EVQ_IN_TMR_IMMED_START 0x1 /* enum */
+#define	MC_CMD_INIT_EVQ_IN_TMR_TRIG_START 0x2 /* enum */
+#define	MC_CMD_INIT_EVQ_IN_TMR_INT_HLDOFF 0x3 /* enum */
+#define	MC_CMD_INIT_EVQ_IN_TARGET_EVQ_OFST 24
+#define	MC_CMD_INIT_EVQ_IN_IRQ_NUM_OFST 24
+#define	MC_CMD_INIT_EVQ_IN_DMA_ADDR_OFST 28
+#define	MC_CMD_INIT_EVQ_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_INIT_EVQ_IN_DMA_ADDR_LO_OFST 28
+#define	MC_CMD_INIT_EVQ_IN_DMA_ADDR_HI_OFST 32
+#define	MC_CMD_INIT_EVQ_IN_DMA_ADDR_MINNUM 1
+#define	MC_CMD_INIT_EVQ_IN_DMA_ADDR_MAXNUM 64
+
+/* MC_CMD_INIT_EVQ_OUT msgresponse */
+#define	MC_CMD_INIT_EVQ_OUT_LEN 4
+#define	MC_CMD_INIT_EVQ_OUT_IRQ_OFST 0
+
+/* QUEUE_CRC_MODE structuredef */
+#define	QUEUE_CRC_MODE_LEN 1
+#define	QUEUE_CRC_MODE_MODE_LBN 0
+#define	QUEUE_CRC_MODE_MODE_WIDTH 4
+#define	QUEUE_CRC_MODE_NONE  0x0 /* enum */
+#define	QUEUE_CRC_MODE_FCOE  0x1 /* enum */
+#define	QUEUE_CRC_MODE_ISCSI_HDR  0x2 /* enum */
+#define	QUEUE_CRC_MODE_ISCSI  0x3 /* enum */
+#define	QUEUE_CRC_MODE_FCOIPOE  0x4 /* enum */
+#define	QUEUE_CRC_MODE_MPA  0x5 /* enum */
+#define	QUEUE_CRC_MODE_SPARE_LBN 4
+#define	QUEUE_CRC_MODE_SPARE_WIDTH 4
+
+
+/***********************************/
+/* MC_CMD_INIT_RXQ 
+ */
+#define	MC_CMD_INIT_RXQ  0x51
+
+/* MC_CMD_INIT_RXQ_IN msgrequest */
+#define	MC_CMD_INIT_RXQ_IN_LENMIN 32
+#define	MC_CMD_INIT_RXQ_IN_LENMAX 248
+#define	MC_CMD_INIT_RXQ_IN_LEN(num) (24+8*(num))
+#define	MC_CMD_INIT_RXQ_IN_SIZE_OFST 0
+#define	MC_CMD_INIT_RXQ_IN_TARGET_EVQ_OFST 4
+#define	MC_CMD_INIT_RXQ_IN_LABEL_OFST 8
+#define	MC_CMD_INIT_RXQ_IN_INSTANCE_OFST 12
+#define	MC_CMD_INIT_RXQ_IN_FLAGS_OFST 16
+#define	MC_CMD_INIT_RXQ_IN_FLAG_BUFF_MODE_LBN 0
+#define	MC_CMD_INIT_RXQ_IN_FLAG_BUFF_MODE_WIDTH 1
+#define	MC_CMD_INIT_RXQ_IN_FLAG_HDR_SPLIT_LBN 1
+#define	MC_CMD_INIT_RXQ_IN_FLAG_HDR_SPLIT_WIDTH 1
+#define	MC_CMD_INIT_RXQ_IN_FLAG_PKT_EDIT_LBN 2
+#define	MC_CMD_INIT_RXQ_IN_FLAG_PKT_EDIT_WIDTH 1
+#define	MC_CMD_INIT_RXQ_IN_CRC_MODE_LBN 3
+#define	MC_CMD_INIT_RXQ_IN_CRC_MODE_WIDTH 4
+#define	MC_CMD_INIT_RXQ_IN_OWNER_ID_OFST 20
+#define	MC_CMD_INIT_RXQ_IN_DMA_ADDR_OFST 24
+#define	MC_CMD_INIT_RXQ_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_INIT_RXQ_IN_DMA_ADDR_LO_OFST 24
+#define	MC_CMD_INIT_RXQ_IN_DMA_ADDR_HI_OFST 28
+#define	MC_CMD_INIT_RXQ_IN_DMA_ADDR_MINNUM 1
+#define	MC_CMD_INIT_RXQ_IN_DMA_ADDR_MAXNUM 28
+
+/* MC_CMD_INIT_RXQ_OUT msgresponse */
+#define	MC_CMD_INIT_RXQ_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_INIT_TXQ 
+ */
+#define	MC_CMD_INIT_TXQ  0x52
+
+/* MC_CMD_INIT_TXQ_IN msgrequest */
+#define	MC_CMD_INIT_TXQ_IN_LENMIN 32
+#define	MC_CMD_INIT_TXQ_IN_LENMAX 248
+#define	MC_CMD_INIT_TXQ_IN_LEN(num) (24+8*(num))
+#define	MC_CMD_INIT_TXQ_IN_SIZE_OFST 0
+#define	MC_CMD_INIT_TXQ_IN_TARGET_EVQ_OFST 4
+#define	MC_CMD_INIT_TXQ_IN_LABEL_OFST 8
+#define	MC_CMD_INIT_TXQ_IN_INSTANCE_OFST 12
+#define	MC_CMD_INIT_TXQ_IN_FLAGS_OFST 16
+#define	MC_CMD_INIT_TXQ_IN_FLAG_BUFF_MODE_LBN 0
+#define	MC_CMD_INIT_TXQ_IN_FLAG_BUFF_MODE_WIDTH 1
+#define	MC_CMD_INIT_TXQ_IN_FLAG_IP_CSUM_DIS_LBN 1
+#define	MC_CMD_INIT_TXQ_IN_FLAG_IP_CSUM_DIS_WIDTH 1
+#define	MC_CMD_INIT_TXQ_IN_FLAG_TCP_CSUM_DIS_LBN 2
+#define	MC_CMD_INIT_TXQ_IN_FLAG_TCP_CSUM_DIS_WIDTH 1
+#define	MC_CMD_INIT_TXQ_IN_CRC_MODE_LBN 4
+#define	MC_CMD_INIT_TXQ_IN_CRC_MODE_WIDTH 4
+#define	MC_CMD_INIT_TXQ_IN_OWNER_ID_OFST 20
+#define	MC_CMD_INIT_TXQ_IN_DMA_ADDR_OFST 24
+#define	MC_CMD_INIT_TXQ_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_INIT_TXQ_IN_DMA_ADDR_LO_OFST 24
+#define	MC_CMD_INIT_TXQ_IN_DMA_ADDR_HI_OFST 28
+#define	MC_CMD_INIT_TXQ_IN_DMA_ADDR_MINNUM 1
+#define	MC_CMD_INIT_TXQ_IN_DMA_ADDR_MAXNUM 28
+
+/* MC_CMD_INIT_TXQ_OUT msgresponse */
+#define	MC_CMD_INIT_TXQ_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_FINI_EVQ 
+ */
+#define	MC_CMD_FINI_EVQ  0x55
+
+/* MC_CMD_FINI_EVQ_IN msgrequest */
+#define	MC_CMD_FINI_EVQ_IN_LEN 4
+#define	MC_CMD_FINI_EVQ_IN_INSTANCE_OFST 0
+
+/* MC_CMD_FINI_EVQ_OUT msgresponse */
+#define	MC_CMD_FINI_EVQ_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_FINI_RXQ 
+ */
+#define	MC_CMD_FINI_RXQ  0x56
+
+/* MC_CMD_FINI_RXQ_IN msgrequest */
+#define	MC_CMD_FINI_RXQ_IN_LEN 4
+#define	MC_CMD_FINI_RXQ_IN_INSTANCE_OFST 0
+
+/* MC_CMD_FINI_RXQ_OUT msgresponse */
+#define	MC_CMD_FINI_RXQ_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_FINI_TXQ 
+ */
+#define	MC_CMD_FINI_TXQ  0x57
+
+/* MC_CMD_FINI_TXQ_IN msgrequest */
+#define	MC_CMD_FINI_TXQ_IN_LEN 4
+#define	MC_CMD_FINI_TXQ_IN_INSTANCE_OFST 0
+
+/* MC_CMD_FINI_TXQ_OUT msgresponse */
+#define	MC_CMD_FINI_TXQ_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_DRIVER_EVENT 
+ */
+#define	MC_CMD_DRIVER_EVENT  0x5a
+
+/* MC_CMD_DRIVER_EVENT_IN msgrequest */
+#define	MC_CMD_DRIVER_EVENT_IN_LEN 12
+#define	MC_CMD_DRIVER_EVENT_IN_EVQ_OFST 0
+#define	MC_CMD_DRIVER_EVENT_IN_DATA_OFST 4
+#define	MC_CMD_DRIVER_EVENT_IN_DATA_LEN 8
+#define	MC_CMD_DRIVER_EVENT_IN_DATA_LO_OFST 4
+#define	MC_CMD_DRIVER_EVENT_IN_DATA_HI_OFST 8
+
+
+/***********************************/
+/* MC_CMD_PROXY_CMD 
+ */
+#define	MC_CMD_PROXY_CMD  0x5b
+
+/* MC_CMD_PROXY_CMD_IN msgrequest */
+#define	MC_CMD_PROXY_CMD_IN_LEN 4
+#define	MC_CMD_PROXY_CMD_IN_TARGET_OFST 0
+
+
+/***********************************/
+/* MC_CMD_ALLOC_OWNER_IDS 
+ */
+#define	MC_CMD_ALLOC_OWNER_IDS  0x54
+
+/* MC_CMD_ALLOC_OWNER_IDS_IN msgrequest */
+#define	MC_CMD_ALLOC_OWNER_IDS_IN_LEN 4
+#define	MC_CMD_ALLOC_OWNER_IDS_IN_NIDS_OFST 0
+
+/* MC_CMD_ALLOC_OWNER_IDS_OUT msgresponse */
+#define	MC_CMD_ALLOC_OWNER_IDS_OUT_LEN 12
+#define	MC_CMD_ALLOC_OWNER_IDS_OUT_HANDLE_OFST 0
+#define	MC_CMD_ALLOC_OWNER_IDS_OUT_NIDS_OFST 4
+#define	MC_CMD_ALLOC_OWNER_IDS_OUT_BASE_OFST 8
+
+
+/***********************************/
+/* MC_CMD_FREE_OWNER_IDS 
+ */
+#define	MC_CMD_FREE_OWNER_IDS  0x59
+
+/* MC_CMD_FREE_OWNER_IDS_IN msgrequest */
+#define	MC_CMD_FREE_OWNER_IDS_IN_LEN 4
+#define	MC_CMD_FREE_OWNER_IDS_IN_HANDLE_OFST 0
+
+/* MC_CMD_FREE_OWNER_IDS_OUT msgresponse */
+#define	MC_CMD_FREE_OWNER_IDS_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_ALLOC_BUFTBL_CHUNK 
+ */
+#define	MC_CMD_ALLOC_BUFTBL_CHUNK  0x5c
+
+/* MC_CMD_ALLOC_BUFTBL_CHUNK_IN msgrequest */
+#define	MC_CMD_ALLOC_BUFTBL_CHUNK_IN_LEN 8
+#define	MC_CMD_ALLOC_BUFTBL_CHUNK_IN_OWNER_OFST 0
+#define	MC_CMD_ALLOC_BUFTBL_CHUNK_IN_PAGE_SIZE_OFST 4
+
+/* MC_CMD_ALLOC_BUFTBL_CHUNK_OUT msgresponse */
+#define	MC_CMD_ALLOC_BUFTBL_CHUNK_OUT_LEN 12
+#define	MC_CMD_ALLOC_BUFTBL_CHUNK_OUT_HANDLE_OFST 0
+#define	MC_CMD_ALLOC_BUFTBL_CHUNK_OUT_NUMENTRIES_OFST 4
+#define	MC_CMD_ALLOC_BUFTBL_CHUNK_OUT_ID_OFST 8
+
+
+/***********************************/
+/* MC_CMD_PROGRAM_BUFTBL_ENTRIES 
+ */
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES  0x5d
+
+/* MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN msgrequest */
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_LENMIN 20
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_LENMAX 252
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_LEN(num) (12+8*(num))
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_HANDLE_OFST 0
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_FIRSTID_OFST 4
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_NUMENTRIES_OFST 8
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_OFST 12
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_LEN 8
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_LO_OFST 12
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_HI_OFST 16
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_MINNUM 1
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_IN_ENTRY_MAXNUM 30
+
+/* MC_CMD_PROGRAM_BUFTBL_ENTRIES_OUT msgresponse */
+#define	MC_CMD_PROGRAM_BUFTBL_ENTRIES_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_FREE_BUFTBL_CHUNK 
+ */
+#define	MC_CMD_FREE_BUFTBL_CHUNK  0x5e
+
+/* MC_CMD_FREE_BUFTBL_CHUNK_IN msgrequest */
+#define	MC_CMD_FREE_BUFTBL_CHUNK_IN_LEN 4
+#define	MC_CMD_FREE_BUFTBL_CHUNK_IN_HANDLE_OFST 0
+
+/* MC_CMD_FREE_BUFTBL_CHUNK_OUT msgresponse */
+#define	MC_CMD_FREE_BUFTBL_CHUNK_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_PF_COUNT 
+ */
+#define	MC_CMD_GET_PF_COUNT  0x60
+
+/* MC_CMD_GET_PF_COUNT_IN msgrequest */
+#define	MC_CMD_GET_PF_COUNT_IN_LEN 0
+
+/* MC_CMD_GET_PF_COUNT_OUT msgresponse */
+#define	MC_CMD_GET_PF_COUNT_OUT_LEN 1
+#define	MC_CMD_GET_PF_COUNT_OUT_PF_COUNT_OFST 0
+#define	MC_CMD_GET_PF_COUNT_OUT_PF_COUNT_LEN 1
+
+
+/***********************************/
+/* MC_CMD_FILTER_OP 
+ */
+#define	MC_CMD_FILTER_OP  0x61
+
+/* MC_CMD_FILTER_OP_IN msgrequest */
+#define	MC_CMD_FILTER_OP_IN_LEN 100
+#define	MC_CMD_FILTER_OP_IN_OP_OFST 0
+#define	MC_CMD_FILTER_OP_IN_OP_INSERT  0x0 /* enum */
+#define	MC_CMD_FILTER_OP_IN_OP_REMOVE  0x1 /* enum */
+#define	MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE  0x2 /* enum */
+#define	MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE  0x3 /* enum */
+#define	MC_CMD_FILTER_OP_IN_HANDLE_OFST 4
+#define	MC_CMD_FILTER_OP_IN_MATCH_FIELDS_OFST 8
+#define	MC_CMD_FILTER_OP_IN_MATCH_SRC_IP_LBN 0
+#define	MC_CMD_FILTER_OP_IN_MATCH_SRC_IP_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_DST_IP_LBN 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_DST_IP_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_SRC_MAC_LBN 2
+#define	MC_CMD_FILTER_OP_IN_MATCH_SRC_MAC_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_SRC_PORT_LBN 3
+#define	MC_CMD_FILTER_OP_IN_MATCH_SRC_PORT_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_DST_MAC_LBN 4
+#define	MC_CMD_FILTER_OP_IN_MATCH_DST_MAC_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_DST_PORT_LBN 5
+#define	MC_CMD_FILTER_OP_IN_MATCH_DST_PORT_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_ETHER_TYPE_LBN 6
+#define	MC_CMD_FILTER_OP_IN_MATCH_ETHER_TYPE_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_INNER_VLAN_LBN 7
+#define	MC_CMD_FILTER_OP_IN_MATCH_INNER_VLAN_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_OUTER_VLAN_LBN 8
+#define	MC_CMD_FILTER_OP_IN_MATCH_OUTER_VLAN_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_IP_PROTO_LBN 9
+#define	MC_CMD_FILTER_OP_IN_MATCH_IP_PROTO_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF0_LBN 10
+#define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF0_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_LBN 11
+#define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_RX_DEST_OFST 12
+#define	MC_CMD_FILTER_OP_IN_RX_DEST_DROP  0x0 /* enum */
+#define	MC_CMD_FILTER_OP_IN_RX_DEST_HOST  0x1 /* enum */
+#define	MC_CMD_FILTER_OP_IN_RX_DEST_MC  0x2 /* enum */
+#define	MC_CMD_FILTER_OP_IN_RX_DEST_TX0  0x3 /* enum */
+#define	MC_CMD_FILTER_OP_IN_RX_DEST_TX1  0x4 /* enum */
+#define	MC_CMD_FILTER_OP_IN_RX_QUEUE_OFST 16
+#define	MC_CMD_FILTER_OP_IN_RX_FLAGS_OFST 20
+#define	MC_CMD_FILTER_OP_IN_RX_FLAG_RSS_LBN 0
+#define	MC_CMD_FILTER_OP_IN_RX_FLAG_RSS_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_RSS_CONTEXT_OFST 24
+#define	MC_CMD_FILTER_OP_IN_TX_DOMAIN_OFST 28
+#define	MC_CMD_FILTER_OP_IN_TX_DEST_OFST 32
+#define	MC_CMD_FILTER_OP_IN_TX_DEST_MAC_LBN 0
+#define	MC_CMD_FILTER_OP_IN_TX_DEST_MAC_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_TX_DEST_PM_LBN 1
+#define	MC_CMD_FILTER_OP_IN_TX_DEST_PM_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_SRC_MAC_OFST 36
+#define	MC_CMD_FILTER_OP_IN_SRC_MAC_LEN 6
+#define	MC_CMD_FILTER_OP_IN_SRC_PORT_OFST 42
+#define	MC_CMD_FILTER_OP_IN_SRC_PORT_LEN 2
+#define	MC_CMD_FILTER_OP_IN_DST_MAC_OFST 44
+#define	MC_CMD_FILTER_OP_IN_DST_MAC_LEN 6
+#define	MC_CMD_FILTER_OP_IN_DST_PORT_OFST 50
+#define	MC_CMD_FILTER_OP_IN_DST_PORT_LEN 2
+#define	MC_CMD_FILTER_OP_IN_ETHER_TYPE_OFST 52
+#define	MC_CMD_FILTER_OP_IN_ETHER_TYPE_LEN 2
+#define	MC_CMD_FILTER_OP_IN_INNER_VLAN_OFST 54
+#define	MC_CMD_FILTER_OP_IN_INNER_VLAN_LEN 2
+#define	MC_CMD_FILTER_OP_IN_OUTER_VLAN_OFST 56
+#define	MC_CMD_FILTER_OP_IN_OUTER_VLAN_LEN 2
+#define	MC_CMD_FILTER_OP_IN_IP_PROTO_OFST 58
+#define	MC_CMD_FILTER_OP_IN_IP_PROTO_LEN 2
+#define	MC_CMD_FILTER_OP_IN_FWDEF0_OFST 60
+#define	MC_CMD_FILTER_OP_IN_FWDEF1_OFST 64
+#define	MC_CMD_FILTER_OP_IN_SRC_IP_OFST 68
+#define	MC_CMD_FILTER_OP_IN_SRC_IP_LEN 16
+#define	MC_CMD_FILTER_OP_IN_DST_IP_OFST 84
+#define	MC_CMD_FILTER_OP_IN_DST_IP_LEN 16
+
+/* MC_CMD_FILTER_OP_OUT msgresponse */
+#define	MC_CMD_FILTER_OP_OUT_LEN 8
+#define	MC_CMD_FILTER_OP_OUT_OP_OFST 0
+#define	MC_CMD_FILTER_OP_OUT_OP_INSERT  0x0 /* enum */
+#define	MC_CMD_FILTER_OP_OUT_OP_REMOVE  0x1 /* enum */
+#define	MC_CMD_FILTER_OP_OUT_OP_SUBSCRIBE  0x2 /* enum */
+#define	MC_CMD_FILTER_OP_OUT_OP_UNSUBSCRIBE  0x3 /* enum */
+#define	MC_CMD_FILTER_OP_OUT_HANDLE_OFST 4
+
+
+/***********************************/
+/* MC_CMD_SET_PF_COUNT 
+ */
+#define	MC_CMD_SET_PF_COUNT  0x62
+
+/* MC_CMD_SET_PF_COUNT_IN msgrequest */
+#define	MC_CMD_SET_PF_COUNT_IN_LEN 4
+#define	MC_CMD_SET_PF_COUNT_IN_PF_COUNT_OFST 0
+
+/* MC_CMD_SET_PF_COUNT_OUT msgresponse */
+#define	MC_CMD_SET_PF_COUNT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_PORT_ASSIGNMENT 
+ */
+#define	MC_CMD_GET_PORT_ASSIGNMENT  0x63
+
+/* MC_CMD_GET_PORT_ASSIGNMENT_IN msgrequest */
+#define	MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN 0
+
+/* MC_CMD_GET_PORT_ASSIGNMENT_OUT msgresponse */
+#define	MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN 4
+#define	MC_CMD_GET_PORT_ASSIGNMENT_OUT_PORT_OFST 0
+
+
+/***********************************/
+/* MC_CMD_SET_PORT_ASSIGNMENT 
+ */
+#define	MC_CMD_SET_PORT_ASSIGNMENT  0x64
+
+/* MC_CMD_SET_PORT_ASSIGNMENT_IN msgrequest */
+#define	MC_CMD_SET_PORT_ASSIGNMENT_IN_LEN 4
+#define	MC_CMD_SET_PORT_ASSIGNMENT_IN_PORT_OFST 0
+
+/* MC_CMD_SET_PORT_ASSIGNMENT_OUT msgresponse */
+#define	MC_CMD_SET_PORT_ASSIGNMENT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_ALLOC_VIS 
+ */
+#define	MC_CMD_ALLOC_VIS  0x65
+
+/* MC_CMD_ALLOC_VIS_IN msgrequest */
+#define	MC_CMD_ALLOC_VIS_IN_LEN 4
+#define	MC_CMD_ALLOC_VIS_IN_VI_COUNT_OFST 0
+
+/* MC_CMD_ALLOC_VIS_OUT msgresponse */
+#define	MC_CMD_ALLOC_VIS_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_FREE_VIS 
+ */
+#define	MC_CMD_FREE_VIS  0x66
+
+/* MC_CMD_FREE_VIS_IN msgrequest */
+#define	MC_CMD_FREE_VIS_IN_LEN 0
+
+/* MC_CMD_FREE_VIS_OUT msgresponse */
+#define	MC_CMD_FREE_VIS_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_SRIOV_CFG 
+ */
+#define	MC_CMD_GET_SRIOV_CFG  0x67
+
+/* MC_CMD_GET_SRIOV_CFG_IN msgrequest */
+#define	MC_CMD_GET_SRIOV_CFG_IN_LEN 0
+
+/* MC_CMD_GET_SRIOV_CFG_OUT msgresponse */
+#define	MC_CMD_GET_SRIOV_CFG_OUT_LEN 20
+#define	MC_CMD_GET_SRIOV_CFG_OUT_VF_CURRENT_OFST 0
+#define	MC_CMD_GET_SRIOV_CFG_OUT_VF_MAX_OFST 4
+#define	MC_CMD_GET_SRIOV_CFG_OUT_FLAGS_OFST 8
+#define	MC_CMD_GET_SRIOV_CFG_OUT_VF_ENABLED_LBN 0
+#define	MC_CMD_GET_SRIOV_CFG_OUT_VF_ENABLED_WIDTH 1
+#define	MC_CMD_GET_SRIOV_CFG_OUT_VF_OFFSET_OFST 12
+#define	MC_CMD_GET_SRIOV_CFG_OUT_VF_STRIDE_OFST 16
+
+
+/***********************************/
+/* MC_CMD_SET_SRIOV_CFG 
+ */
+#define	MC_CMD_SET_SRIOV_CFG  0x68
+
+/* MC_CMD_SET_SRIOV_CFG_IN msgrequest */
+#define	MC_CMD_SET_SRIOV_CFG_IN_LEN 20
+#define	MC_CMD_SET_SRIOV_CFG_IN_VF_CURRENT_OFST 0
+#define	MC_CMD_SET_SRIOV_CFG_IN_VF_MAX_OFST 4
+#define	MC_CMD_SET_SRIOV_CFG_IN_FLAGS_OFST 8
+#define	MC_CMD_SET_SRIOV_CFG_IN_VF_ENABLED_LBN 0
+#define	MC_CMD_SET_SRIOV_CFG_IN_VF_ENABLED_WIDTH 1
+#define	MC_CMD_SET_SRIOV_CFG_IN_VF_OFFSET_OFST 12
+#define	MC_CMD_SET_SRIOV_CFG_IN_VF_STRIDE_OFST 16
+
+/* MC_CMD_SET_SRIOV_CFG_OUT msgresponse */
+#define	MC_CMD_SET_SRIOV_CFG_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_VI_COUNT 
+ */
+#define	MC_CMD_GET_VI_COUNT  0x69
+
+/* MC_CMD_GET_VI_COUNT_IN msgrequest */
+#define	MC_CMD_GET_VI_COUNT_IN_LEN 0
+
+/* MC_CMD_GET_VI_COUNT_OUT msgresponse */
+#define	MC_CMD_GET_VI_COUNT_OUT_LEN 4
+#define	MC_CMD_GET_VI_COUNT_OUT_VI_COUNT_OFST 0
+
+
+/***********************************/
+/* MC_CMD_GET_VECTOR_CFG 
+ */
+#define	MC_CMD_GET_VECTOR_CFG  0x70
+
+/* MC_CMD_GET_VECTOR_CFG_IN msgrequest */
+#define	MC_CMD_GET_VECTOR_CFG_IN_LEN 0
+
+/* MC_CMD_GET_VECTOR_CFG_OUT msgresponse */
+#define	MC_CMD_GET_VECTOR_CFG_OUT_LEN 12
+#define	MC_CMD_GET_VECTOR_CFG_OUT_VEC_BASE_OFST 0
+#define	MC_CMD_GET_VECTOR_CFG_OUT_VECS_PER_PF_OFST 4
+#define	MC_CMD_GET_VECTOR_CFG_OUT_VECS_PER_VF_OFST 8
+
+
+/***********************************/
+/* MC_CMD_SET_VECTOR_CFG 
+ */
+#define	MC_CMD_SET_VECTOR_CFG  0x71
+
+/* MC_CMD_SET_VECTOR_CFG_IN msgrequest */
+#define	MC_CMD_SET_VECTOR_CFG_IN_LEN 12
+#define	MC_CMD_SET_VECTOR_CFG_IN_VEC_BASE_OFST 0
+#define	MC_CMD_SET_VECTOR_CFG_IN_VECS_PER_PF_OFST 4
+#define	MC_CMD_SET_VECTOR_CFG_IN_VECS_PER_VF_OFST 8
+
+/* MC_CMD_SET_VECTOR_CFG_OUT msgresponse */
+#define	MC_CMD_SET_VECTOR_CFG_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_ALLOC_PIOBUF 
+ */
+#define	MC_CMD_ALLOC_PIOBUF  0x72
+
+/* MC_CMD_ALLOC_PIOBUF_IN msgrequest */
+#define	MC_CMD_ALLOC_PIOBUF_IN_LEN 0
+
+/* MC_CMD_ALLOC_PIOBUF_OUT msgresponse */
+#define	MC_CMD_ALLOC_PIOBUF_OUT_LEN 4
+#define	MC_CMD_ALLOC_PIOBUF_OUT_PIOBUF_HANDLE_OFST 0
+
+
+/***********************************/
+/* MC_CMD_FREE_PIOBUF 
+ */
+#define	MC_CMD_FREE_PIOBUF  0x73
+
+/* MC_CMD_FREE_PIOBUF_IN msgrequest */
+#define	MC_CMD_FREE_PIOBUF_IN_LEN 4
+#define	MC_CMD_FREE_PIOBUF_IN_PIOBUF_HANDLE_OFST 0
+
+/* MC_CMD_FREE_PIOBUF_OUT msgresponse */
+#define	MC_CMD_FREE_PIOBUF_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_V2_EXTN 
+ */
+#define	MC_CMD_V2_EXTN  0x7f
+
+/* MC_CMD_V2_EXTN_IN msgrequest */
+#define	MC_CMD_V2_EXTN_IN_LEN 4
+#define	MC_CMD_V2_EXTN_IN_EXTENDED_CMD_LBN 0
+#define	MC_CMD_V2_EXTN_IN_EXTENDED_CMD_WIDTH 15
+#define	MC_CMD_V2_EXTN_IN_UNUSED_LBN 15
+#define	MC_CMD_V2_EXTN_IN_UNUSED_WIDTH 1
+#define	MC_CMD_V2_EXTN_IN_ACTUAL_LEN_LBN 16
+#define	MC_CMD_V2_EXTN_IN_ACTUAL_LEN_WIDTH 10
+#define	MC_CMD_V2_EXTN_IN_UNUSED2_LBN 26
+#define	MC_CMD_V2_EXTN_IN_UNUSED2_WIDTH 6
+
+
+/***********************************/
+/* MC_CMD_TCM_BUCKET_ALLOC 
+ */
+#define	MC_CMD_TCM_BUCKET_ALLOC  0x80
+
+/* MC_CMD_TCM_BUCKET_ALLOC_IN msgrequest */
+#define	MC_CMD_TCM_BUCKET_ALLOC_IN_LEN 0
+
+/* MC_CMD_TCM_BUCKET_ALLOC_OUT msgresponse */
+#define	MC_CMD_TCM_BUCKET_ALLOC_OUT_LEN 4
+#define	MC_CMD_TCM_BUCKET_ALLOC_OUT_BUCKET_OFST 0
+
+
+/***********************************/
+/* MC_CMD_TCM_BUCKET_FREE 
+ */
+#define	MC_CMD_TCM_BUCKET_FREE  0x81
+
+/* MC_CMD_TCM_BUCKET_FREE_IN msgrequest */
+#define	MC_CMD_TCM_BUCKET_FREE_IN_LEN 4
+#define	MC_CMD_TCM_BUCKET_FREE_IN_BUCKET_OFST 0
+
+/* MC_CMD_TCM_BUCKET_FREE_OUT msgresponse */
+#define	MC_CMD_TCM_BUCKET_FREE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TCM_BUCKET_INIT 
+ */
+#define	MC_CMD_TCM_BUCKET_INIT  0x82
+
+/* MC_CMD_TCM_BUCKET_INIT_IN msgrequest */
+#define	MC_CMD_TCM_BUCKET_INIT_IN_LEN 8
+#define	MC_CMD_TCM_BUCKET_INIT_IN_BUCKET_OFST 0
+#define	MC_CMD_TCM_BUCKET_INIT_IN_RATE_OFST 4
+
+/* MC_CMD_TCM_BUCKET_INIT_OUT msgresponse */
+#define	MC_CMD_TCM_BUCKET_INIT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TCM_TXQ_INIT 
+ */
+#define	MC_CMD_TCM_TXQ_INIT  0x83
+
+/* MC_CMD_TCM_TXQ_INIT_IN msgrequest */
+#define	MC_CMD_TCM_TXQ_INIT_IN_LEN 28
+#define	MC_CMD_TCM_TXQ_INIT_IN_QID_OFST 0
+#define	MC_CMD_TCM_TXQ_INIT_IN_LABEL_OFST 4
+#define	MC_CMD_TCM_TXQ_INIT_IN_PQ_FLAGS_OFST 8
+#define	MC_CMD_TCM_TXQ_INIT_IN_RP_BKT_OFST 12
+#define	MC_CMD_TCM_TXQ_INIT_IN_MAX_BKT1_OFST 16
+#define	MC_CMD_TCM_TXQ_INIT_IN_MAX_BKT2_OFST 20
+#define	MC_CMD_TCM_TXQ_INIT_IN_MIN_BKT_OFST 24
+
+/* MC_CMD_TCM_TXQ_INIT_OUT msgresponse */
+#define	MC_CMD_TCM_TXQ_INIT_OUT_LEN 0
+
+#endif /* _SIENA_MC_DRIVER_PCOL_H */
+/*! \cidoxg_end */
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_regs_pci.h	2013-08-22 18:57:29.019900160 -0400
@@ -0,0 +1,2376 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_EFX_REGS_PCI_H
+#define	_SYS_EFX_REGS_PCI_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * PC_VEND_ID_REG(16bit):
+ * Vendor ID register
+ */
+
+#define	PCR_AZ_VEND_ID_REG 0x00000000
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_VEND_ID_LBN 0
+#define	PCRF_AZ_VEND_ID_WIDTH 16
+
+
+/*
+ * PC_DEV_ID_REG(16bit):
+ * Device ID register
+ */
+
+#define	PCR_AZ_DEV_ID_REG 0x00000002
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_DEV_ID_LBN 0
+#define	PCRF_AZ_DEV_ID_WIDTH 16
+
+
+/*
+ * PC_CMD_REG(16bit):
+ * Command register
+ */
+
+#define	PCR_AZ_CMD_REG 0x00000004
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_INTX_DIS_LBN 10
+#define	PCRF_AZ_INTX_DIS_WIDTH 1
+#define	PCRF_AZ_FB2B_EN_LBN 9
+#define	PCRF_AZ_FB2B_EN_WIDTH 1
+#define	PCRF_AZ_SERR_EN_LBN 8
+#define	PCRF_AZ_SERR_EN_WIDTH 1
+#define	PCRF_AZ_IDSEL_CTL_LBN 7
+#define	PCRF_AZ_IDSEL_CTL_WIDTH 1
+#define	PCRF_AZ_PERR_EN_LBN 6
+#define	PCRF_AZ_PERR_EN_WIDTH 1
+#define	PCRF_AZ_VGA_PAL_SNP_LBN 5
+#define	PCRF_AZ_VGA_PAL_SNP_WIDTH 1
+#define	PCRF_AZ_MWI_EN_LBN 4
+#define	PCRF_AZ_MWI_EN_WIDTH 1
+#define	PCRF_AZ_SPEC_CYC_LBN 3
+#define	PCRF_AZ_SPEC_CYC_WIDTH 1
+#define	PCRF_AZ_MST_EN_LBN 2
+#define	PCRF_AZ_MST_EN_WIDTH 1
+#define	PCRF_AZ_MEM_EN_LBN 1
+#define	PCRF_AZ_MEM_EN_WIDTH 1
+#define	PCRF_AZ_IO_EN_LBN 0
+#define	PCRF_AZ_IO_EN_WIDTH 1
+
+
+/*
+ * PC_STAT_REG(16bit):
+ * Status register
+ */
+
+#define	PCR_AZ_STAT_REG 0x00000006
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_DET_PERR_LBN 15
+#define	PCRF_AZ_DET_PERR_WIDTH 1
+#define	PCRF_AZ_SIG_SERR_LBN 14
+#define	PCRF_AZ_SIG_SERR_WIDTH 1
+#define	PCRF_AZ_GOT_MABRT_LBN 13
+#define	PCRF_AZ_GOT_MABRT_WIDTH 1
+#define	PCRF_AZ_GOT_TABRT_LBN 12
+#define	PCRF_AZ_GOT_TABRT_WIDTH 1
+#define	PCRF_AZ_SIG_TABRT_LBN 11
+#define	PCRF_AZ_SIG_TABRT_WIDTH 1
+#define	PCRF_AZ_DEVSEL_TIM_LBN 9
+#define	PCRF_AZ_DEVSEL_TIM_WIDTH 2
+#define	PCRF_AZ_MDAT_PERR_LBN 8
+#define	PCRF_AZ_MDAT_PERR_WIDTH 1
+#define	PCRF_AZ_FB2B_CAP_LBN 7
+#define	PCRF_AZ_FB2B_CAP_WIDTH 1
+#define	PCRF_AZ_66MHZ_CAP_LBN 5
+#define	PCRF_AZ_66MHZ_CAP_WIDTH 1
+#define	PCRF_AZ_CAP_LIST_LBN 4
+#define	PCRF_AZ_CAP_LIST_WIDTH 1
+#define	PCRF_AZ_INTX_STAT_LBN 3
+#define	PCRF_AZ_INTX_STAT_WIDTH 1
+
+
+/*
+ * PC_REV_ID_REG(8bit):
+ * Class code & revision ID register
+ */
+
+#define	PCR_AZ_REV_ID_REG 0x00000008
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_REV_ID_LBN 0
+#define	PCRF_AZ_REV_ID_WIDTH 8
+
+
+/*
+ * PC_CC_REG(24bit):
+ * Class code register
+ */
+
+#define	PCR_AZ_CC_REG 0x00000009
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_BASE_CC_LBN 16
+#define	PCRF_AZ_BASE_CC_WIDTH 8
+#define	PCRF_AZ_SUB_CC_LBN 8
+#define	PCRF_AZ_SUB_CC_WIDTH 8
+#define	PCRF_AZ_PROG_IF_LBN 0
+#define	PCRF_AZ_PROG_IF_WIDTH 8
+
+
+/*
+ * PC_CACHE_LSIZE_REG(8bit):
+ * Cache line size
+ */
+
+#define	PCR_AZ_CACHE_LSIZE_REG 0x0000000c
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_CACHE_LSIZE_LBN 0
+#define	PCRF_AZ_CACHE_LSIZE_WIDTH 8
+
+
+/*
+ * PC_MST_LAT_REG(8bit):
+ * Master latency timer register
+ */
+
+#define	PCR_AZ_MST_LAT_REG 0x0000000d
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_MST_LAT_LBN 0
+#define	PCRF_AZ_MST_LAT_WIDTH 8
+
+
+/*
+ * PC_HDR_TYPE_REG(8bit):
+ * Header type register
+ */
+
+#define	PCR_AZ_HDR_TYPE_REG 0x0000000e
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_MULT_FUNC_LBN 7
+#define	PCRF_AZ_MULT_FUNC_WIDTH 1
+#define	PCRF_AZ_TYPE_LBN 0
+#define	PCRF_AZ_TYPE_WIDTH 7
+
+
+/*
+ * PC_BIST_REG(8bit):
+ * BIST register
+ */
+
+#define	PCR_AZ_BIST_REG 0x0000000f
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_BIST_LBN 0
+#define	PCRF_AZ_BIST_WIDTH 8
+
+
+/*
+ * PC_BAR0_REG(32bit):
+ * Primary function base address register 0
+ */
+
+#define	PCR_AZ_BAR0_REG 0x00000010
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_BAR0_LBN 4
+#define	PCRF_AZ_BAR0_WIDTH 28
+#define	PCRF_AZ_BAR0_PREF_LBN 3
+#define	PCRF_AZ_BAR0_PREF_WIDTH 1
+#define	PCRF_AZ_BAR0_TYPE_LBN 1
+#define	PCRF_AZ_BAR0_TYPE_WIDTH 2
+#define	PCRF_AZ_BAR0_IOM_LBN 0
+#define	PCRF_AZ_BAR0_IOM_WIDTH 1
+
+
+/*
+ * PC_BAR1_REG(32bit):
+ * Primary function base address register 1, BAR1 is not implemented so read only.
+ */
+
+#define	PCR_DZ_BAR1_REG 0x00000014
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_BAR1_LBN 0
+#define	PCRF_DZ_BAR1_WIDTH 32
+
+
+/*
+ * PC_BAR2_LO_REG(32bit):
+ * Primary function base address register 2 low bits
+ */
+
+#define	PCR_AZ_BAR2_LO_REG 0x00000018
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_BAR2_LO_LBN 4
+#define	PCRF_AZ_BAR2_LO_WIDTH 28
+#define	PCRF_AZ_BAR2_PREF_LBN 3
+#define	PCRF_AZ_BAR2_PREF_WIDTH 1
+#define	PCRF_AZ_BAR2_TYPE_LBN 1
+#define	PCRF_AZ_BAR2_TYPE_WIDTH 2
+#define	PCRF_AZ_BAR2_IOM_LBN 0
+#define	PCRF_AZ_BAR2_IOM_WIDTH 1
+
+
+/*
+ * PC_BAR2_HI_REG(32bit):
+ * Primary function base address register 2 high bits
+ */
+
+#define	PCR_AZ_BAR2_HI_REG 0x0000001c
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_BAR2_HI_LBN 0
+#define	PCRF_AZ_BAR2_HI_WIDTH 32
+
+
+/*
+ * PC_BAR4_LO_REG(32bit):
+ * Primary function base address register 2 low bits
+ */
+
+#define	PCR_CZ_BAR4_LO_REG 0x00000020
+/* sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_CZ_BAR4_LO_LBN 4
+#define	PCRF_CZ_BAR4_LO_WIDTH 28
+#define	PCRF_CZ_BAR4_PREF_LBN 3
+#define	PCRF_CZ_BAR4_PREF_WIDTH 1
+#define	PCRF_CZ_BAR4_TYPE_LBN 1
+#define	PCRF_CZ_BAR4_TYPE_WIDTH 2
+#define	PCRF_CZ_BAR4_IOM_LBN 0
+#define	PCRF_CZ_BAR4_IOM_WIDTH 1
+
+
+/*
+ * PC_BAR4_HI_REG(32bit):
+ * Primary function base address register 2 high bits
+ */
+
+#define	PCR_CZ_BAR4_HI_REG 0x00000024
+/* sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_CZ_BAR4_HI_LBN 0
+#define	PCRF_CZ_BAR4_HI_WIDTH 32
+
+
+/*
+ * PC_SS_VEND_ID_REG(16bit):
+ * Sub-system vendor ID register
+ */
+
+#define	PCR_AZ_SS_VEND_ID_REG 0x0000002c
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_SS_VEND_ID_LBN 0
+#define	PCRF_AZ_SS_VEND_ID_WIDTH 16
+
+
+/*
+ * PC_SS_ID_REG(16bit):
+ * Sub-system ID register
+ */
+
+#define	PCR_AZ_SS_ID_REG 0x0000002e
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_SS_ID_LBN 0
+#define	PCRF_AZ_SS_ID_WIDTH 16
+
+
+/*
+ * PC_EXPROM_BAR_REG(32bit):
+ * Expansion ROM base address register
+ */
+
+#define	PCR_AZ_EXPROM_BAR_REG 0x00000030
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_EXPROM_BAR_LBN 11
+#define	PCRF_AZ_EXPROM_BAR_WIDTH 21
+#define	PCRF_AB_EXPROM_MIN_SIZE_LBN 2
+#define	PCRF_AB_EXPROM_MIN_SIZE_WIDTH 9
+#define	PCRF_CZ_EXPROM_MIN_SIZE_LBN 1
+#define	PCRF_CZ_EXPROM_MIN_SIZE_WIDTH 10
+#define	PCRF_AB_EXPROM_FEATURE_ENABLE_LBN 1
+#define	PCRF_AB_EXPROM_FEATURE_ENABLE_WIDTH 1
+#define	PCRF_AZ_EXPROM_EN_LBN 0
+#define	PCRF_AZ_EXPROM_EN_WIDTH 1
+
+
+/*
+ * PC_CAP_PTR_REG(8bit):
+ * Capability pointer register
+ */
+
+#define	PCR_AZ_CAP_PTR_REG 0x00000034
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_CAP_PTR_LBN 0
+#define	PCRF_AZ_CAP_PTR_WIDTH 8
+
+
+/*
+ * PC_INT_LINE_REG(8bit):
+ * Interrupt line register
+ */
+
+#define	PCR_AZ_INT_LINE_REG 0x0000003c
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_INT_LINE_LBN 0
+#define	PCRF_AZ_INT_LINE_WIDTH 8
+
+
+/*
+ * PC_INT_PIN_REG(8bit):
+ * Interrupt pin register
+ */
+
+#define	PCR_AZ_INT_PIN_REG 0x0000003d
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_INT_PIN_LBN 0
+#define	PCRF_AZ_INT_PIN_WIDTH 8
+
+
+/*
+ * PC_PM_CAP_ID_REG(8bit):
+ * Power management capability ID
+ */
+
+#define	PCR_AC_PM_CAP_ID_REG 0x00000040
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_PM_CAP_ID_REG 0x00000080
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_PM_CAP_ID_LBN 0
+#define	PCRF_AZ_PM_CAP_ID_WIDTH 8
+
+
+/*
+ * PC_PM_NXT_PTR_REG(8bit):
+ * Power management next item pointer
+ */
+
+#define	PCR_AC_PM_NXT_PTR_REG 0x00000041
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_PM_NXT_PTR_REG 0x00000081
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_PM_NXT_PTR_LBN 0
+#define	PCRF_AZ_PM_NXT_PTR_WIDTH 8
+
+
+/*
+ * PC_PM_CAP_REG(16bit):
+ * Power management capabilities register
+ */
+
+#define	PCR_AC_PM_CAP_REG 0x00000042
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_PM_CAP_REG 0x00000082
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_PM_PME_SUPT_LBN 11
+#define	PCRF_AZ_PM_PME_SUPT_WIDTH 5
+#define	PCRF_AZ_PM_D2_SUPT_LBN 10
+#define	PCRF_AZ_PM_D2_SUPT_WIDTH 1
+#define	PCRF_AZ_PM_D1_SUPT_LBN 9
+#define	PCRF_AZ_PM_D1_SUPT_WIDTH 1
+#define	PCRF_AZ_PM_AUX_CURR_LBN 6
+#define	PCRF_AZ_PM_AUX_CURR_WIDTH 3
+#define	PCRF_AZ_PM_DSI_LBN 5
+#define	PCRF_AZ_PM_DSI_WIDTH 1
+#define	PCRF_AZ_PM_PME_CLK_LBN 3
+#define	PCRF_AZ_PM_PME_CLK_WIDTH 1
+#define	PCRF_AZ_PM_PME_VER_LBN 0
+#define	PCRF_AZ_PM_PME_VER_WIDTH 3
+
+
+/*
+ * PC_PM_CS_REG(16bit):
+ * Power management control & status register
+ */
+
+#define	PCR_AC_PM_CS_REG 0x00000044
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_PM_CS_REG 0x00000084
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_PM_PME_STAT_LBN 15
+#define	PCRF_AZ_PM_PME_STAT_WIDTH 1
+#define	PCRF_AZ_PM_DAT_SCALE_LBN 13
+#define	PCRF_AZ_PM_DAT_SCALE_WIDTH 2
+#define	PCRF_AZ_PM_DAT_SEL_LBN 9
+#define	PCRF_AZ_PM_DAT_SEL_WIDTH 4
+#define	PCRF_AZ_PM_PME_EN_LBN 8
+#define	PCRF_AZ_PM_PME_EN_WIDTH 1
+#define	PCRF_CZ_NO_SOFT_RESET_LBN 3
+#define	PCRF_CZ_NO_SOFT_RESET_WIDTH 1
+#define	PCRF_AZ_PM_PWR_ST_LBN 0
+#define	PCRF_AZ_PM_PWR_ST_WIDTH 2
+
+
+/*
+ * PC_MSI_CAP_ID_REG(8bit):
+ * MSI capability ID
+ */
+
+#define	PCR_AC_MSI_CAP_ID_REG 0x00000050
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_MSI_CAP_ID_REG 0x00000090
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_MSI_CAP_ID_LBN 0
+#define	PCRF_AZ_MSI_CAP_ID_WIDTH 8
+
+
+/*
+ * PC_MSI_NXT_PTR_REG(8bit):
+ * MSI next item pointer
+ */
+
+#define	PCR_AC_MSI_NXT_PTR_REG 0x00000051
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_MSI_NXT_PTR_REG 0x00000091
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_MSI_NXT_PTR_LBN 0
+#define	PCRF_AZ_MSI_NXT_PTR_WIDTH 8
+
+
+/*
+ * PC_MSI_CTL_REG(16bit):
+ * MSI control register
+ */
+
+#define	PCR_AC_MSI_CTL_REG 0x00000052
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_MSI_CTL_REG 0x00000092
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_MSI_64_EN_LBN 7
+#define	PCRF_AZ_MSI_64_EN_WIDTH 1
+#define	PCRF_AZ_MSI_MULT_MSG_EN_LBN 4
+#define	PCRF_AZ_MSI_MULT_MSG_EN_WIDTH 3
+#define	PCRF_AZ_MSI_MULT_MSG_CAP_LBN 1
+#define	PCRF_AZ_MSI_MULT_MSG_CAP_WIDTH 3
+#define	PCRF_AZ_MSI_EN_LBN 0
+#define	PCRF_AZ_MSI_EN_WIDTH 1
+
+
+/*
+ * PC_MSI_ADR_LO_REG(32bit):
+ * MSI low 32 bits address register
+ */
+
+#define	PCR_AC_MSI_ADR_LO_REG 0x00000054
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_MSI_ADR_LO_REG 0x00000094
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_MSI_ADR_LO_LBN 2
+#define	PCRF_AZ_MSI_ADR_LO_WIDTH 30
+
+
+/*
+ * PC_VPD_CAP_CTL_REG(8bit):
+ * VPD control and capabilities register
+ */
+
+#define	PCR_DZ_VPD_CAP_CTL_REG 0x00000054
+/* hunta0=pci_f0_config */
+
+#define	PCR_CC_VPD_CAP_CTL_REG 0x000000d0
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CZ_VPD_FLAG_LBN 31
+#define	PCRF_CZ_VPD_FLAG_WIDTH 1
+#define	PCRF_CZ_VPD_ADDR_LBN 16
+#define	PCRF_CZ_VPD_ADDR_WIDTH 15
+#define	PCRF_CZ_VPD_NXT_PTR_LBN 8
+#define	PCRF_CZ_VPD_NXT_PTR_WIDTH 8
+#define	PCRF_CZ_VPD_CAP_ID_LBN 0
+#define	PCRF_CZ_VPD_CAP_ID_WIDTH 8
+
+
+/*
+ * PC_VPD_CAP_DATA_REG(32bit):
+ * documentation to be written for sum_PC_VPD_CAP_DATA_REG
+ */
+
+#define	PCR_DZ_VPD_CAP_DATA_REG 0x00000058
+/* hunta0=pci_f0_config */
+
+#define	PCR_AB_VPD_CAP_DATA_REG 0x000000b4
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_VPD_CAP_DATA_REG 0x000000d4
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_AZ_VPD_DATA_LBN 0
+#define	PCRF_AZ_VPD_DATA_WIDTH 32
+
+
+/*
+ * PC_MSI_ADR_HI_REG(32bit):
+ * MSI high 32 bits address register
+ */
+
+#define	PCR_AC_MSI_ADR_HI_REG 0x00000058
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_MSI_ADR_HI_REG 0x00000098
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_MSI_ADR_HI_LBN 0
+#define	PCRF_AZ_MSI_ADR_HI_WIDTH 32
+
+
+/*
+ * PC_MSI_DAT_REG(16bit):
+ * MSI data register
+ */
+
+#define	PCR_AC_MSI_DAT_REG 0x0000005c
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCR_DZ_MSI_DAT_REG 0x0000009c
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_MSI_DAT_LBN 0
+#define	PCRF_AZ_MSI_DAT_WIDTH 16
+
+
+/*
+ * PC_PCIE_CAP_LIST_REG(16bit):
+ * PCIe capability list register
+ */
+
+#define	PCR_AB_PCIE_CAP_LIST_REG 0x00000060
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_PCIE_CAP_LIST_REG 0x00000070
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_PCIE_CAP_LIST_REG 0x000000c0
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_PCIE_NXT_PTR_LBN 8
+#define	PCRF_AZ_PCIE_NXT_PTR_WIDTH 8
+#define	PCRF_AZ_PCIE_CAP_ID_LBN 0
+#define	PCRF_AZ_PCIE_CAP_ID_WIDTH 8
+
+
+/*
+ * PC_PCIE_CAP_REG(16bit):
+ * PCIe capability register
+ */
+
+#define	PCR_AB_PCIE_CAP_REG 0x00000062
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_PCIE_CAP_REG 0x00000072
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_PCIE_CAP_REG 0x000000c2
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_PCIE_INT_MSG_NUM_LBN 9
+#define	PCRF_AZ_PCIE_INT_MSG_NUM_WIDTH 5
+#define	PCRF_AZ_PCIE_SLOT_IMP_LBN 8
+#define	PCRF_AZ_PCIE_SLOT_IMP_WIDTH 1
+#define	PCRF_AZ_PCIE_DEV_PORT_TYPE_LBN 4
+#define	PCRF_AZ_PCIE_DEV_PORT_TYPE_WIDTH 4
+#define	PCRF_AZ_PCIE_CAP_VER_LBN 0
+#define	PCRF_AZ_PCIE_CAP_VER_WIDTH 4
+
+
+/*
+ * PC_DEV_CAP_REG(32bit):
+ * PCIe device capabilities register
+ */
+
+#define	PCR_AB_DEV_CAP_REG 0x00000064
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_DEV_CAP_REG 0x00000074
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_DEV_CAP_REG 0x000000c4
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_CAP_FN_LEVEL_RESET_LBN 28
+#define	PCRF_CZ_CAP_FN_LEVEL_RESET_WIDTH 1
+#define	PCRF_AZ_CAP_SLOT_PWR_SCL_LBN 26
+#define	PCRF_AZ_CAP_SLOT_PWR_SCL_WIDTH 2
+#define	PCRF_AZ_CAP_SLOT_PWR_VAL_LBN 18
+#define	PCRF_AZ_CAP_SLOT_PWR_VAL_WIDTH 8
+#define	PCRF_CZ_ROLE_BASE_ERR_REPORTING_LBN 15
+#define	PCRF_CZ_ROLE_BASE_ERR_REPORTING_WIDTH 1
+#define	PCRF_AB_PWR_IND_LBN 14
+#define	PCRF_AB_PWR_IND_WIDTH 1
+#define	PCRF_AB_ATTN_IND_LBN 13
+#define	PCRF_AB_ATTN_IND_WIDTH 1
+#define	PCRF_AB_ATTN_BUTTON_LBN 12
+#define	PCRF_AB_ATTN_BUTTON_WIDTH 1
+#define	PCRF_AZ_ENDPT_L1_LAT_LBN 9
+#define	PCRF_AZ_ENDPT_L1_LAT_WIDTH 3
+#define	PCRF_AZ_ENDPT_L0_LAT_LBN 6
+#define	PCRF_AZ_ENDPT_L0_LAT_WIDTH 3
+#define	PCRF_AZ_TAG_FIELD_LBN 5
+#define	PCRF_AZ_TAG_FIELD_WIDTH 1
+#define	PCRF_AZ_PHAN_FUNC_LBN 3
+#define	PCRF_AZ_PHAN_FUNC_WIDTH 2
+#define	PCRF_AZ_MAX_PAYL_SIZE_SUPT_LBN 0
+#define	PCRF_AZ_MAX_PAYL_SIZE_SUPT_WIDTH 3
+
+
+/*
+ * PC_DEV_CTL_REG(16bit):
+ * PCIe device control register
+ */
+
+#define	PCR_AB_DEV_CTL_REG 0x00000068
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_DEV_CTL_REG 0x00000078
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_DEV_CTL_REG 0x000000c8
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_FN_LEVEL_RESET_LBN 15
+#define	PCRF_CZ_FN_LEVEL_RESET_WIDTH 1
+#define	PCRF_AZ_MAX_RD_REQ_SIZE_LBN 12
+#define	PCRF_AZ_MAX_RD_REQ_SIZE_WIDTH 3
+#define	PCFE_AZ_MAX_RD_REQ_SIZE_4096 5
+#define	PCFE_AZ_MAX_RD_REQ_SIZE_2048 4
+#define	PCFE_AZ_MAX_RD_REQ_SIZE_1024 3
+#define	PCFE_AZ_MAX_RD_REQ_SIZE_512 2
+#define	PCFE_AZ_MAX_RD_REQ_SIZE_256 1
+#define	PCFE_AZ_MAX_RD_REQ_SIZE_128 0
+#define	PCFE_DZ_OTHER other
+#define	PCRF_AZ_EN_NO_SNOOP_LBN 11
+#define	PCRF_AZ_EN_NO_SNOOP_WIDTH 1
+#define	PCRF_AZ_AUX_PWR_PM_EN_LBN 10
+#define	PCRF_AZ_AUX_PWR_PM_EN_WIDTH 1
+#define	PCRF_AZ_PHAN_FUNC_EN_LBN 9
+#define	PCRF_AZ_PHAN_FUNC_EN_WIDTH 1
+#define	PCRF_AB_DEV_CAP_REG_RSVD0_LBN 8
+#define	PCRF_AB_DEV_CAP_REG_RSVD0_WIDTH 1
+#define	PCRF_CZ_EXTENDED_TAG_EN_LBN 8
+#define	PCRF_CZ_EXTENDED_TAG_EN_WIDTH 1
+#define	PCRF_AZ_MAX_PAYL_SIZE_LBN 5
+#define	PCRF_AZ_MAX_PAYL_SIZE_WIDTH 3
+#define	PCFE_AZ_MAX_PAYL_SIZE_4096 5
+#define	PCFE_AZ_MAX_PAYL_SIZE_2048 4
+#define	PCFE_AZ_MAX_PAYL_SIZE_1024 3
+#define	PCFE_AZ_MAX_PAYL_SIZE_512 2
+#define	PCFE_AZ_MAX_PAYL_SIZE_256 1
+#define	PCFE_AZ_MAX_PAYL_SIZE_128 0
+#define	PCFE_DZ_OTHER other
+#define	PCRF_AZ_EN_RELAX_ORDER_LBN 4
+#define	PCRF_AZ_EN_RELAX_ORDER_WIDTH 1
+#define	PCRF_AZ_UNSUP_REQ_RPT_EN_LBN 3
+#define	PCRF_AZ_UNSUP_REQ_RPT_EN_WIDTH 1
+#define	PCRF_AZ_FATAL_ERR_RPT_EN_LBN 2
+#define	PCRF_AZ_FATAL_ERR_RPT_EN_WIDTH 1
+#define	PCRF_AZ_NONFATAL_ERR_RPT_EN_LBN 1
+#define	PCRF_AZ_NONFATAL_ERR_RPT_EN_WIDTH 1
+#define	PCRF_AZ_CORR_ERR_RPT_EN_LBN 0
+#define	PCRF_AZ_CORR_ERR_RPT_EN_WIDTH 1
+
+
+/*
+ * PC_DEV_STAT_REG(16bit):
+ * PCIe device status register
+ */
+
+#define	PCR_AB_DEV_STAT_REG 0x0000006a
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_DEV_STAT_REG 0x0000007a
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_DEV_STAT_REG 0x000000ca
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_TRNS_PEND_LBN 5
+#define	PCRF_AZ_TRNS_PEND_WIDTH 1
+#define	PCRF_AZ_AUX_PWR_DET_LBN 4
+#define	PCRF_AZ_AUX_PWR_DET_WIDTH 1
+#define	PCRF_AZ_UNSUP_REQ_DET_LBN 3
+#define	PCRF_AZ_UNSUP_REQ_DET_WIDTH 1
+#define	PCRF_AZ_FATAL_ERR_DET_LBN 2
+#define	PCRF_AZ_FATAL_ERR_DET_WIDTH 1
+#define	PCRF_AZ_NONFATAL_ERR_DET_LBN 1
+#define	PCRF_AZ_NONFATAL_ERR_DET_WIDTH 1
+#define	PCRF_AZ_CORR_ERR_DET_LBN 0
+#define	PCRF_AZ_CORR_ERR_DET_WIDTH 1
+
+
+/*
+ * PC_LNK_CAP_REG(32bit):
+ * PCIe link capabilities register
+ */
+
+#define	PCR_AB_LNK_CAP_REG 0x0000006c
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_LNK_CAP_REG 0x0000007c
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_LNK_CAP_REG 0x000000cc
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_PORT_NUM_LBN 24
+#define	PCRF_AZ_PORT_NUM_WIDTH 8
+#define	PCRF_CZ_LINK_BWDITH_NOTIF_CAP_LBN 21
+#define	PCRF_CZ_LINK_BWDITH_NOTIF_CAP_WIDTH 1
+#define	PCRF_CZ_DATA_LINK_ACTIVE_RPT_CAP_LBN 20
+#define	PCRF_CZ_DATA_LINK_ACTIVE_RPT_CAP_WIDTH 1
+#define	PCRF_CZ_SURPISE_DOWN_RPT_CAP_LBN 19
+#define	PCRF_CZ_SURPISE_DOWN_RPT_CAP_WIDTH 1
+#define	PCRF_CZ_CLOCK_PWR_MNGMNT_CAP_LBN 18
+#define	PCRF_CZ_CLOCK_PWR_MNGMNT_CAP_WIDTH 1
+#define	PCRF_AZ_DEF_L1_EXIT_LAT_LBN 15
+#define	PCRF_AZ_DEF_L1_EXIT_LAT_WIDTH 3
+#define	PCRF_AZ_DEF_L0_EXIT_LATPORT_NUM_LBN 12
+#define	PCRF_AZ_DEF_L0_EXIT_LATPORT_NUM_WIDTH 3
+#define	PCRF_AZ_AS_LNK_PM_SUPT_LBN 10
+#define	PCRF_AZ_AS_LNK_PM_SUPT_WIDTH 2
+#define	PCRF_AZ_MAX_LNK_WIDTH_LBN 4
+#define	PCRF_AZ_MAX_LNK_WIDTH_WIDTH 6
+#define	PCRF_AZ_MAX_LNK_SP_LBN 0
+#define	PCRF_AZ_MAX_LNK_SP_WIDTH 4
+
+
+/*
+ * PC_LNK_CTL_REG(16bit):
+ * PCIe link control register
+ */
+
+#define	PCR_AB_LNK_CTL_REG 0x00000070
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_LNK_CTL_REG 0x00000080
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_LNK_CTL_REG 0x000000d0
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_EXT_SYNC_LBN 7
+#define	PCRF_AZ_EXT_SYNC_WIDTH 1
+#define	PCRF_AZ_COMM_CLK_CFG_LBN 6
+#define	PCRF_AZ_COMM_CLK_CFG_WIDTH 1
+#define	PCRF_AB_LNK_CTL_REG_RSVD0_LBN 5
+#define	PCRF_AB_LNK_CTL_REG_RSVD0_WIDTH 1
+#define	PCRF_CZ_LNK_RETRAIN_LBN 5
+#define	PCRF_CZ_LNK_RETRAIN_WIDTH 1
+#define	PCRF_AZ_LNK_DIS_LBN 4
+#define	PCRF_AZ_LNK_DIS_WIDTH 1
+#define	PCRF_AZ_RD_COM_BDRY_LBN 3
+#define	PCRF_AZ_RD_COM_BDRY_WIDTH 1
+#define	PCRF_AZ_ACT_ST_LNK_PM_CTL_LBN 0
+#define	PCRF_AZ_ACT_ST_LNK_PM_CTL_WIDTH 2
+
+
+/*
+ * PC_LNK_STAT_REG(16bit):
+ * PCIe link status register
+ */
+
+#define	PCR_AB_LNK_STAT_REG 0x00000072
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_LNK_STAT_REG 0x00000082
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_LNK_STAT_REG 0x000000d2
+/* hunta0=pci_f0_config */
+
+#define	PCRF_AZ_SLOT_CLK_CFG_LBN 12
+#define	PCRF_AZ_SLOT_CLK_CFG_WIDTH 1
+#define	PCRF_AZ_LNK_TRAIN_LBN 11
+#define	PCRF_AZ_LNK_TRAIN_WIDTH 1
+#define	PCRF_AB_TRAIN_ERR_LBN 10
+#define	PCRF_AB_TRAIN_ERR_WIDTH 1
+#define	PCRF_AZ_LNK_WIDTH_LBN 4
+#define	PCRF_AZ_LNK_WIDTH_WIDTH 6
+#define	PCRF_AZ_LNK_SP_LBN 0
+#define	PCRF_AZ_LNK_SP_WIDTH 4
+
+
+/*
+ * PC_SLOT_CAP_REG(32bit):
+ * PCIe slot capabilities register
+ */
+
+#define	PCR_AB_SLOT_CAP_REG 0x00000074
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCRF_AB_SLOT_NUM_LBN 19
+#define	PCRF_AB_SLOT_NUM_WIDTH 13
+#define	PCRF_AB_SLOT_PWR_LIM_SCL_LBN 15
+#define	PCRF_AB_SLOT_PWR_LIM_SCL_WIDTH 2
+#define	PCRF_AB_SLOT_PWR_LIM_VAL_LBN 7
+#define	PCRF_AB_SLOT_PWR_LIM_VAL_WIDTH 8
+#define	PCRF_AB_SLOT_HP_CAP_LBN 6
+#define	PCRF_AB_SLOT_HP_CAP_WIDTH 1
+#define	PCRF_AB_SLOT_HP_SURP_LBN 5
+#define	PCRF_AB_SLOT_HP_SURP_WIDTH 1
+#define	PCRF_AB_SLOT_PWR_IND_PRST_LBN 4
+#define	PCRF_AB_SLOT_PWR_IND_PRST_WIDTH 1
+#define	PCRF_AB_SLOT_ATTN_IND_PRST_LBN 3
+#define	PCRF_AB_SLOT_ATTN_IND_PRST_WIDTH 1
+#define	PCRF_AB_SLOT_MRL_SENS_PRST_LBN 2
+#define	PCRF_AB_SLOT_MRL_SENS_PRST_WIDTH 1
+#define	PCRF_AB_SLOT_PWR_CTL_PRST_LBN 1
+#define	PCRF_AB_SLOT_PWR_CTL_PRST_WIDTH 1
+#define	PCRF_AB_SLOT_ATTN_BUT_PRST_LBN 0
+#define	PCRF_AB_SLOT_ATTN_BUT_PRST_WIDTH 1
+
+
+/*
+ * PC_SLOT_CTL_REG(16bit):
+ * PCIe slot control register
+ */
+
+#define	PCR_AB_SLOT_CTL_REG 0x00000078
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCRF_AB_SLOT_PWR_CTLR_CTL_LBN 10
+#define	PCRF_AB_SLOT_PWR_CTLR_CTL_WIDTH 1
+#define	PCRF_AB_SLOT_PWR_IND_CTL_LBN 8
+#define	PCRF_AB_SLOT_PWR_IND_CTL_WIDTH 2
+#define	PCRF_AB_SLOT_ATT_IND_CTL_LBN 6
+#define	PCRF_AB_SLOT_ATT_IND_CTL_WIDTH 2
+#define	PCRF_AB_SLOT_HP_INT_EN_LBN 5
+#define	PCRF_AB_SLOT_HP_INT_EN_WIDTH 1
+#define	PCRF_AB_SLOT_CMD_COMP_INT_EN_LBN 4
+#define	PCRF_AB_SLOT_CMD_COMP_INT_EN_WIDTH 1
+#define	PCRF_AB_SLOT_PRES_DET_CHG_EN_LBN 3
+#define	PCRF_AB_SLOT_PRES_DET_CHG_EN_WIDTH 1
+#define	PCRF_AB_SLOT_MRL_SENS_CHG_EN_LBN 2
+#define	PCRF_AB_SLOT_MRL_SENS_CHG_EN_WIDTH 1
+#define	PCRF_AB_SLOT_PWR_FLTDET_EN_LBN 1
+#define	PCRF_AB_SLOT_PWR_FLTDET_EN_WIDTH 1
+#define	PCRF_AB_SLOT_ATTN_BUT_EN_LBN 0
+#define	PCRF_AB_SLOT_ATTN_BUT_EN_WIDTH 1
+
+
+/*
+ * PC_SLOT_STAT_REG(16bit):
+ * PCIe slot status register
+ */
+
+#define	PCR_AB_SLOT_STAT_REG 0x0000007a
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCRF_AB_PRES_DET_ST_LBN 6
+#define	PCRF_AB_PRES_DET_ST_WIDTH 1
+#define	PCRF_AB_MRL_SENS_ST_LBN 5
+#define	PCRF_AB_MRL_SENS_ST_WIDTH 1
+#define	PCRF_AB_SLOT_PWR_IND_LBN 4
+#define	PCRF_AB_SLOT_PWR_IND_WIDTH 1
+#define	PCRF_AB_SLOT_ATTN_IND_LBN 3
+#define	PCRF_AB_SLOT_ATTN_IND_WIDTH 1
+#define	PCRF_AB_SLOT_MRL_SENS_LBN 2
+#define	PCRF_AB_SLOT_MRL_SENS_WIDTH 1
+#define	PCRF_AB_PWR_FLTDET_LBN 1
+#define	PCRF_AB_PWR_FLTDET_WIDTH 1
+#define	PCRF_AB_ATTN_BUTDET_LBN 0
+#define	PCRF_AB_ATTN_BUTDET_WIDTH 1
+
+
+/*
+ * PC_MSIX_CAP_ID_REG(8bit):
+ * MSIX Capability ID
+ */
+
+#define	PCR_BB_MSIX_CAP_ID_REG 0x00000090
+/* falconb0=pci_f0_config */
+
+#define	PCR_CZ_MSIX_CAP_ID_REG 0x000000b0
+/* sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_BZ_MSIX_CAP_ID_LBN 0
+#define	PCRF_BZ_MSIX_CAP_ID_WIDTH 8
+
+
+/*
+ * PC_MSIX_NXT_PTR_REG(8bit):
+ * MSIX Capability Next Capability Ptr
+ */
+
+#define	PCR_BB_MSIX_NXT_PTR_REG 0x00000091
+/* falconb0=pci_f0_config */
+
+#define	PCR_CZ_MSIX_NXT_PTR_REG 0x000000b1
+/* sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_BZ_MSIX_NXT_PTR_LBN 0
+#define	PCRF_BZ_MSIX_NXT_PTR_WIDTH 8
+
+
+/*
+ * PC_MSIX_CTL_REG(16bit):
+ * MSIX control register
+ */
+
+#define	PCR_BB_MSIX_CTL_REG 0x00000092
+/* falconb0=pci_f0_config */
+
+#define	PCR_CZ_MSIX_CTL_REG 0x000000b2
+/* sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_BZ_MSIX_EN_LBN 15
+#define	PCRF_BZ_MSIX_EN_WIDTH 1
+#define	PCRF_BZ_MSIX_FUNC_MASK_LBN 14
+#define	PCRF_BZ_MSIX_FUNC_MASK_WIDTH 1
+#define	PCRF_BZ_MSIX_TBL_SIZE_LBN 0
+#define	PCRF_BZ_MSIX_TBL_SIZE_WIDTH 11
+
+
+/*
+ * PC_DEV_CAP2_REG(16bit):
+ * PCIe Device Capabilities 2
+ */
+
+#define	PCR_CC_DEV_CAP2_REG 0x00000094
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_DEV_CAP2_REG 0x000000e4
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_CMPL_TIMEOUT_DIS_LBN 4
+#define	PCRF_CZ_CMPL_TIMEOUT_DIS_WIDTH 1
+#define	PCRF_CZ_CMPL_TIMEOUT_LBN 0
+#define	PCRF_CZ_CMPL_TIMEOUT_WIDTH 4
+#define	PCFE_CZ_CMPL_TIMEOUT_17000_TO_6400MS 14
+#define	PCFE_CZ_CMPL_TIMEOUT_4000_TO_1300MS 13
+#define	PCFE_CZ_CMPL_TIMEOUT_1000_TO_3500MS 10
+#define	PCFE_CZ_CMPL_TIMEOUT_260_TO_900MS 9
+#define	PCFE_CZ_CMPL_TIMEOUT_65_TO_210MS 6
+#define	PCFE_CZ_CMPL_TIMEOUT_16_TO_55MS 5
+#define	PCFE_CZ_CMPL_TIMEOUT_1_TO_10MS 2
+#define	PCFE_CZ_CMPL_TIMEOUT_50_TO_100US 1
+#define	PCFE_CZ_CMPL_TIMEOUT_DEFAULT 0
+
+
+/*
+ * PC_MSIX_TBL_BASE_REG(32bit):
+ * MSIX Capability Vector Table Base
+ */
+
+#define	PCR_BB_MSIX_TBL_BASE_REG 0x00000094
+/* falconb0=pci_f0_config */
+
+#define	PCR_CZ_MSIX_TBL_BASE_REG 0x000000b4
+/* sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_BZ_MSIX_TBL_OFF_LBN 3
+#define	PCRF_BZ_MSIX_TBL_OFF_WIDTH 29
+#define	PCRF_BZ_MSIX_TBL_BIR_LBN 0
+#define	PCRF_BZ_MSIX_TBL_BIR_WIDTH 3
+
+
+/*
+ * PC_DEV_CTL2_REG(16bit):
+ * PCIe Device Control 2
+ */
+
+#define	PCR_CC_DEV_CTL2_REG 0x00000098
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_DEV_CTL2_REG 0x000000e8
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_CMPL_TIMEOUT_DIS_CTL_LBN 4
+#define	PCRF_CZ_CMPL_TIMEOUT_DIS_CTL_WIDTH 1
+#define	PCRF_CZ_CMPL_TIMEOUT_CTL_LBN 0
+#define	PCRF_CZ_CMPL_TIMEOUT_CTL_WIDTH 4
+
+
+/*
+ * PC_MSIX_PBA_BASE_REG(32bit):
+ * MSIX Capability PBA Base
+ */
+
+#define	PCR_BB_MSIX_PBA_BASE_REG 0x00000098
+/* falconb0=pci_f0_config */
+
+#define	PCR_CZ_MSIX_PBA_BASE_REG 0x000000b8
+/* sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_BZ_MSIX_PBA_OFF_LBN 3
+#define	PCRF_BZ_MSIX_PBA_OFF_WIDTH 29
+#define	PCRF_BZ_MSIX_PBA_BIR_LBN 0
+#define	PCRF_BZ_MSIX_PBA_BIR_WIDTH 3
+
+
+/*
+ * PC_LNK_CTL2_REG(16bit):
+ * PCIe Link Control 2
+ */
+
+#define	PCR_CC_LNK_CTL2_REG 0x000000a0
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_LNK_CTL2_REG 0x000000f0
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_POLLING_DEEMPH_LVL_LBN 12
+#define	PCRF_CZ_POLLING_DEEMPH_LVL_WIDTH 1
+#define	PCRF_CZ_COMPLIANCE_SOS_CTL_LBN 11
+#define	PCRF_CZ_COMPLIANCE_SOS_CTL_WIDTH 1
+#define	PCRF_CZ_ENTER_MODIFIED_COMPLIANCE_CTL_LBN 10
+#define	PCRF_CZ_ENTER_MODIFIED_COMPLIANCE_CTL_WIDTH 1
+#define	PCRF_CZ_TRANSMIT_MARGIN_LBN 7
+#define	PCRF_CZ_TRANSMIT_MARGIN_WIDTH 3
+#define	PCRF_CZ_SELECT_DEEMPH_LBN 6
+#define	PCRF_CZ_SELECT_DEEMPH_WIDTH 1
+#define	PCRF_CZ_HW_AUTONOMOUS_SPEED_DIS_LBN 5
+#define	PCRF_CZ_HW_AUTONOMOUS_SPEED_DIS_WIDTH 1
+#define	PCRF_CZ_ENTER_COMPLIANCE_CTL_LBN 4
+#define	PCRF_CZ_ENTER_COMPLIANCE_CTL_WIDTH 1
+#define	PCRF_CZ_TGT_LNK_SPEED_CTL_LBN 0
+#define	PCRF_CZ_TGT_LNK_SPEED_CTL_WIDTH 4
+
+
+/*
+ * PC_LNK_STAT2_REG(16bit):
+ * PCIe Link Status 2
+ */
+
+#define	PCR_CC_LNK_STAT2_REG 0x000000a2
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_LNK_STAT2_REG 0x000000f2
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_CURRENT_DEEMPH_LBN 0
+#define	PCRF_CZ_CURRENT_DEEMPH_WIDTH 1
+
+
+/*
+ * PC_VPD_CAP_ID_REG(8bit):
+ * VPD data register
+ */
+
+#define	PCR_AB_VPD_CAP_ID_REG 0x000000b0
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCRF_AB_VPD_CAP_ID_LBN 0
+#define	PCRF_AB_VPD_CAP_ID_WIDTH 8
+
+
+/*
+ * PC_VPD_NXT_PTR_REG(8bit):
+ * VPD next item pointer
+ */
+
+#define	PCR_AB_VPD_NXT_PTR_REG 0x000000b1
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCRF_AB_VPD_NXT_PTR_LBN 0
+#define	PCRF_AB_VPD_NXT_PTR_WIDTH 8
+
+
+/*
+ * PC_VPD_ADDR_REG(16bit):
+ * VPD address register
+ */
+
+#define	PCR_AB_VPD_ADDR_REG 0x000000b2
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCRF_AB_VPD_FLAG_LBN 15
+#define	PCRF_AB_VPD_FLAG_WIDTH 1
+#define	PCRF_AB_VPD_ADDR_LBN 0
+#define	PCRF_AB_VPD_ADDR_WIDTH 15
+
+
+/*
+ * PC_AER_CAP_HDR_REG(32bit):
+ * AER capability header register
+ */
+
+#define	PCR_AZ_AER_CAP_HDR_REG 0x00000100
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_AERCAPHDR_NXT_PTR_LBN 20
+#define	PCRF_AZ_AERCAPHDR_NXT_PTR_WIDTH 12
+#define	PCRF_AZ_AERCAPHDR_VER_LBN 16
+#define	PCRF_AZ_AERCAPHDR_VER_WIDTH 4
+#define	PCRF_AZ_AERCAPHDR_ID_LBN 0
+#define	PCRF_AZ_AERCAPHDR_ID_WIDTH 16
+
+
+/*
+ * PC_AER_UNCORR_ERR_STAT_REG(32bit):
+ * AER Uncorrectable error status register
+ */
+
+#define	PCR_AZ_AER_UNCORR_ERR_STAT_REG 0x00000104
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_UNSUPT_REQ_ERR_STAT_LBN 20
+#define	PCRF_AZ_UNSUPT_REQ_ERR_STAT_WIDTH 1
+#define	PCRF_AZ_ECRC_ERR_STAT_LBN 19
+#define	PCRF_AZ_ECRC_ERR_STAT_WIDTH 1
+#define	PCRF_AZ_MALF_TLP_STAT_LBN 18
+#define	PCRF_AZ_MALF_TLP_STAT_WIDTH 1
+#define	PCRF_AZ_RX_OVF_STAT_LBN 17
+#define	PCRF_AZ_RX_OVF_STAT_WIDTH 1
+#define	PCRF_AZ_UNEXP_COMP_STAT_LBN 16
+#define	PCRF_AZ_UNEXP_COMP_STAT_WIDTH 1
+#define	PCRF_AZ_COMP_ABRT_STAT_LBN 15
+#define	PCRF_AZ_COMP_ABRT_STAT_WIDTH 1
+#define	PCRF_AZ_COMP_TIMEOUT_STAT_LBN 14
+#define	PCRF_AZ_COMP_TIMEOUT_STAT_WIDTH 1
+#define	PCRF_AZ_FC_PROTO_ERR_STAT_LBN 13
+#define	PCRF_AZ_FC_PROTO_ERR_STAT_WIDTH 1
+#define	PCRF_AZ_PSON_TLP_STAT_LBN 12
+#define	PCRF_AZ_PSON_TLP_STAT_WIDTH 1
+#define	PCRF_AZ_DL_PROTO_ERR_STAT_LBN 4
+#define	PCRF_AZ_DL_PROTO_ERR_STAT_WIDTH 1
+#define	PCRF_AB_TRAIN_ERR_STAT_LBN 0
+#define	PCRF_AB_TRAIN_ERR_STAT_WIDTH 1
+
+
+/*
+ * PC_AER_UNCORR_ERR_MASK_REG(32bit):
+ * AER Uncorrectable error mask register
+ */
+
+#define	PCR_AZ_AER_UNCORR_ERR_MASK_REG 0x00000108
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_UNSUPT_REQ_ERR_MASK_LBN 20
+#define	PCRF_AZ_UNSUPT_REQ_ERR_MASK_WIDTH 1
+#define	PCRF_AZ_ECRC_ERR_MASK_LBN 19
+#define	PCRF_AZ_ECRC_ERR_MASK_WIDTH 1
+#define	PCRF_AZ_MALF_TLP_MASK_LBN 18
+#define	PCRF_AZ_MALF_TLP_MASK_WIDTH 1
+#define	PCRF_AZ_RX_OVF_MASK_LBN 17
+#define	PCRF_AZ_RX_OVF_MASK_WIDTH 1
+#define	PCRF_AZ_UNEXP_COMP_MASK_LBN 16
+#define	PCRF_AZ_UNEXP_COMP_MASK_WIDTH 1
+#define	PCRF_AZ_COMP_ABRT_MASK_LBN 15
+#define	PCRF_AZ_COMP_ABRT_MASK_WIDTH 1
+#define	PCRF_AZ_COMP_TIMEOUT_MASK_LBN 14
+#define	PCRF_AZ_COMP_TIMEOUT_MASK_WIDTH 1
+#define	PCRF_AZ_FC_PROTO_ERR_MASK_LBN 13
+#define	PCRF_AZ_FC_PROTO_ERR_MASK_WIDTH 1
+#define	PCRF_AZ_PSON_TLP_MASK_LBN 12
+#define	PCRF_AZ_PSON_TLP_MASK_WIDTH 1
+#define	PCRF_AZ_DL_PROTO_ERR_MASK_LBN 4
+#define	PCRF_AZ_DL_PROTO_ERR_MASK_WIDTH 1
+#define	PCRF_AB_TRAIN_ERR_MASK_LBN 0
+#define	PCRF_AB_TRAIN_ERR_MASK_WIDTH 1
+
+
+/*
+ * PC_AER_UNCORR_ERR_SEV_REG(32bit):
+ * AER Uncorrectable error severity register
+ */
+
+#define	PCR_AZ_AER_UNCORR_ERR_SEV_REG 0x0000010c
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_UNSUPT_REQ_ERR_SEV_LBN 20
+#define	PCRF_AZ_UNSUPT_REQ_ERR_SEV_WIDTH 1
+#define	PCRF_AZ_ECRC_ERR_SEV_LBN 19
+#define	PCRF_AZ_ECRC_ERR_SEV_WIDTH 1
+#define	PCRF_AZ_MALF_TLP_SEV_LBN 18
+#define	PCRF_AZ_MALF_TLP_SEV_WIDTH 1
+#define	PCRF_AZ_RX_OVF_SEV_LBN 17
+#define	PCRF_AZ_RX_OVF_SEV_WIDTH 1
+#define	PCRF_AZ_UNEXP_COMP_SEV_LBN 16
+#define	PCRF_AZ_UNEXP_COMP_SEV_WIDTH 1
+#define	PCRF_AZ_COMP_ABRT_SEV_LBN 15
+#define	PCRF_AZ_COMP_ABRT_SEV_WIDTH 1
+#define	PCRF_AZ_COMP_TIMEOUT_SEV_LBN 14
+#define	PCRF_AZ_COMP_TIMEOUT_SEV_WIDTH 1
+#define	PCRF_AZ_FC_PROTO_ERR_SEV_LBN 13
+#define	PCRF_AZ_FC_PROTO_ERR_SEV_WIDTH 1
+#define	PCRF_AZ_PSON_TLP_SEV_LBN 12
+#define	PCRF_AZ_PSON_TLP_SEV_WIDTH 1
+#define	PCRF_AZ_DL_PROTO_ERR_SEV_LBN 4
+#define	PCRF_AZ_DL_PROTO_ERR_SEV_WIDTH 1
+#define	PCRF_AB_TRAIN_ERR_SEV_LBN 0
+#define	PCRF_AB_TRAIN_ERR_SEV_WIDTH 1
+
+
+/*
+ * PC_AER_CORR_ERR_STAT_REG(32bit):
+ * AER Correctable error status register
+ */
+
+#define	PCR_AZ_AER_CORR_ERR_STAT_REG 0x00000110
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_CZ_ADVSY_NON_FATAL_STAT_LBN 13
+#define	PCRF_CZ_ADVSY_NON_FATAL_STAT_WIDTH 1
+#define	PCRF_AZ_RPLY_TMR_TOUT_STAT_LBN 12
+#define	PCRF_AZ_RPLY_TMR_TOUT_STAT_WIDTH 1
+#define	PCRF_AZ_RPLAY_NUM_RO_STAT_LBN 8
+#define	PCRF_AZ_RPLAY_NUM_RO_STAT_WIDTH 1
+#define	PCRF_AZ_BAD_DLLP_STAT_LBN 7
+#define	PCRF_AZ_BAD_DLLP_STAT_WIDTH 1
+#define	PCRF_AZ_BAD_TLP_STAT_LBN 6
+#define	PCRF_AZ_BAD_TLP_STAT_WIDTH 1
+#define	PCRF_AZ_RX_ERR_STAT_LBN 0
+#define	PCRF_AZ_RX_ERR_STAT_WIDTH 1
+
+
+/*
+ * PC_AER_CORR_ERR_MASK_REG(32bit):
+ * AER Correctable error status register
+ */
+
+#define	PCR_AZ_AER_CORR_ERR_MASK_REG 0x00000114
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_CZ_ADVSY_NON_FATAL_MASK_LBN 13
+#define	PCRF_CZ_ADVSY_NON_FATAL_MASK_WIDTH 1
+#define	PCRF_AZ_RPLY_TMR_TOUT_MASK_LBN 12
+#define	PCRF_AZ_RPLY_TMR_TOUT_MASK_WIDTH 1
+#define	PCRF_AZ_RPLAY_NUM_RO_MASK_LBN 8
+#define	PCRF_AZ_RPLAY_NUM_RO_MASK_WIDTH 1
+#define	PCRF_AZ_BAD_DLLP_MASK_LBN 7
+#define	PCRF_AZ_BAD_DLLP_MASK_WIDTH 1
+#define	PCRF_AZ_BAD_TLP_MASK_LBN 6
+#define	PCRF_AZ_BAD_TLP_MASK_WIDTH 1
+#define	PCRF_AZ_RX_ERR_MASK_LBN 0
+#define	PCRF_AZ_RX_ERR_MASK_WIDTH 1
+
+
+/*
+ * PC_AER_CAP_CTL_REG(32bit):
+ * AER capability and control register
+ */
+
+#define	PCR_AZ_AER_CAP_CTL_REG 0x00000118
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_ECRC_CHK_EN_LBN 8
+#define	PCRF_AZ_ECRC_CHK_EN_WIDTH 1
+#define	PCRF_AZ_ECRC_CHK_CAP_LBN 7
+#define	PCRF_AZ_ECRC_CHK_CAP_WIDTH 1
+#define	PCRF_AZ_ECRC_GEN_EN_LBN 6
+#define	PCRF_AZ_ECRC_GEN_EN_WIDTH 1
+#define	PCRF_AZ_ECRC_GEN_CAP_LBN 5
+#define	PCRF_AZ_ECRC_GEN_CAP_WIDTH 1
+#define	PCRF_AZ_1ST_ERR_PTR_LBN 0
+#define	PCRF_AZ_1ST_ERR_PTR_WIDTH 5
+
+
+/*
+ * PC_AER_HDR_LOG_REG(128bit):
+ * AER Header log register
+ */
+
+#define	PCR_AZ_AER_HDR_LOG_REG 0x0000011c
+/* falcona0,falconb0,sienaa0,hunta0=pci_f0_config */
+
+#define	PCRF_AZ_HDR_LOG_LBN 0
+#define	PCRF_AZ_HDR_LOG_WIDTH 128
+
+
+/*
+ * PC_DEVSN_CAP_HDR_REG(32bit):
+ * Device serial number capability header register
+ */
+
+#define	PCR_DZ_DEVSN_CAP_HDR_REG 0x00000130
+/* hunta0=pci_f0_config */
+
+#define	PCR_CC_DEVSN_CAP_HDR_REG 0x00000140
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CZ_DEVSNCAPHDR_NXT_PTR_LBN 20
+#define	PCRF_CZ_DEVSNCAPHDR_NXT_PTR_WIDTH 12
+#define	PCRF_CZ_DEVSNCAPHDR_VER_LBN 16
+#define	PCRF_CZ_DEVSNCAPHDR_VER_WIDTH 4
+#define	PCRF_CZ_DEVSNCAPHDR_ID_LBN 0
+#define	PCRF_CZ_DEVSNCAPHDR_ID_WIDTH 16
+
+
+/*
+ * PC_DEVSN_DWORD0_REG(32bit):
+ * Device serial number DWORD0
+ */
+
+#define	PCR_DZ_DEVSN_DWORD0_REG 0x00000134
+/* hunta0=pci_f0_config */
+
+#define	PCR_CC_DEVSN_DWORD0_REG 0x00000144
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CZ_DEVSN_DWORD0_LBN 0
+#define	PCRF_CZ_DEVSN_DWORD0_WIDTH 32
+
+
+/*
+ * PC_DEVSN_DWORD1_REG(32bit):
+ * Device serial number DWORD0
+ */
+
+#define	PCR_DZ_DEVSN_DWORD1_REG 0x00000138
+/* hunta0=pci_f0_config */
+
+#define	PCR_CC_DEVSN_DWORD1_REG 0x00000148
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CZ_DEVSN_DWORD1_LBN 0
+#define	PCRF_CZ_DEVSN_DWORD1_WIDTH 32
+
+
+/*
+ * PC_ARI_CAP_HDR_REG(32bit):
+ * ARI capability header register
+ */
+
+#define	PCR_DZ_ARI_CAP_HDR_REG 0x00000140
+/* hunta0=pci_f0_config */
+
+#define	PCR_CC_ARI_CAP_HDR_REG 0x00000150
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CZ_ARICAPHDR_NXT_PTR_LBN 20
+#define	PCRF_CZ_ARICAPHDR_NXT_PTR_WIDTH 12
+#define	PCRF_CZ_ARICAPHDR_VER_LBN 16
+#define	PCRF_CZ_ARICAPHDR_VER_WIDTH 4
+#define	PCRF_CZ_ARICAPHDR_ID_LBN 0
+#define	PCRF_CZ_ARICAPHDR_ID_WIDTH 16
+
+
+/*
+ * PC_ARI_CAP_REG(16bit):
+ * ARI Capabilities
+ */
+
+#define	PCR_DZ_ARI_CAP_REG 0x00000144
+/* hunta0=pci_f0_config */
+
+#define	PCR_CC_ARI_CAP_REG 0x00000154
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CZ_ARI_NXT_FN_NUM_LBN 8
+#define	PCRF_CZ_ARI_NXT_FN_NUM_WIDTH 8
+#define	PCRF_CZ_ARI_ACS_FNGRP_CAP_LBN 1
+#define	PCRF_CZ_ARI_ACS_FNGRP_CAP_WIDTH 1
+#define	PCRF_CZ_ARI_MFVC_FNGRP_CAP_LBN 0
+#define	PCRF_CZ_ARI_MFVC_FNGRP_CAP_WIDTH 1
+
+
+/*
+ * PC_ARI_CTL_REG(16bit):
+ * ARI Control
+ */
+
+#define	PCR_DZ_ARI_CTL_REG 0x00000146
+/* hunta0=pci_f0_config */
+
+#define	PCR_CC_ARI_CTL_REG 0x00000156
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CZ_ARI_FN_GRP_LBN 4
+#define	PCRF_CZ_ARI_FN_GRP_WIDTH 3
+#define	PCRF_CZ_ARI_ACS_FNGRP_EN_LBN 1
+#define	PCRF_CZ_ARI_ACS_FNGRP_EN_WIDTH 1
+#define	PCRF_CZ_ARI_MFVC_FNGRP_EN_LBN 0
+#define	PCRF_CZ_ARI_MFVC_FNGRP_EN_WIDTH 1
+
+
+/*
+ * PC_SRIOV_CAP_HDR_REG(32bit):
+ * SRIOV capability header register
+ */
+
+#define	PCR_CC_SRIOV_CAP_HDR_REG 0x00000160
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_CAP_HDR_REG 0x00000200
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_SRIOVCAPHDR_NXT_PTR_LBN 20
+#define	PCRF_CZ_SRIOVCAPHDR_NXT_PTR_WIDTH 12
+#define	PCRF_CZ_SRIOVCAPHDR_VER_LBN 16
+#define	PCRF_CZ_SRIOVCAPHDR_VER_WIDTH 4
+#define	PCRF_CZ_SRIOVCAPHDR_ID_LBN 0
+#define	PCRF_CZ_SRIOVCAPHDR_ID_WIDTH 16
+
+
+/*
+ * PC_SRIOV_CAP_REG(32bit):
+ * SRIOV Capabilities
+ */
+
+#define	PCR_CC_SRIOV_CAP_REG 0x00000164
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_CAP_REG 0x00000204
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_MIGR_INT_MSG_NUM_LBN 21
+#define	PCRF_CZ_VF_MIGR_INT_MSG_NUM_WIDTH 11
+#define	PCRF_CZ_VF_MIGR_CAP_LBN 0
+#define	PCRF_CZ_VF_MIGR_CAP_WIDTH 1
+
+
+/*
+ * PC_SRIOV_CTL_REG(16bit):
+ * SRIOV Control
+ */
+
+#define	PCR_CC_SRIOV_CTL_REG 0x00000168
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_CTL_REG 0x00000208
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_ARI_CAP_HRCHY_LBN 4
+#define	PCRF_CZ_VF_ARI_CAP_HRCHY_WIDTH 1
+#define	PCRF_CZ_VF_MSE_LBN 3
+#define	PCRF_CZ_VF_MSE_WIDTH 1
+#define	PCRF_CZ_VF_MIGR_INT_EN_LBN 2
+#define	PCRF_CZ_VF_MIGR_INT_EN_WIDTH 1
+#define	PCRF_CZ_VF_MIGR_EN_LBN 1
+#define	PCRF_CZ_VF_MIGR_EN_WIDTH 1
+#define	PCRF_CZ_VF_EN_LBN 0
+#define	PCRF_CZ_VF_EN_WIDTH 1
+
+
+/*
+ * PC_SRIOV_STAT_REG(16bit):
+ * SRIOV Status
+ */
+
+#define	PCR_CC_SRIOV_STAT_REG 0x0000016a
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_STAT_REG 0x0000020a
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_MIGR_STAT_LBN 0
+#define	PCRF_CZ_VF_MIGR_STAT_WIDTH 1
+
+
+/*
+ * PC_SRIOV_INITIALVFS_REG(16bit):
+ * SRIOV Initial VFs
+ */
+
+#define	PCR_CC_SRIOV_INITIALVFS_REG 0x0000016c
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_INITIALVFS_REG 0x0000020c
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_INITIALVFS_LBN 0
+#define	PCRF_CZ_VF_INITIALVFS_WIDTH 16
+
+
+/*
+ * PC_SRIOV_TOTALVFS_REG(10bit):
+ * SRIOV Total VFs
+ */
+
+#define	PCR_CC_SRIOV_TOTALVFS_REG 0x0000016e
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_TOTALVFS_REG 0x0000020e
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_TOTALVFS_LBN 0
+#define	PCRF_CZ_VF_TOTALVFS_WIDTH 16
+
+
+/*
+ * PC_SRIOV_NUMVFS_REG(16bit):
+ * SRIOV Number of VFs
+ */
+
+#define	PCR_CC_SRIOV_NUMVFS_REG 0x00000170
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_NUMVFS_REG 0x00000210
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_NUMVFS_LBN 0
+#define	PCRF_CZ_VF_NUMVFS_WIDTH 16
+
+
+/*
+ * PC_SRIOV_FN_DPND_LNK_REG(16bit):
+ * SRIOV Function dependency link
+ */
+
+#define	PCR_CC_SRIOV_FN_DPND_LNK_REG 0x00000172
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_FN_DPND_LNK_REG 0x00000212
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_SRIOV_FN_DPND_LNK_LBN 0
+#define	PCRF_CZ_SRIOV_FN_DPND_LNK_WIDTH 8
+
+
+/*
+ * PC_SRIOV_1STVF_OFFSET_REG(16bit):
+ * SRIOV First VF Offset
+ */
+
+#define	PCR_CC_SRIOV_1STVF_OFFSET_REG 0x00000174
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_1STVF_OFFSET_REG 0x00000214
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_1STVF_OFFSET_LBN 0
+#define	PCRF_CZ_VF_1STVF_OFFSET_WIDTH 16
+
+
+/*
+ * PC_SRIOV_VFSTRIDE_REG(16bit):
+ * SRIOV VF Stride
+ */
+
+#define	PCR_CC_SRIOV_VFSTRIDE_REG 0x00000176
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_VFSTRIDE_REG 0x00000216
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_VFSTRIDE_LBN 0
+#define	PCRF_CZ_VF_VFSTRIDE_WIDTH 16
+
+
+/*
+ * PC_SRIOV_DEVID_REG(16bit):
+ * SRIOV VF Device ID
+ */
+
+#define	PCR_CC_SRIOV_DEVID_REG 0x0000017a
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_DEVID_REG 0x0000021a
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_DEVID_LBN 0
+#define	PCRF_CZ_VF_DEVID_WIDTH 16
+
+
+/*
+ * PC_SRIOV_SUP_PAGESZ_REG(16bit):
+ * SRIOV Supported Page Sizes
+ */
+
+#define	PCR_CC_SRIOV_SUP_PAGESZ_REG 0x0000017c
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_SUP_PAGESZ_REG 0x0000021c
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_SUP_PAGESZ_LBN 0
+#define	PCRF_CZ_VF_SUP_PAGESZ_WIDTH 16
+
+
+/*
+ * PC_SRIOV_SYS_PAGESZ_REG(32bit):
+ * SRIOV System Page Size
+ */
+
+#define	PCR_CC_SRIOV_SYS_PAGESZ_REG 0x00000180
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_SYS_PAGESZ_REG 0x00000220
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_SYS_PAGESZ_LBN 0
+#define	PCRF_CZ_VF_SYS_PAGESZ_WIDTH 16
+
+
+/*
+ * PC_SRIOV_BAR0_REG(32bit):
+ * SRIOV VF Bar0
+ */
+
+#define	PCR_CC_SRIOV_BAR0_REG 0x00000184
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_BAR0_REG 0x00000224
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CC_VF_BAR_ADDRESS_LBN 0
+#define	PCRF_CC_VF_BAR_ADDRESS_WIDTH 32
+#define	PCRF_DZ_VF_BAR0_ADDRESS_LBN 0
+#define	PCRF_DZ_VF_BAR0_ADDRESS_WIDTH 32
+
+
+/*
+ * PC_SRIOV_BAR1_REG(32bit):
+ * SRIOV Bar1
+ */
+
+#define	PCR_CC_SRIOV_BAR1_REG 0x00000188
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_BAR1_REG 0x00000228
+/* hunta0=pci_f0_config */
+
+/* defined as PCRF_CC_VF_BAR_ADDRESS_LBN 0; */
+/* defined as PCRF_CC_VF_BAR_ADDRESS_WIDTH 32 */
+#define	PCRF_DZ_VF_BAR1_ADDRESS_LBN 0
+#define	PCRF_DZ_VF_BAR1_ADDRESS_WIDTH 32
+
+
+/*
+ * PC_SRIOV_BAR2_REG(32bit):
+ * SRIOV Bar2
+ */
+
+#define	PCR_CC_SRIOV_BAR2_REG 0x0000018c
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_BAR2_REG 0x0000022c
+/* hunta0=pci_f0_config */
+
+/* defined as PCRF_CC_VF_BAR_ADDRESS_LBN 0; */
+/* defined as PCRF_CC_VF_BAR_ADDRESS_WIDTH 32 */
+#define	PCRF_DZ_VF_BAR2_ADDRESS_LBN 0
+#define	PCRF_DZ_VF_BAR2_ADDRESS_WIDTH 32
+
+
+/*
+ * PC_SRIOV_BAR3_REG(32bit):
+ * SRIOV Bar3
+ */
+
+#define	PCR_CC_SRIOV_BAR3_REG 0x00000190
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_BAR3_REG 0x00000230
+/* hunta0=pci_f0_config */
+
+/* defined as PCRF_CC_VF_BAR_ADDRESS_LBN 0; */
+/* defined as PCRF_CC_VF_BAR_ADDRESS_WIDTH 32 */
+#define	PCRF_DZ_VF_BAR3_ADDRESS_LBN 0
+#define	PCRF_DZ_VF_BAR3_ADDRESS_WIDTH 32
+
+
+/*
+ * PC_SRIOV_BAR4_REG(32bit):
+ * SRIOV Bar4
+ */
+
+#define	PCR_CC_SRIOV_BAR4_REG 0x00000194
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_BAR4_REG 0x00000234
+/* hunta0=pci_f0_config */
+
+/* defined as PCRF_CC_VF_BAR_ADDRESS_LBN 0; */
+/* defined as PCRF_CC_VF_BAR_ADDRESS_WIDTH 32 */
+#define	PCRF_DZ_VF_BAR4_ADDRESS_LBN 0
+#define	PCRF_DZ_VF_BAR4_ADDRESS_WIDTH 32
+
+
+/*
+ * PC_SRIOV_BAR5_REG(32bit):
+ * SRIOV Bar5
+ */
+
+#define	PCR_CC_SRIOV_BAR5_REG 0x00000198
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_BAR5_REG 0x00000238
+/* hunta0=pci_f0_config */
+
+/* defined as PCRF_CC_VF_BAR_ADDRESS_LBN 0; */
+/* defined as PCRF_CC_VF_BAR_ADDRESS_WIDTH 32 */
+#define	PCRF_DZ_VF_BAR5_ADDRESS_LBN 0
+#define	PCRF_DZ_VF_BAR5_ADDRESS_WIDTH 32
+
+
+/*
+ * PC_SRIOV_MIBR_SARRAY_OFFSET_REG(32bit):
+ * SRIOV VF Migration State Array Offset
+ */
+
+#define	PCR_CC_SRIOV_MIBR_SARRAY_OFFSET_REG 0x0000019c
+/* sienaa0=pci_f0_config */
+
+#define	PCR_DZ_SRIOV_MIBR_SARRAY_OFFSET_REG 0x0000023c
+/* hunta0=pci_f0_config */
+
+#define	PCRF_CZ_VF_MIGR_OFFSET_LBN 3
+#define	PCRF_CZ_VF_MIGR_OFFSET_WIDTH 29
+#define	PCRF_CZ_VF_MIGR_BIR_LBN 0
+#define	PCRF_CZ_VF_MIGR_BIR_WIDTH 3
+
+
+/*
+ * PC_LTR_CAP_HDR_REG(32bit):
+ * Latency Tolerance Reporting Cap Header Reg
+ */
+
+#define	PCR_DZ_LTR_CAP_HDR_REG 0x00000240
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_LTR_NXT_PTR_LBN 20
+#define	PCRF_DZ_LTR_NXT_PTR_WIDTH 12
+#define	PCRF_DZ_LTR_VERSION_LBN 16
+#define	PCRF_DZ_LTR_VERSION_WIDTH 4
+#define	PCRF_DZ_LTR_EXT_CAP_ID_LBN 0
+#define	PCRF_DZ_LTR_EXT_CAP_ID_WIDTH 16
+
+
+/*
+ * PC_LTR_MAX_SNOOP_REG(32bit):
+ * LTR Maximum Snoop/No Snoop Register
+ */
+
+#define	PCR_DZ_LTR_MAX_SNOOP_REG 0x00000244
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_LTR_MAX_NOSNOOP_SCALE_LBN 26
+#define	PCRF_DZ_LTR_MAX_NOSNOOP_SCALE_WIDTH 3
+#define	PCRF_DZ_LTR_MAX_NOSNOOP_LAT_LBN 16
+#define	PCRF_DZ_LTR_MAX_NOSNOOP_LAT_WIDTH 10
+#define	PCRF_DZ_LTR_MAX_SNOOP_SCALE_LBN 10
+#define	PCRF_DZ_LTR_MAX_SNOOP_SCALE_WIDTH 3
+#define	PCRF_DZ_LTR_MAX_SNOOP_LAT_LBN 0
+#define	PCRF_DZ_LTR_MAX_SNOOP_LAT_WIDTH 10
+
+
+/*
+ * PC_TPH_CAP_HDR_REG(32bit):
+ * TPH Capability Header Register
+ */
+
+#define	PCR_DZ_TPH_CAP_HDR_REG 0x00000274
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_TPH_NXT_PTR_LBN 20
+#define	PCRF_DZ_TPH_NXT_PTR_WIDTH 12
+#define	PCRF_DZ_TPH_VERSION_LBN 16
+#define	PCRF_DZ_TPH_VERSION_WIDTH 4
+#define	PCRF_DZ_TPH_EXT_CAP_ID_LBN 0
+#define	PCRF_DZ_TPH_EXT_CAP_ID_WIDTH 16
+
+
+/*
+ * PC_TPH_REQ_CAP_REG(32bit):
+ * TPH Requester Capability Register
+ */
+
+#define	PCR_DZ_TPH_REQ_CAP_REG 0x00000278
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_ST_TBLE_SIZE_LBN 16
+#define	PCRF_DZ_ST_TBLE_SIZE_WIDTH 11
+#define	PCRF_DZ_ST_TBLE_LOC_LBN 9
+#define	PCRF_DZ_ST_TBLE_LOC_WIDTH 2
+#define	PCRF_DZ_EXT_TPH_MODE_SUP_LBN 8
+#define	PCRF_DZ_EXT_TPH_MODE_SUP_WIDTH 1
+#define	PCRF_DZ_TPH_DEV_MODE_SUP_LBN 2
+#define	PCRF_DZ_TPH_DEV_MODE_SUP_WIDTH 1
+#define	PCRF_DZ_TPH_INT_MODE_SUP_LBN 1
+#define	PCRF_DZ_TPH_INT_MODE_SUP_WIDTH 1
+#define	PCRF_DZ_TPH_NOST_MODE_SUP_LBN 0
+#define	PCRF_DZ_TPH_NOST_MODE_SUP_WIDTH 1
+
+
+/*
+ * PC_TPH_REQ_CTL_REG(32bit):
+ * TPH Requester Control Register
+ */
+
+#define	PCR_DZ_TPH_REQ_CTL_REG 0x0000027c
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_TPH_REQ_ENABLE_LBN 8
+#define	PCRF_DZ_TPH_REQ_ENABLE_WIDTH 2
+#define	PCRF_DZ_TPH_ST_MODE_LBN 0
+#define	PCRF_DZ_TPH_ST_MODE_WIDTH 3
+
+
+/*
+ * PC_SEC_PCIE_CAP_REG(32bit):
+ * Secondary PCIE Capability Register
+ */
+
+#define	PCR_DZ_SEC_PCIE_CAP_REG 0x00000300
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_SEC_NXT_PTR_LBN 20
+#define	PCRF_DZ_SEC_NXT_PTR_WIDTH 12
+#define	PCRF_DZ_SEC_VERSION_LBN 16
+#define	PCRF_DZ_SEC_VERSION_WIDTH 4
+#define	PCRF_DZ_SEC_EXT_CAP_ID_LBN 0
+#define	PCRF_DZ_SEC_EXT_CAP_ID_WIDTH 16
+
+
+/*
+ * PC_LINK_CONTROL3_REG(32bit):
+ * Link Control 3.
+ */
+
+#define	PCR_DZ_LINK_CONTROL3_REG 0x00000304
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_LINK_EQ_INT_EN_LBN 1
+#define	PCRF_DZ_LINK_EQ_INT_EN_WIDTH 1
+#define	PCRF_DZ_PERFORM_EQL_LBN 0
+#define	PCRF_DZ_PERFORM_EQL_WIDTH 1
+
+
+/*
+ * PC_LANE_ERROR_STAT_REG(32bit):
+ * Lane Error Status Register.
+ */
+
+#define	PCR_DZ_LANE_ERROR_STAT_REG 0x00000308
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_LANE_STATUS_LBN 0
+#define	PCRF_DZ_LANE_STATUS_WIDTH 8
+
+
+/*
+ * PC_LANE01_EQU_CONTROL_REG(32bit):
+ * Lanes 0,1 Equalization Control Register.
+ */
+
+#define	PCR_DZ_LANE01_EQU_CONTROL_REG 0x0000030c
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_LANE1_EQ_CTRL_LBN 16
+#define	PCRF_DZ_LANE1_EQ_CTRL_WIDTH 16
+#define	PCRF_DZ_LANE0_EQ_CTRL_LBN 0
+#define	PCRF_DZ_LANE0_EQ_CTRL_WIDTH 16
+
+
+/*
+ * PC_LANE23_EQU_CONTROL_REG(32bit):
+ * Lanes 2,3 Equalization Control Register.
+ */
+
+#define	PCR_DZ_LANE23_EQU_CONTROL_REG 0x00000310
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_LANE3_EQ_CTRL_LBN 16
+#define	PCRF_DZ_LANE3_EQ_CTRL_WIDTH 16
+#define	PCRF_DZ_LANE2_EQ_CTRL_LBN 0
+#define	PCRF_DZ_LANE2_EQ_CTRL_WIDTH 16
+
+
+/*
+ * PC_LANE45_EQU_CONTROL_REG(32bit):
+ * Lanes 4,5 Equalization Control Register.
+ */
+
+#define	PCR_DZ_LANE45_EQU_CONTROL_REG 0x00000314
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_LANE5_EQ_CTRL_LBN 16
+#define	PCRF_DZ_LANE5_EQ_CTRL_WIDTH 16
+#define	PCRF_DZ_LANE4_EQ_CTRL_LBN 0
+#define	PCRF_DZ_LANE4_EQ_CTRL_WIDTH 16
+
+
+/*
+ * PC_LANE67_EQU_CONTROL_REG(32bit):
+ * Lanes 6,7 Equalization Control Register.
+ */
+
+#define	PCR_DZ_LANE67_EQU_CONTROL_REG 0x00000318
+/* hunta0=pci_f0_config */
+
+#define	PCRF_DZ_LANE7_EQ_CTRL_LBN 16
+#define	PCRF_DZ_LANE7_EQ_CTRL_WIDTH 16
+#define	PCRF_DZ_LANE6_EQ_CTRL_LBN 0
+#define	PCRF_DZ_LANE6_EQ_CTRL_WIDTH 16
+
+
+/*
+ * PC_ACK_LAT_TMR_REG(32bit):
+ * ACK latency timer & replay timer register
+ */
+
+#define	PCR_AC_ACK_LAT_TMR_REG 0x00000700
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_RT_LBN 16
+#define	PCRF_AC_RT_WIDTH 16
+#define	PCRF_AC_ALT_LBN 0
+#define	PCRF_AC_ALT_WIDTH 16
+
+
+/*
+ * PC_OTHER_MSG_REG(32bit):
+ * Other message register
+ */
+
+#define	PCR_AC_OTHER_MSG_REG 0x00000704
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_OM_CRPT3_LBN 24
+#define	PCRF_AC_OM_CRPT3_WIDTH 8
+#define	PCRF_AC_OM_CRPT2_LBN 16
+#define	PCRF_AC_OM_CRPT2_WIDTH 8
+#define	PCRF_AC_OM_CRPT1_LBN 8
+#define	PCRF_AC_OM_CRPT1_WIDTH 8
+#define	PCRF_AC_OM_CRPT0_LBN 0
+#define	PCRF_AC_OM_CRPT0_WIDTH 8
+
+
+/*
+ * PC_FORCE_LNK_REG(24bit):
+ * Port force link register
+ */
+
+#define	PCR_AC_FORCE_LNK_REG 0x00000708
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_LFS_LBN 16
+#define	PCRF_AC_LFS_WIDTH 6
+#define	PCRF_AC_FL_LBN 15
+#define	PCRF_AC_FL_WIDTH 1
+#define	PCRF_AC_LN_LBN 0
+#define	PCRF_AC_LN_WIDTH 8
+
+
+/*
+ * PC_ACK_FREQ_REG(32bit):
+ * ACK frequency register
+ */
+
+#define	PCR_AC_ACK_FREQ_REG 0x0000070c
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_CC_ALLOW_L1_WITHOUT_L0S_LBN 30
+#define	PCRF_CC_ALLOW_L1_WITHOUT_L0S_WIDTH 1
+#define	PCRF_AC_L1_ENTR_LAT_LBN 27
+#define	PCRF_AC_L1_ENTR_LAT_WIDTH 3
+#define	PCRF_AC_L0_ENTR_LAT_LBN 24
+#define	PCRF_AC_L0_ENTR_LAT_WIDTH 3
+#define	PCRF_CC_COMM_NFTS_LBN 16
+#define	PCRF_CC_COMM_NFTS_WIDTH 8
+#define	PCRF_AB_ACK_FREQ_REG_RSVD0_LBN 16
+#define	PCRF_AB_ACK_FREQ_REG_RSVD0_WIDTH 3
+#define	PCRF_AC_MAX_FTS_LBN 8
+#define	PCRF_AC_MAX_FTS_WIDTH 8
+#define	PCRF_AC_ACK_FREQ_LBN 0
+#define	PCRF_AC_ACK_FREQ_WIDTH 8
+
+
+/*
+ * PC_PORT_LNK_CTL_REG(32bit):
+ * Port link control register
+ */
+
+#define	PCR_AC_PORT_LNK_CTL_REG 0x00000710
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AB_LRE_LBN 27
+#define	PCRF_AB_LRE_WIDTH 1
+#define	PCRF_AB_ESYNC_LBN 26
+#define	PCRF_AB_ESYNC_WIDTH 1
+#define	PCRF_AB_CRPT_LBN 25
+#define	PCRF_AB_CRPT_WIDTH 1
+#define	PCRF_AB_XB_LBN 24
+#define	PCRF_AB_XB_WIDTH 1
+#define	PCRF_AC_LC_LBN 16
+#define	PCRF_AC_LC_WIDTH 6
+#define	PCRF_AC_LDR_LBN 8
+#define	PCRF_AC_LDR_WIDTH 4
+#define	PCRF_AC_FLM_LBN 7
+#define	PCRF_AC_FLM_WIDTH 1
+#define	PCRF_AC_LKD_LBN 6
+#define	PCRF_AC_LKD_WIDTH 1
+#define	PCRF_AC_DLE_LBN 5
+#define	PCRF_AC_DLE_WIDTH 1
+#define	PCRF_AB_PORT_LNK_CTL_REG_RSVD0_LBN 4
+#define	PCRF_AB_PORT_LNK_CTL_REG_RSVD0_WIDTH 1
+#define	PCRF_AC_RA_LBN 3
+#define	PCRF_AC_RA_WIDTH 1
+#define	PCRF_AC_LE_LBN 2
+#define	PCRF_AC_LE_WIDTH 1
+#define	PCRF_AC_SD_LBN 1
+#define	PCRF_AC_SD_WIDTH 1
+#define	PCRF_AC_OMR_LBN 0
+#define	PCRF_AC_OMR_WIDTH 1
+
+
+/*
+ * PC_LN_SKEW_REG(32bit):
+ * Lane skew register
+ */
+
+#define	PCR_AC_LN_SKEW_REG 0x00000714
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_DIS_LBN 31
+#define	PCRF_AC_DIS_WIDTH 1
+#define	PCRF_AB_RST_LBN 30
+#define	PCRF_AB_RST_WIDTH 1
+#define	PCRF_AC_AD_LBN 25
+#define	PCRF_AC_AD_WIDTH 1
+#define	PCRF_AC_FCD_LBN 24
+#define	PCRF_AC_FCD_WIDTH 1
+#define	PCRF_AC_LS2_LBN 16
+#define	PCRF_AC_LS2_WIDTH 8
+#define	PCRF_AC_LS1_LBN 8
+#define	PCRF_AC_LS1_WIDTH 8
+#define	PCRF_AC_LS0_LBN 0
+#define	PCRF_AC_LS0_WIDTH 8
+
+
+/*
+ * PC_SYM_NUM_REG(16bit):
+ * Symbol number register
+ */
+
+#define	PCR_AC_SYM_NUM_REG 0x00000718
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_CC_MAX_FUNCTIONS_LBN 29
+#define	PCRF_CC_MAX_FUNCTIONS_WIDTH 3
+#define	PCRF_CC_FC_WATCHDOG_TMR_LBN 24
+#define	PCRF_CC_FC_WATCHDOG_TMR_WIDTH 5
+#define	PCRF_CC_ACK_NAK_TMR_MOD_LBN 19
+#define	PCRF_CC_ACK_NAK_TMR_MOD_WIDTH 5
+#define	PCRF_CC_REPLAY_TMR_MOD_LBN 14
+#define	PCRF_CC_REPLAY_TMR_MOD_WIDTH 5
+#define	PCRF_AB_ES_LBN 12
+#define	PCRF_AB_ES_WIDTH 3
+#define	PCRF_AB_SYM_NUM_REG_RSVD0_LBN 11
+#define	PCRF_AB_SYM_NUM_REG_RSVD0_WIDTH 1
+#define	PCRF_CC_NUM_SKP_SYMS_LBN 8
+#define	PCRF_CC_NUM_SKP_SYMS_WIDTH 3
+#define	PCRF_AB_TS2_LBN 4
+#define	PCRF_AB_TS2_WIDTH 4
+#define	PCRF_AC_TS1_LBN 0
+#define	PCRF_AC_TS1_WIDTH 4
+
+
+/*
+ * PC_SYM_TMR_FLT_MSK_REG(16bit):
+ * Symbol timer and Filter Mask Register
+ */
+
+#define	PCR_CC_SYM_TMR_FLT_MSK_REG 0x0000071c
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CC_DEFAULT_FLT_MSK1_LBN 16
+#define	PCRF_CC_DEFAULT_FLT_MSK1_WIDTH 16
+#define	PCRF_CC_FC_WDOG_TMR_DIS_LBN 15
+#define	PCRF_CC_FC_WDOG_TMR_DIS_WIDTH 1
+#define	PCRF_CC_SI1_LBN 8
+#define	PCRF_CC_SI1_WIDTH 3
+#define	PCRF_CC_SKIP_INT_VAL_LBN 0
+#define	PCRF_CC_SKIP_INT_VAL_WIDTH 11
+#define	PCRF_CC_SI0_LBN 0
+#define	PCRF_CC_SI0_WIDTH 8
+
+
+/*
+ * PC_SYM_TMR_REG(16bit):
+ * Symbol timer register
+ */
+
+#define	PCR_AB_SYM_TMR_REG 0x0000071c
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCRF_AB_ET_LBN 11
+#define	PCRF_AB_ET_WIDTH 4
+#define	PCRF_AB_SI1_LBN 8
+#define	PCRF_AB_SI1_WIDTH 3
+#define	PCRF_AB_SI0_LBN 0
+#define	PCRF_AB_SI0_WIDTH 8
+
+
+/*
+ * PC_PHY_STAT_REG(32bit):
+ * PHY status register
+ */
+
+#define	PCR_AB_PHY_STAT_REG 0x00000720
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_PHY_STAT_REG 0x00000810
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_AC_SSL_LBN 3
+#define	PCRF_AC_SSL_WIDTH 1
+#define	PCRF_AC_SSR_LBN 2
+#define	PCRF_AC_SSR_WIDTH 1
+#define	PCRF_AC_SSCL_LBN 1
+#define	PCRF_AC_SSCL_WIDTH 1
+#define	PCRF_AC_SSCD_LBN 0
+#define	PCRF_AC_SSCD_WIDTH 1
+
+
+/*
+ * PC_FLT_MSK_REG(32bit):
+ * Filter Mask Register 2
+ */
+
+#define	PCR_CC_FLT_MSK_REG 0x00000720
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CC_DEFAULT_FLT_MSK2_LBN 0
+#define	PCRF_CC_DEFAULT_FLT_MSK2_WIDTH 32
+
+
+/*
+ * PC_PHY_CTL_REG(32bit):
+ * PHY control register
+ */
+
+#define	PCR_AB_PHY_CTL_REG 0x00000724
+/* falcona0,falconb0=pci_f0_config */
+
+#define	PCR_CC_PHY_CTL_REG 0x00000814
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_AC_BD_LBN 31
+#define	PCRF_AC_BD_WIDTH 1
+#define	PCRF_AC_CDS_LBN 30
+#define	PCRF_AC_CDS_WIDTH 1
+#define	PCRF_AC_DWRAP_LB_LBN 29
+#define	PCRF_AC_DWRAP_LB_WIDTH 1
+#define	PCRF_AC_EBD_LBN 28
+#define	PCRF_AC_EBD_WIDTH 1
+#define	PCRF_AC_SNR_LBN 27
+#define	PCRF_AC_SNR_WIDTH 1
+#define	PCRF_AC_RX_NOT_DET_LBN 2
+#define	PCRF_AC_RX_NOT_DET_WIDTH 1
+#define	PCRF_AC_FORCE_LOS_VAL_LBN 1
+#define	PCRF_AC_FORCE_LOS_VAL_WIDTH 1
+#define	PCRF_AC_FORCE_LOS_EN_LBN 0
+#define	PCRF_AC_FORCE_LOS_EN_WIDTH 1
+
+
+/*
+ * PC_DEBUG0_REG(32bit):
+ * Debug register 0
+ */
+
+#define	PCR_AC_DEBUG0_REG 0x00000728
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_CDI03_LBN 24
+#define	PCRF_AC_CDI03_WIDTH 8
+#define	PCRF_AC_CDI0_LBN 0
+#define	PCRF_AC_CDI0_WIDTH 32
+#define	PCRF_AC_CDI02_LBN 16
+#define	PCRF_AC_CDI02_WIDTH 8
+#define	PCRF_AC_CDI01_LBN 8
+#define	PCRF_AC_CDI01_WIDTH 8
+#define	PCRF_AC_CDI00_LBN 0
+#define	PCRF_AC_CDI00_WIDTH 8
+
+
+/*
+ * PC_DEBUG1_REG(32bit):
+ * Debug register 1
+ */
+
+#define	PCR_AC_DEBUG1_REG 0x0000072c
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_CDI13_LBN 24
+#define	PCRF_AC_CDI13_WIDTH 8
+#define	PCRF_AC_CDI1_LBN 0
+#define	PCRF_AC_CDI1_WIDTH 32
+#define	PCRF_AC_CDI12_LBN 16
+#define	PCRF_AC_CDI12_WIDTH 8
+#define	PCRF_AC_CDI11_LBN 8
+#define	PCRF_AC_CDI11_WIDTH 8
+#define	PCRF_AC_CDI10_LBN 0
+#define	PCRF_AC_CDI10_WIDTH 8
+
+
+/*
+ * PC_XPFCC_STAT_REG(24bit):
+ * documentation to be written for sum_PC_XPFCC_STAT_REG
+ */
+
+#define	PCR_AC_XPFCC_STAT_REG 0x00000730
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_XPDC_LBN 12
+#define	PCRF_AC_XPDC_WIDTH 8
+#define	PCRF_AC_XPHC_LBN 0
+#define	PCRF_AC_XPHC_WIDTH 12
+
+
+/*
+ * PC_XNPFCC_STAT_REG(24bit):
+ * documentation to be written for sum_PC_XNPFCC_STAT_REG
+ */
+
+#define	PCR_AC_XNPFCC_STAT_REG 0x00000734
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_XNPDC_LBN 12
+#define	PCRF_AC_XNPDC_WIDTH 8
+#define	PCRF_AC_XNPHC_LBN 0
+#define	PCRF_AC_XNPHC_WIDTH 12
+
+
+/*
+ * PC_XCFCC_STAT_REG(24bit):
+ * documentation to be written for sum_PC_XCFCC_STAT_REG
+ */
+
+#define	PCR_AC_XCFCC_STAT_REG 0x00000738
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_XCDC_LBN 12
+#define	PCRF_AC_XCDC_WIDTH 8
+#define	PCRF_AC_XCHC_LBN 0
+#define	PCRF_AC_XCHC_WIDTH 12
+
+
+/*
+ * PC_Q_STAT_REG(8bit):
+ * documentation to be written for sum_PC_Q_STAT_REG
+ */
+
+#define	PCR_AC_Q_STAT_REG 0x0000073c
+/* falcona0,falconb0,sienaa0=pci_f0_config */
+
+#define	PCRF_AC_RQNE_LBN 2
+#define	PCRF_AC_RQNE_WIDTH 1
+#define	PCRF_AC_XRNE_LBN 1
+#define	PCRF_AC_XRNE_WIDTH 1
+#define	PCRF_AC_RCNR_LBN 0
+#define	PCRF_AC_RCNR_WIDTH 1
+
+
+/*
+ * PC_VC_XMIT_ARB1_REG(32bit):
+ * VC Transmit Arbitration Register 1
+ */
+
+#define	PCR_CC_VC_XMIT_ARB1_REG 0x00000740
+/* sienaa0=pci_f0_config */
+
+
+
+/*
+ * PC_VC_XMIT_ARB2_REG(32bit):
+ * VC Transmit Arbitration Register 2
+ */
+
+#define	PCR_CC_VC_XMIT_ARB2_REG 0x00000744
+/* sienaa0=pci_f0_config */
+
+
+
+/*
+ * PC_VC0_P_RQ_CTL_REG(32bit):
+ * VC0 Posted Receive Queue Control
+ */
+
+#define	PCR_CC_VC0_P_RQ_CTL_REG 0x00000748
+/* sienaa0=pci_f0_config */
+
+
+
+/*
+ * PC_VC0_NP_RQ_CTL_REG(32bit):
+ * VC0 Non-Posted Receive Queue Control
+ */
+
+#define	PCR_CC_VC0_NP_RQ_CTL_REG 0x0000074c
+/* sienaa0=pci_f0_config */
+
+
+
+/*
+ * PC_VC0_C_RQ_CTL_REG(32bit):
+ * VC0 Completion Receive Queue Control
+ */
+
+#define	PCR_CC_VC0_C_RQ_CTL_REG 0x00000750
+/* sienaa0=pci_f0_config */
+
+
+
+/*
+ * PC_GEN2_REG(32bit):
+ * Gen2 Register
+ */
+
+#define	PCR_CC_GEN2_REG 0x0000080c
+/* sienaa0=pci_f0_config */
+
+#define	PCRF_CC_SET_DE_EMPHASIS_LBN 20
+#define	PCRF_CC_SET_DE_EMPHASIS_WIDTH 1
+#define	PCRF_CC_CFG_TX_COMPLIANCE_LBN 19
+#define	PCRF_CC_CFG_TX_COMPLIANCE_WIDTH 1
+#define	PCRF_CC_CFG_TX_SWING_LBN 18
+#define	PCRF_CC_CFG_TX_SWING_WIDTH 1
+#define	PCRF_CC_DIR_SPEED_CHANGE_LBN 17
+#define	PCRF_CC_DIR_SPEED_CHANGE_WIDTH 1
+#define	PCRF_CC_LANE_ENABLE_LBN 8
+#define	PCRF_CC_LANE_ENABLE_WIDTH 9
+#define	PCRF_CC_NUM_FTS_LBN 0
+#define	PCRF_CC_NUM_FTS_WIDTH 8
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _SYS_EFX_REGS_PCI_H */
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_rx.c	2013-08-22 18:57:29.125367437 -0400
@@ -0,0 +1,817 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+	__checkReturn	int
+efx_rx_init(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	unsigned int index;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+
+	if (!(enp->en_mod_flags & EFX_MOD_EV)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (enp->en_mod_flags & EFX_MOD_RX) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_DESC_PUSH_EN, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, 0x3000 / 32);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
+
+	/* Zero the RSS table */
+	for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS;
+	    index++) {
+		EFX_ZERO_OWORD(oword);
+		EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
+				    index, &oword);
+	}
+
+	enp->en_mod_flags |= EFX_MOD_RX;
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_RX_HDR_SPLIT
+	__checkReturn	int
+efx_rx_hdr_split_enable(
+	__in		efx_nic_t *enp,
+	__in		unsigned int hdr_buf_size,
+	__in		unsigned int pld_buf_size)
+{
+	unsigned int nhdr32;
+	unsigned int npld32;
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
+	EFSYS_ASSERT3U(enp->en_family, >=, EFX_FAMILY_SIENA);
+
+	nhdr32 = hdr_buf_size / 32;
+	if ((nhdr32 == 0) ||
+	    (nhdr32 >= (1 << FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_WIDTH)) ||
+	    ((hdr_buf_size % 32) != 0)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	npld32 = pld_buf_size / 32;
+	if ((npld32 == 0) ||
+	    (npld32 >= (1 << FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_WIDTH)) ||
+	    ((pld_buf_size % 32) != 0)) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (enp->en_rx_qcount > 0) {
+		rc = EBUSY;
+		goto fail3;
+	}
+
+	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_HDR_SPLIT_EN, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE, nhdr32);
+	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE, npld32);
+
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_RX_HDR_SPLIT */
+
+
+#if EFSYS_OPT_RX_SCATTER
+	__checkReturn	int
+efx_rx_scatter_enable(
+	__in		efx_nic_t *enp,
+	__in		unsigned int buf_size)
+{
+	unsigned int nbuf32;
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
+	EFSYS_ASSERT3U(enp->en_family, >=, EFX_FAMILY_FALCON);
+
+	nbuf32 = buf_size / 32;
+	if ((nbuf32 == 0) ||
+	    (nbuf32 >= (1 << FRF_BZ_RX_USR_BUF_SIZE_WIDTH)) ||
+	    ((buf_size % 32) != 0)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (enp->en_rx_qcount > 0) {
+		rc = EBUSY;
+		goto fail2;
+	}
+
+	/* Set scatter buffer size */
+	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, nbuf32);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
+
+	/* Enable scatter for packets not matching a filter */
+	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_SCATTER_ENBL_NO_MATCH_Q, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_RX_SCATTER */
+
+
+#define	EFX_RX_LFSR_HASH(_enp, _insert)					\
+	do {                                    			\
+		efx_oword_t oword;					\
+									\
+		EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword);	\
+		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);	\
+		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);	\
+		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);	\
+		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,	\
+		    (_insert) ? 1 : 0);					\
+		EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);	\
+									\
+		if ((_enp)->en_family == EFX_FAMILY_SIENA) {		\
+			EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3,	\
+			    &oword);					\
+			EFX_SET_OWORD_FIELD(oword,			\
+			    FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 0);	\
+			EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3,	\
+			    &oword);					\
+		}							\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+	} while (B_FALSE)
+
+#define	EFX_RX_TOEPLITZ_IPV4_HASH(_enp, _insert, _ip, _tcp)		\
+	do {                                    			\
+		efx_oword_t oword;					\
+									\
+		EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG,	&oword);	\
+		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 1);	\
+		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH,		\
+		    (_ip) ? 1 : 0);					\
+		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP,		\
+		    (_tcp) ? 0 : 1);					\
+		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,	\
+		    (_insert) ? 1 : 0);					\
+		EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);	\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+	} while (B_FALSE)
+
+#define	EFX_RX_TOEPLITZ_IPV6_HASH(_enp, _ip, _tcp, _rc)			\
+	do {                                    			\
+		efx_oword_t oword;					\
+									\
+		if ((_enp)->en_family == EFX_FAMILY_FALCON) {		\
+			(_rc) = ((_ip) || (_tcp)) ? ENOTSUP : 0;	\
+			break;						\
+		}							\
+									\
+		EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword);	\
+		EFX_SET_OWORD_FIELD(oword,				\
+		    FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1);		\
+		EFX_SET_OWORD_FIELD(oword,				\
+		    FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, (_ip) ? 1 : 0);	\
+		EFX_SET_OWORD_FIELD(oword,				\
+		    FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS, (_tcp) ? 0 : 1);	\
+		EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword);	\
+									\
+		(_rc) = 0;						\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+	} while (B_FALSE)
+
+
+#if EFSYS_OPT_RX_SCALE
+	__checkReturn	int
+efx_rx_scale_mode_set(
+	__in		efx_nic_t *enp,
+	__in		efx_rx_hash_alg_t alg,
+	__in		efx_rx_hash_type_t type,
+	__in		boolean_t insert)
+{
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
+	EFSYS_ASSERT3U(enp->en_family, >=, EFX_FAMILY_FALCON);
+
+	switch (alg) {
+	case EFX_RX_HASHALG_LFSR:
+		EFX_RX_LFSR_HASH(enp, insert);
+		break;
+
+	case EFX_RX_HASHALG_TOEPLITZ:
+		EFX_RX_TOEPLITZ_IPV4_HASH(enp, insert,
+		    type & (1 << EFX_RX_HASH_IPV4),
+		    type & (1 << EFX_RX_HASH_TCPIPV4));
+
+		EFX_RX_TOEPLITZ_IPV6_HASH(enp,
+		    type & (1 << EFX_RX_HASH_IPV6),
+		    type & (1 << EFX_RX_HASH_TCPIPV6),
+		    rc);
+		if (rc != 0)
+			goto fail1;
+
+		break;
+
+	default:
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	EFX_RX_LFSR_HASH(enp, B_FALSE);
+
+	return (rc);
+}
+#endif
+
+#if EFSYS_OPT_RX_SCALE
+	__checkReturn	int
+efx_rx_scale_toeplitz_ipv4_key_set(
+	__in		efx_nic_t *enp,
+	__in_ecount(n)	uint8_t *key,
+	__in		size_t n)
+{
+	efx_oword_t oword;
+	unsigned int byte;
+	unsigned int offset;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
+
+	byte = 0;
+
+	/* Write toeplitz hash key */
+	EFX_ZERO_OWORD(oword);
+	for (offset = (FRF_BZ_RX_RSS_TKEY_LBN + FRF_BZ_RX_RSS_TKEY_WIDTH) / 8;
+	    offset > 0 && byte < n;
+	    --offset)
+		oword.eo_u8[offset - 1] = key[byte++];
+
+	EFX_BAR_WRITEO(enp, FR_BZ_RX_RSS_TKEY_REG, &oword);
+
+	byte = 0;
+
+	/* Verify toeplitz hash key */
+	EFX_BAR_READO(enp, FR_BZ_RX_RSS_TKEY_REG, &oword);
+	for (offset = (FRF_BZ_RX_RSS_TKEY_LBN + FRF_BZ_RX_RSS_TKEY_WIDTH) / 8;
+	    offset > 0 && byte < n;
+	    --offset) {
+		if (oword.eo_u8[offset - 1] != key[byte++]) {
+			rc = EFAULT;
+			goto fail1;
+		}
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif
+
+#if EFSYS_OPT_RX_SCALE
+	__checkReturn	int
+efx_rx_scale_toeplitz_ipv6_key_set(
+	__in		efx_nic_t *enp,
+	__in_ecount(n)	uint8_t *key,
+	__in		size_t n)
+{
+	efx_oword_t oword;
+	unsigned int byte;
+	int offset;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
+
+	byte = 0;
+
+	/* Write toeplitz hash key 3 */
+	EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
+	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN +
+	    FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH) / 8;
+	    offset > 0 && byte < n;
+	    --offset)
+		oword.eo_u8[offset - 1] = key[byte++];
+
+	EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
+
+	/* Write toeplitz hash key 2 */
+	EFX_ZERO_OWORD(oword);
+	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN +
+	    FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH) / 8;
+	    offset > 0 && byte < n;
+	    --offset)
+		oword.eo_u8[offset - 1] = key[byte++];
+
+	EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG2, &oword);
+
+	/* Write toeplitz hash key 1 */
+	EFX_ZERO_OWORD(oword);
+	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN +
+	    FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH) / 8;
+	    offset > 0 && byte < n;
+	    --offset)
+		oword.eo_u8[offset - 1] = key[byte++];
+
+	EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG1, &oword);
+
+	byte = 0;
+
+	/* Verify toeplitz hash key 3 */
+	EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
+	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN +
+	    FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH) / 8;
+	    offset > 0 && byte < n;
+	    --offset) {
+		if (oword.eo_u8[offset - 1] != key[byte++]) {
+			rc = EFAULT;
+			goto fail1;
+		}
+	}
+
+	/* Verify toeplitz hash key 2 */
+	EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG2, &oword);
+	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN +
+	    FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH) / 8;
+	    offset > 0 && byte < n;
+	    --offset) {
+		if (oword.eo_u8[offset - 1] != key[byte++]) {
+			rc = EFAULT;
+			goto fail2;
+		}
+	}
+
+	/* Verify toeplitz hash key 1 */
+	EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG1, &oword);
+	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN +
+	    FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH) / 8;
+	    offset > 0 && byte < n;
+	    --offset) {
+		if (oword.eo_u8[offset - 1] != key[byte++]) {
+			rc = EFAULT;
+			goto fail3;
+		}
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif
+
+#if EFSYS_OPT_RX_SCALE
+	__checkReturn	int
+efx_rx_scale_tbl_set(
+	__in		efx_nic_t *enp,
+	__in_ecount(n)	unsigned int *table,
+	__in		size_t n)
+{
+	efx_oword_t oword;
+	int index;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
+
+	EFX_STATIC_ASSERT(EFX_RSS_TBL_SIZE == FR_BZ_RX_INDIRECTION_TBL_ROWS);
+	EFX_STATIC_ASSERT(EFX_MAXRSS == (1 << FRF_BZ_IT_QUEUE_WIDTH));
+
+	if (n > FR_BZ_RX_INDIRECTION_TBL_ROWS) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS; index++) {
+		uint32_t byte;
+
+		/* Calculate the entry to place in the table */
+		byte = (uint32_t)table[index % n];
+
+		EFSYS_PROBE2(table, int, index, uint32_t, byte);
+
+		EFX_POPULATE_OWORD_1(oword, FRF_BZ_IT_QUEUE, byte);
+
+		/* Write the table */
+		EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
+				    index, &oword);
+	}
+
+	for (index = FR_BZ_RX_INDIRECTION_TBL_ROWS - 1; index >= 0; --index) {
+		uint32_t byte;
+
+		/* Determine if we're starting a new batch */
+		byte = (uint32_t)table[index % n];
+
+		/* Read the table */
+		EFX_BAR_TBL_READO(enp, FR_BZ_RX_INDIRECTION_TBL,
+				    index, &oword);
+
+		/* Verify the entry */
+		if (EFX_OWORD_FIELD(oword, FRF_BZ_IT_QUEUE) != byte) {
+			rc = EFAULT;
+			goto fail2;
+		}
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif
+
+#if EFSYS_OPT_FILTER
+extern	__checkReturn	int
+efx_rx_filter_insert(
+	__in		efx_rxq_t *erp,
+	__inout		efx_filter_spec_t *spec)
+{
+	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
+	EFSYS_ASSERT3P(spec, !=, NULL);
+
+	spec->efs_dmaq_id = (uint16_t)erp->er_index;
+	return (efx_filter_insert_filter(erp->er_enp, spec, B_FALSE));
+}
+#endif
+
+#if EFSYS_OPT_FILTER
+extern	__checkReturn	int
+efx_rx_filter_remove(
+	__in		efx_rxq_t *erp,
+	__inout		efx_filter_spec_t *spec)
+{
+	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
+	EFSYS_ASSERT3P(spec, !=, NULL);
+
+	spec->efs_dmaq_id = (uint16_t)erp->er_index;
+	return (efx_filter_remove_filter(erp->er_enp, spec));
+}
+#endif
+
+extern			void
+efx_rx_qpost(
+	__in		efx_rxq_t *erp,
+	__in_ecount(n)	efsys_dma_addr_t *addrp,
+	__in		size_t size,
+	__in		unsigned int n,
+	__in		unsigned int completed,
+	__in		unsigned int added)
+{
+	efx_qword_t qword;
+	unsigned int i;
+	unsigned int offset;
+	unsigned int id;
+
+	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
+
+	/* The client driver must not overfill the queue */
+	EFSYS_ASSERT3U(added - completed + n, <=,
+	    EFX_RXQ_LIMIT(erp->er_mask + 1));
+
+	id = added & (erp->er_mask);
+	for (i = 0; i < n; i++) {
+		EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
+		    unsigned int, id, efsys_dma_addr_t, addrp[i],
+		    size_t, size);
+
+		EFX_POPULATE_QWORD_3(qword,
+		    FSF_AZ_RX_KER_BUF_SIZE, (uint32_t)(size),
+		    FSF_AZ_RX_KER_BUF_ADDR_DW0,
+		    (uint32_t)(addrp[i] & 0xffffffff),
+		    FSF_AZ_RX_KER_BUF_ADDR_DW1,
+		    (uint32_t)(addrp[i] >> 32));
+
+		offset = id * sizeof (efx_qword_t);
+		EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
+
+		id = (id + 1) & (erp->er_mask);
+	}
+}
+
+		void
+efx_rx_qpush(
+	__in	efx_rxq_t *erp,
+	__in	unsigned int added)
+{
+	efx_nic_t *enp = erp->er_enp;
+	uint32_t wptr;
+	efx_oword_t oword;
+	efx_dword_t dword;
+
+	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
+
+	/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
+	EFSYS_PIO_WRITE_BARRIER();
+
+	/* Push the populated descriptors out */
+	wptr = added & erp->er_mask;
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DESC_WPTR, wptr);
+
+	/* Only write the third DWORD */
+	EFX_POPULATE_DWORD_1(dword,
+	    EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
+	EFX_BAR_TBL_WRITED3(enp, FR_BZ_RX_DESC_UPD_REGP0,
+			    erp->er_index, &dword, B_FALSE);
+}
+
+		void
+efx_rx_qflush(
+	__in	efx_rxq_t *erp)
+{
+	efx_nic_t *enp = erp->er_enp;
+	efx_oword_t oword;
+	uint32_t label;
+
+	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
+
+	label = erp->er_index;
+
+	/* Flush the queue */
+	EFX_POPULATE_OWORD_2(oword, FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
+	    FRF_AZ_RX_FLUSH_DESCQ, label);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_FLUSH_DESCQ_REG, &oword);
+}
+
+		void
+efx_rx_qenable(
+	__in	efx_rxq_t *erp)
+{
+	efx_nic_t *enp = erp->er_enp;
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
+
+	EFX_BAR_TBL_READO(enp, FR_AZ_RX_DESC_PTR_TBL,
+			    erp->er_index, &oword);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DC_HW_RPTR, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_HW_RPTR, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_EN, 1);
+
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
+			    erp->er_index, &oword);
+}
+
+	__checkReturn	int
+efx_rx_qcreate(
+	__in		efx_nic_t *enp,
+	__in		unsigned int index,
+	__in		unsigned int label,
+	__in		efx_rxq_type_t type,
+	__in		efsys_mem_t *esmp,
+	__in		size_t n,
+	__in		uint32_t id,
+	__in		efx_evq_t *eep,
+	__deref_out	efx_rxq_t **erpp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_rxq_t *erp;
+	efx_oword_t oword;
+	uint32_t size;
+	boolean_t split;
+	boolean_t jumbo;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
+
+	EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS ==
+	    (1 << FRF_AZ_RX_DESCQ_LABEL_WIDTH));
+	EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
+	EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
+
+	if (!ISP2(n) || !(n & EFX_RXQ_NDESCS_MASK)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+	if (index >= encp->enc_rxq_limit) {
+		rc = EINVAL;
+		goto fail2;
+	}
+	for (size = 0; (1 << size) <= (EFX_RXQ_MAXNDESCS / EFX_RXQ_MINNDESCS);
+	    size++)
+		if ((1 << size) == (int)(n / EFX_RXQ_MINNDESCS))
+			break;
+	if (id + (1 << size) >= encp->enc_buftbl_limit) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	switch (type) {
+	case EFX_RXQ_TYPE_DEFAULT:
+		split = B_FALSE;
+		jumbo = B_FALSE;
+		break;
+
+#if EFSYS_OPT_RX_HDR_SPLIT
+	case EFX_RXQ_TYPE_SPLIT_HEADER:
+		if ((enp->en_family < EFX_FAMILY_SIENA) || ((index & 1) != 0)) {
+			rc = EINVAL;
+			goto fail4;
+		}
+		split = B_TRUE;
+		jumbo = B_TRUE;
+		break;
+
+	case EFX_RXQ_TYPE_SPLIT_PAYLOAD:
+		if ((enp->en_family < EFX_FAMILY_SIENA) || ((index & 1) == 0)) {
+			rc = EINVAL;
+			goto fail4;
+		}
+		split = B_FALSE;
+		jumbo = B_TRUE;
+		break;
+#endif	/* EFSYS_OPT_RX_HDR_SPLIT */
+
+#if EFSYS_OPT_RX_SCATTER
+	case EFX_RXQ_TYPE_SCATTER:
+		if (enp->en_family < EFX_FAMILY_SIENA) {
+			rc = EINVAL;
+			goto fail4;
+		}
+		split = B_FALSE;
+		jumbo = B_TRUE;
+		break;
+#endif	/* EFSYS_OPT_RX_SCATTER */
+
+	default:
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	/* Allocate an RXQ object */
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_rxq_t), erp);
+
+	if (erp == NULL) {
+		rc = ENOMEM;
+		goto fail5;
+	}
+
+	erp->er_magic = EFX_RXQ_MAGIC;
+	erp->er_enp = enp;
+	erp->er_index = index;
+	erp->er_mask = n - 1;
+	erp->er_esmp = esmp;
+
+	/* Set up the new descriptor queue */
+	EFX_POPULATE_OWORD_10(oword,
+	    FRF_CZ_RX_HDR_SPLIT, split,
+	    FRF_AZ_RX_ISCSI_DDIG_EN, 0,
+	    FRF_AZ_RX_ISCSI_HDIG_EN, 0,
+	    FRF_AZ_RX_DESCQ_BUF_BASE_ID, id,
+	    FRF_AZ_RX_DESCQ_EVQ_ID, eep->ee_index,
+	    FRF_AZ_RX_DESCQ_OWNER_ID, 0,
+	    FRF_AZ_RX_DESCQ_LABEL, label,
+	    FRF_AZ_RX_DESCQ_SIZE, size,
+	    FRF_AZ_RX_DESCQ_TYPE, 0,
+	    FRF_AZ_RX_DESCQ_JUMBO, jumbo);
+
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
+			    erp->er_index, &oword);
+
+	enp->en_rx_qcount++;
+	*erpp = erp;
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+		void
+efx_rx_qdestroy(
+	__in	efx_rxq_t *erp)
+{
+	efx_nic_t *enp = erp->er_enp;
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
+
+	EFSYS_ASSERT(enp->en_rx_qcount != 0);
+	--enp->en_rx_qcount;
+
+	/* Purge descriptor queue */
+	EFX_ZERO_OWORD(oword);
+
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
+			    erp->er_index, &oword);
+
+	/* Free the RXQ object */
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
+}
+
+		void
+efx_rx_fini(
+	__in	efx_nic_t *enp)
+{
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
+	EFSYS_ASSERT3U(enp->en_rx_qcount, ==, 0);
+
+	enp->en_mod_flags &= ~EFX_MOD_RX;
+}
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_sram.c	2013-08-22 18:57:29.217002512 -0400
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+	__checkReturn	int
+efx_sram_buf_tbl_set(
+	__in		efx_nic_t *enp,
+	__in		uint32_t id,
+	__in		efsys_mem_t *esmp,
+	__in		size_t n)
+{
+	efx_qword_t qword;
+	uint32_t start = id;
+	uint32_t stop = start + n;
+	efsys_dma_addr_t addr;
+	efx_oword_t oword;
+	unsigned int count;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+
+	if (stop >= EFX_BUF_TBL_SIZE) {
+		rc = EFBIG;
+		goto fail1;
+	}
+
+	/* Add the entries into the buffer table */
+	addr = EFSYS_MEM_ADDR(esmp);
+	for (id = start; id != stop; id++) {
+		EFX_POPULATE_QWORD_5(qword,
+		    FRF_AZ_IP_DAT_BUF_SIZE, 0, FRF_AZ_BUF_ADR_REGION, 0,
+		    FRF_AZ_BUF_ADR_FBUF_DW0,
+		    (uint32_t)((addr >> 12) & 0xffffffff),
+		    FRF_AZ_BUF_ADR_FBUF_DW1,
+		    (uint32_t)((addr >> 12) >> 32),
+		    FRF_AZ_BUF_OWNER_ID_FBUF, 0);
+
+		EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_FULL_TBL,
+				    id, &qword);
+
+		addr += EFX_BUF_SIZE;
+	}
+
+	EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
+
+	/* Flush the write buffer */
+	EFX_POPULATE_OWORD_2(oword, FRF_AZ_BUF_UPD_CMD, 1,
+	    FRF_AZ_BUF_CLR_CMD, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
+
+	/* Poll for the last entry being written to the buffer table */
+	EFSYS_ASSERT3U(id, ==, stop);
+	addr -= EFX_BUF_SIZE;
+
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 1 ms */
+		EFSYS_SPIN(1000);
+
+		EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
+				    id - 1, &qword);
+
+		if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) ==
+		    (uint32_t)((addr >> 12) & 0xffffffff) &&
+		    EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) ==
+		    (uint32_t)((addr >> 12) >> 32))
+			goto verify;
+
+	} while (++count < 100);
+
+	rc = ETIMEDOUT;
+	goto fail2;
+
+verify:
+	/* Verify the rest of the entries in the buffer table */
+	while (--id != start) {
+		addr -= EFX_BUF_SIZE;
+
+		/* Read the buffer table entry */
+		EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_FULL_TBL,
+				    id - 1, &qword);
+
+		if (EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW0) !=
+		    (uint32_t)((addr >> 12) & 0xffffffff) ||
+		    EFX_QWORD_FIELD(qword, FRF_AZ_BUF_ADR_FBUF_DW1) !=
+		    (uint32_t)((addr >> 12) >> 32)) {
+			rc = EFAULT;
+			goto fail3;
+		}
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+
+	id = stop;
+
+fail2:
+	EFSYS_PROBE(fail2);
+
+	EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
+	    FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, id - 1,
+	    FRF_AZ_BUF_CLR_START_ID, start);
+	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+		void
+efx_sram_buf_tbl_clear(
+	__in	efx_nic_t *enp,
+	__in	uint32_t id,
+	__in	size_t n)
+{
+	efx_oword_t oword;
+	uint32_t start = id;
+	uint32_t stop = start + n;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+
+	EFSYS_ASSERT3U(stop, <, EFX_BUF_TBL_SIZE);
+
+	EFSYS_PROBE2(buf, uint32_t, start, uint32_t, stop - 1);
+
+	EFX_POPULATE_OWORD_4(oword, FRF_AZ_BUF_UPD_CMD, 0,
+	    FRF_AZ_BUF_CLR_CMD, 1, FRF_AZ_BUF_CLR_END_ID, stop - 1,
+	    FRF_AZ_BUF_CLR_START_ID, start);
+	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_UPD_REG, &oword);
+}
+
+
+#if EFSYS_OPT_DIAG
+
+static			void
+efx_sram_byte_increment_set(
+	__in		size_t row,
+	__in		boolean_t negate,
+	__out		efx_qword_t *eqp)
+{
+	size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
+	unsigned int index;
+
+	_NOTE(ARGUNUSED(negate))
+
+	for (index = 0; index < sizeof (efx_qword_t); index++)
+		eqp->eq_u8[index] = offset + index;
+}
+
+static			void
+efx_sram_all_the_same_set(
+	__in		size_t row,
+	__in		boolean_t negate,
+	__out		efx_qword_t *eqp)
+{
+	_NOTE(ARGUNUSED(row))
+
+	if (negate)
+		EFX_SET_QWORD(*eqp);
+	else
+		EFX_ZERO_QWORD(*eqp);
+}
+
+static			void
+efx_sram_bit_alternate_set(
+	__in		size_t row,
+	__in		boolean_t negate,
+	__out		efx_qword_t *eqp)
+{
+	_NOTE(ARGUNUSED(row))
+
+	EFX_POPULATE_QWORD_2(*eqp,
+	    EFX_DWORD_0, (negate) ? 0x55555555 : 0xaaaaaaaa,
+	    EFX_DWORD_1, (negate) ? 0x55555555 : 0xaaaaaaaa);
+}
+
+static			void
+efx_sram_byte_alternate_set(
+	__in		size_t row,
+	__in		boolean_t negate,
+	__out		efx_qword_t *eqp)
+{
+	_NOTE(ARGUNUSED(row))
+
+	EFX_POPULATE_QWORD_2(*eqp,
+	    EFX_DWORD_0, (negate) ? 0x00ff00ff : 0xff00ff00,
+	    EFX_DWORD_1, (negate) ? 0x00ff00ff : 0xff00ff00);
+}
+
+static			void
+efx_sram_byte_changing_set(
+	__in		size_t row,
+	__in		boolean_t negate,
+	__out		efx_qword_t *eqp)
+{
+	size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
+	unsigned int index;
+
+	for (index = 0; index < sizeof (efx_qword_t); index++) {
+		uint8_t byte;
+
+		if (offset / 256 == 0)
+			byte = (uint8_t)((offset % 257) % 256);
+		else
+			byte = (uint8_t)(~((offset - 8) % 257) % 256);
+
+		eqp->eq_u8[index] = (negate) ? ~byte : byte;
+	}
+}
+
+static			void
+efx_sram_bit_sweep_set(
+	__in		size_t row,
+	__in		boolean_t negate,
+	__out		efx_qword_t *eqp)
+{
+	size_t offset = row * FR_AZ_SRM_DBG_REG_STEP;
+
+	if (negate) {
+		EFX_SET_QWORD(*eqp);
+		EFX_CLEAR_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
+	} else {
+		EFX_ZERO_QWORD(*eqp);
+		EFX_SET_QWORD_BIT(*eqp, (offset / sizeof (efx_qword_t)) % 64);
+	}
+}
+
+efx_sram_pattern_fn_t	__cs __efx_sram_pattern_fns[] = {
+	efx_sram_byte_increment_set,
+	efx_sram_all_the_same_set,
+	efx_sram_bit_alternate_set,
+	efx_sram_byte_alternate_set,
+	efx_sram_byte_changing_set,
+	efx_sram_bit_sweep_set
+};
+
+	__checkReturn	int
+efx_sram_test(
+	__in		efx_nic_t *enp,
+	__in		efx_pattern_type_t type)
+{
+	efx_nic_ops_t *enop = enp->en_enop;
+	efx_sram_pattern_fn_t func;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
+
+	/* Select pattern generator */
+	EFSYS_ASSERT3U(type, <, EFX_PATTERN_NTYPES);
+	func = __efx_sram_pattern_fns[type];
+
+	return (enop->eno_sram_test(enp, func));
+}
+
+#endif	/* EFSYS_OPT_DIAG */
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_tx.c	2013-08-22 18:57:29.303551622 -0400
@@ -0,0 +1,481 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_QSTATS
+#define	EFX_TX_QSTAT_INCR(_etp, _stat)					\
+	do {								\
+		(_etp)->et_stat[_stat]++;				\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+#else
+#define	EFX_TX_QSTAT_INCR(_etp, _stat)
+#endif
+
+
+
+	__checkReturn	int
+efx_tx_init(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+
+	if (!(enp->en_mod_flags & EFX_MOD_EV)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (enp->en_mod_flags & EFX_MOD_TX) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
+
+	/*
+	 * Disable the timer-based TX DMA backoff and allow TX DMA to be
+	 * controlled by the RX FIFO fill level (although always allow a
+	 * minimal trickle).
+	 */
+	EFX_BAR_READO(enp, FR_AZ_TX_RESERVED_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER, 0xfe);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER_EN, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PUSH_EN, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DIS_NON_IP_EV, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_THRESHOLD, 2);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
+
+	/*
+	 * Filter all packets less than 14 bytes to avoid parsing
+	 * errors.
+	 */
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_TX_RESERVED_REG, &oword);
+
+	/*
+	 * Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16
+	 * descriptors (which is bad).
+	 */
+	EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
+
+	enp->en_mod_flags |= EFX_MOD_TX;
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_FILTER
+extern	__checkReturn	int
+efx_tx_filter_insert(
+	__in		efx_txq_t *etp,
+	__inout		efx_filter_spec_t *spec)
+{
+	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+	EFSYS_ASSERT3P(spec, !=, NULL);
+
+	spec->efs_dmaq_id = (uint16_t)etp->et_index;
+	return (efx_filter_insert_filter(etp->et_enp, spec, B_FALSE));
+}
+#endif
+
+#if EFSYS_OPT_FILTER
+extern	__checkReturn	int
+efx_tx_filter_remove(
+	__in		efx_txq_t *etp,
+	__inout		efx_filter_spec_t *spec)
+{
+	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+	EFSYS_ASSERT3P(spec, !=, NULL);
+
+	spec->efs_dmaq_id = (uint16_t)etp->et_index;
+	return (efx_filter_remove_filter(etp->et_enp, spec));
+}
+#endif
+
+#define	EFX_TX_DESC(_etp, _addr, _size, _eop, _added)			\
+	do {								\
+		unsigned int id;					\
+		size_t offset;						\
+		efx_qword_t qword;					\
+									\
+		id = (_added)++ & (_etp)->et_mask;			\
+		offset = id * sizeof (efx_qword_t);			\
+									\
+		EFSYS_PROBE5(tx_post, unsigned int, (_etp)->et_index,	\
+		    unsigned int, id, efsys_dma_addr_t, (_addr),	\
+		    size_t, (_size), boolean_t, (_eop));		\
+									\
+		EFX_POPULATE_QWORD_4(qword,				\
+		    FSF_AZ_TX_KER_CONT, (_eop) ? 0 : 1,			\
+		    FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)(_size),	\
+		    FSF_AZ_TX_KER_BUF_ADDR_DW0,				\
+		    (uint32_t)((_addr) & 0xffffffff),			\
+		    FSF_AZ_TX_KER_BUF_ADDR_DW1,				\
+		    (uint32_t)((_addr) >> 32));				\
+		EFSYS_MEM_WRITEQ((_etp)->et_esmp, offset, &qword);	\
+									\
+		_NOTE(CONSTANTCONDITION)				\
+	} while (B_FALSE)
+
+	__checkReturn	int
+efx_tx_qpost(
+	__in		efx_txq_t *etp,
+	__in_ecount(n)	efx_buffer_t *eb,
+	__in		unsigned int n,
+	__in		unsigned int completed,
+	__inout		unsigned int *addedp)
+{
+	unsigned int added = *addedp;
+	unsigned int i;
+	int rc = ENOSPC;
+
+	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+
+	if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1))
+		goto fail1;
+
+	for (i = 0; i < n; i++) {
+		efx_buffer_t *ebp = &eb[i];
+		efsys_dma_addr_t start = ebp->eb_addr;
+		size_t size = ebp->eb_size;
+		efsys_dma_addr_t end = start + size;
+
+		/* Fragments must not span 4k boundaries. */
+		EFSYS_ASSERT(P2ROUNDUP(start + 1, 4096) >= end);
+
+		EFX_TX_DESC(etp, start, size, ebp->eb_eop, added);
+	}
+
+	EFX_TX_QSTAT_INCR(etp, TX_POST);
+
+	*addedp = added;
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+		void
+efx_tx_qpush(
+	__in	efx_txq_t *etp,
+	__in	unsigned int added)
+{
+	efx_nic_t *enp = etp->et_enp;
+	uint32_t wptr;
+	efx_dword_t dword;
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+
+	/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
+	EFSYS_PIO_WRITE_BARRIER();
+
+	/* Push the populated descriptors out */
+	wptr = added & etp->et_mask;
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DESC_WPTR, wptr);
+
+	/* Only write the third DWORD */
+	EFX_POPULATE_DWORD_1(dword,
+	    EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
+	EFX_BAR_TBL_WRITED3(enp, FR_BZ_TX_DESC_UPD_REGP0,
+			    etp->et_index, &dword, B_FALSE);
+}
+
+#define	EFX_MAX_PACE_VALUE 20
+
+	__checkReturn	int
+efx_tx_qpace(
+	__in		efx_txq_t *etp,
+	__in		unsigned int ns)
+{
+	efx_nic_t *enp = etp->et_enp;
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_oword_t oword;
+	unsigned int pace_val;
+	unsigned int timer_period;
+	int rc;
+
+	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+
+	if (ns == 0) {
+		pace_val = 0;
+	} else {
+		/*
+		 * The pace_val to write into the table is s.t
+		 * ns <= timer_period * (2 ^ pace_val)
+		 */
+		timer_period = 104 / encp->enc_clk_mult;
+		for (pace_val = 1; pace_val <= EFX_MAX_PACE_VALUE; pace_val++) {
+			if ((timer_period << pace_val) >= ns)
+				break;
+		}
+	}
+	if (pace_val > EFX_MAX_PACE_VALUE) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	/* Update the pacing table */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_PACE, pace_val);
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_PACE_TBL, etp->et_index, &oword);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+		void
+efx_tx_qflush(
+	__in	efx_txq_t *etp)
+{
+	efx_nic_t *enp = etp->et_enp;
+	efx_oword_t oword;
+	uint32_t label;
+
+	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+
+	efx_tx_qpace(etp, 0);
+
+	label = etp->et_index;
+
+	/* Flush the queue */
+	EFX_POPULATE_OWORD_2(oword, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
+	    FRF_AZ_TX_FLUSH_DESCQ, label);
+	EFX_BAR_WRITEO(enp, FR_AZ_TX_FLUSH_DESCQ_REG, &oword);
+}
+
+		void
+efx_tx_qenable(
+	__in	efx_txq_t *etp)
+{
+	efx_nic_t *enp = etp->et_enp;
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+
+	EFX_BAR_TBL_READO(enp, FR_AZ_TX_DESC_PTR_TBL,
+			    etp->et_index, &oword);
+
+	EFSYS_PROBE5(tx_descq_ptr, unsigned int, etp->et_index,
+	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_3),
+	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_2),
+	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_1),
+	    uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_0));
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DC_HW_RPTR, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_HW_RPTR, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_EN, 1);
+
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
+			    etp->et_index, &oword);
+}
+
+	__checkReturn	int
+efx_tx_qcreate(
+	__in		efx_nic_t *enp,
+	__in		unsigned int index,
+	__in		unsigned int label,
+	__in		efsys_mem_t *esmp,
+	__in		size_t n,
+	__in		uint32_t id,
+	__in		uint16_t flags,
+	__in		efx_evq_t *eep,
+	__deref_out	efx_txq_t **etpp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_txq_t *etp;
+	efx_oword_t oword;
+	uint32_t size;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
+
+	EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS ==
+	    (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH));
+	EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS);
+	EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <, encp->enc_txq_limit);
+
+	if (!ISP2(n) || !(n & EFX_TXQ_NDESCS_MASK)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+	if (index >= encp->enc_txq_limit) {
+		rc = EINVAL;
+		goto fail2;
+	}
+	for (size = 0; (1 << size) <= (EFX_TXQ_MAXNDESCS / EFX_TXQ_MINNDESCS);
+	    size++)
+		if ((1 << size) == (int)(n / EFX_TXQ_MINNDESCS))
+			break;
+	if (id + (1 << size) >= encp->enc_buftbl_limit) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	/* Allocate an TXQ object */
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp);
+
+	if (etp == NULL) {
+		rc = ENOMEM;
+		goto fail4;
+	}
+
+	etp->et_magic = EFX_TXQ_MAGIC;
+	etp->et_enp = enp;
+	etp->et_index = index;
+	etp->et_mask = n - 1;
+	etp->et_esmp = esmp;
+
+	/* Set up the new descriptor queue */
+	EFX_POPULATE_OWORD_6(oword,
+	    FRF_AZ_TX_DESCQ_BUF_BASE_ID, id,
+	    FRF_AZ_TX_DESCQ_EVQ_ID, eep->ee_index,
+	    FRF_AZ_TX_DESCQ_OWNER_ID, 0,
+	    FRF_AZ_TX_DESCQ_LABEL, label,
+	    FRF_AZ_TX_DESCQ_SIZE, size,
+	    FRF_AZ_TX_DESCQ_TYPE, 0);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_NON_IP_DROP_DIS, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_IP_CHKSM_DIS,
+	    (flags & EFX_CKSUM_IPV4) ? 0 : 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_TCP_CHKSM_DIS,
+	    (flags & EFX_CKSUM_TCPUDP) ? 0 : 1);
+
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
+	    etp->et_index, &oword);
+
+	enp->en_tx_qcount++;
+	*etpp = etp;
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_NAMES
+/* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 78ca9ab00287fffb */
+static const char 	__cs * __cs __efx_tx_qstat_name[] = {
+	"post",
+	"unaligned_split",
+};
+/* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */
+
+		const char __cs *
+efx_tx_qstat_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(id, <, TX_NQSTATS);
+
+	return (__efx_tx_qstat_name[id]);
+}
+#endif	/* EFSYS_OPT_NAMES */
+
+#if EFSYS_OPT_QSTATS
+					void
+efx_tx_qstats_update(
+	__in				efx_txq_t *etp,
+	__inout_ecount(TX_NQSTATS)	efsys_stat_t *stat)
+{
+	unsigned int id;
+
+	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+
+	for (id = 0; id < TX_NQSTATS; id++) {
+		efsys_stat_t *essp = &stat[id];
+
+		EFSYS_STAT_INCR(essp, etp->et_stat[id]);
+		etp->et_stat[id] = 0;
+	}
+}
+#endif	/* EFSYS_OPT_QSTATS */
+
+		void
+efx_tx_qdestroy(
+	__in	efx_txq_t *etp)
+{
+	efx_nic_t *enp = etp->et_enp;
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+
+	EFSYS_ASSERT(enp->en_tx_qcount != 0);
+	--enp->en_tx_qcount;
+
+	/* Purge descriptor queue */
+	EFX_ZERO_OWORD(oword);
+
+	EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
+			    etp->et_index, &oword);
+
+	/* Free the TXQ object */
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
+}
+
+		void
+efx_tx_fini(
+	__in	efx_nic_t *enp)
+{
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
+	EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
+
+	enp->en_mod_flags &= ~EFX_MOD_TX;
+}
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_types.h	2013-08-22 18:57:29.392134650 -0400
@@ -0,0 +1,1605 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Ackowledgement to Fen Systems Ltd.
+ */
+
+#ifndef	_SYS_EFX_TYPES_H
+#define	_SYS_EFX_TYPES_H
+
+#include "efsys.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Bitfield access
+ *
+ * Solarflare NICs make extensive use of bitfields up to 128 bits
+ * wide.  Since there is no native 128-bit datatype on most systems,
+ * and since 64-bit datatypes are inefficient on 32-bit systems and
+ * vice versa, we wrap accesses in a way that uses the most efficient
+ * datatype.
+ *
+ * The NICs are PCI devices and therefore little-endian.  Since most
+ * of the quantities that we deal with are DMAed to/from host memory,
+ * we define	our datatypes (efx_oword_t, efx_qword_t and efx_dword_t)
+ * to be little-endian.
+ *
+ * In the less common case of using PIO for individual register
+ * writes, we construct the little-endian datatype in host memory and
+ * then use non-swapping register access primitives, rather than
+ * constructing a native-endian datatype and relying on implicit
+ * byte-swapping.  (We use a similar strategy for register reads.)
+ */
+
+/*
+ * NOTE: Field definitions here and elsewhere are done in terms of a lowest
+ *       bit number (LBN) and a width.
+ */
+
+#define	EFX_DUMMY_FIELD_LBN 0
+#define	EFX_DUMMY_FIELD_WIDTH 0
+
+#define	EFX_BYTE_0_LBN 0
+#define	EFX_BYTE_0_WIDTH 8
+
+#define	EFX_BYTE_1_LBN 8
+#define	EFX_BYTE_1_WIDTH 8
+
+#define	EFX_BYTE_2_LBN 16
+#define	EFX_BYTE_2_WIDTH 8
+
+#define	EFX_BYTE_3_LBN 24
+#define	EFX_BYTE_3_WIDTH 8
+
+#define	EFX_BYTE_4_LBN 32
+#define	EFX_BYTE_4_WIDTH 8
+
+#define	EFX_BYTE_5_LBN 40
+#define	EFX_BYTE_5_WIDTH 8
+
+#define	EFX_BYTE_6_LBN 48
+#define	EFX_BYTE_6_WIDTH 8
+
+#define	EFX_BYTE_7_LBN 56
+#define	EFX_BYTE_7_WIDTH 8
+
+#define	EFX_WORD_0_LBN 0
+#define	EFX_WORD_0_WIDTH 16
+
+#define	EFX_WORD_1_LBN 16
+#define	EFX_WORD_1_WIDTH 16
+
+#define	EFX_WORD_2_LBN 32
+#define	EFX_WORD_2_WIDTH 16
+
+#define	EFX_WORD_3_LBN 48
+#define	EFX_WORD_3_WIDTH 16
+
+#define	EFX_DWORD_0_LBN 0
+#define	EFX_DWORD_0_WIDTH 32
+
+#define	EFX_DWORD_1_LBN 32
+#define	EFX_DWORD_1_WIDTH 32
+
+#define	EFX_DWORD_2_LBN 64
+#define	EFX_DWORD_2_WIDTH 32
+
+#define	EFX_DWORD_3_LBN 96
+#define	EFX_DWORD_3_WIDTH 32
+
+#define	EFX_QWORD_0_LBN 0
+#define	EFX_QWORD_0_WIDTH 64
+
+#define	EFX_QWORD_1_LBN 64
+#define	EFX_QWORD_1_WIDTH 64
+
+/* Specified attribute (i.e. LBN ow WIDTH) of the specified field */
+#define	EFX_VAL(_field, _attribute)					\
+	_field ## _ ## _attribute
+
+/* Lowest bit number of the specified field */
+#define	EFX_LOW_BIT(_field)						\
+	EFX_VAL(_field, LBN)
+
+/* Width of the specified field */
+#define	EFX_WIDTH(_field)						\
+	EFX_VAL(_field, WIDTH)
+
+/* Highest bit number of the specified field */
+#define	EFX_HIGH_BIT(_field)						\
+	(EFX_LOW_BIT(_field) + EFX_WIDTH(_field) - 1)
+
+/*
+ * 64-bit mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x000000000000001f.
+ */
+#define	EFX_MASK64(_field)						\
+	((EFX_WIDTH(_field) == 64) ? ~((uint64_t)0) :			\
+	    (((((uint64_t)1) << EFX_WIDTH(_field))) - 1))
+/*
+ * 32-bit mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x0000001f.
+ */
+#define	EFX_MASK32(_field)						\
+	((EFX_WIDTH(_field) == 32) ? ~((uint32_t)0) :			\
+	    (((((uint32_t)1) << EFX_WIDTH(_field))) - 1))
+
+/*
+ * 16-bit mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x001f.
+ */
+#define	EFX_MASK16(_field)						\
+	((EFX_WIDTH(_field) == 16) ? 0xffffu :				\
+	    (uint16_t)((1 << EFX_WIDTH(_field)) - 1))
+
+/*
+ * 8-bit mask equal in width to the specified field.
+ *
+ * For example, a field with width 5 would have a mask of 0x1f.
+ */
+#define	EFX_MASK8(_field)						\
+	((uint8_t)((1 << EFX_WIDTH(_field)) - 1))
+
+#pragma pack(1)
+
+/*
+ * A byte (i.e. 8-bit) datatype
+ */
+typedef union efx_byte_u {
+	uint8_t eb_u8[1];
+} efx_byte_t;
+
+/*
+ * A word (i.e. 16-bit) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efx_word_u {
+	efx_byte_t ew_byte[2];
+	uint16_t ew_u16[1];
+	uint8_t ew_u8[2];
+} efx_word_t;
+
+/*
+ * A doubleword (i.e. 32-bit) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efx_dword_u {
+	efx_byte_t ed_byte[4];
+	efx_word_t ed_word[2];
+	uint32_t ed_u32[1];
+	uint16_t ed_u16[2];
+	uint8_t ed_u8[4];
+} efx_dword_t;
+
+/*
+ * A quadword (i.e. 64-bit) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efx_qword_u {
+	efx_byte_t eq_byte[8];
+	efx_word_t eq_word[4];
+	efx_dword_t eq_dword[2];
+#if EFSYS_HAS_UINT64
+	uint64_t eq_u64[1];
+#endif
+	uint32_t eq_u32[2];
+	uint16_t eq_u16[4];
+	uint8_t eq_u8[8];
+} efx_qword_t;
+
+/*
+ * An octword (i.e. 128-bit) datatype
+ *
+ * This datatype is defined to be little-endian.
+ */
+typedef union efx_oword_u {
+	efx_byte_t eo_byte[16];
+	efx_word_t eo_word[8];
+	efx_dword_t eo_dword[4];
+	efx_qword_t eo_qword[2];
+#if EFSYS_HAS_UINT64
+	uint64_t eo_u64[2];
+#endif	
+	uint32_t eo_u32[4];
+	uint16_t eo_u16[8];
+	uint8_t eo_u8[16];
+} efx_oword_t;
+
+#pragma pack()
+
+#define	__SWAP16(_x) 				\
+	((((_x) & 0xff) << 8) |			\
+	(((_x) >> 8) & 0xff))
+
+#define	__SWAP32(_x)				\
+	((__SWAP16((_x) & 0xffff) << 16) |	\
+	__SWAP16(((_x) >> 16) & 0xffff))
+
+#define	__SWAP64(_x)				\
+	((__SWAP32((_x) & 0xffffffff) << 32) |	\
+	__SWAP32(((_x) >> 32) & 0xffffffff))
+
+#define	__NOSWAP16(_x)		(_x)
+#define	__NOSWAP32(_x)		(_x)
+#define	__NOSWAP64(_x)		(_x)
+
+#if EFSYS_IS_BIG_ENDIAN
+
+#define	__CPU_TO_LE_16(_x)	(uint16_t)__SWAP16(_x)
+#define	__LE_TO_CPU_16(_x)	(uint16_t)__SWAP16(_x)
+#define	__CPU_TO_BE_16(_x)	(uint16_t)__NOSWAP16(_x)
+#define	__BE_TO_CPU_16(_x)	(uint16_t)__NOSWAP16(_x)
+
+#define	__CPU_TO_LE_32(_x)	(uint32_t)__SWAP32(_x)
+#define	__LE_TO_CPU_32(_x)	(uint32_t)__SWAP32(_x)
+#define	__CPU_TO_BE_32(_x)	(uint32_t)__NOSWAP32(_x)
+#define	__BE_TO_CPU_32(_x)	(uint32_t)__NOSWAP32(_x)
+
+#define	__CPU_TO_LE_64(_x)	(uint64_t)__SWAP64(_x)
+#define	__LE_TO_CPU_64(_x)	(uint64_t)__SWAP64(_x)
+#define	__CPU_TO_BE_64(_x)	(uint64_t)__NOSWAP64(_x)
+#define	__BE_TO_CPU_64(_x)	(uint64_t)__NOSWAP64(_x)
+
+#elif EFSYS_IS_LITTLE_ENDIAN
+
+#define	__CPU_TO_LE_16(_x)	(uint16_t)__NOSWAP16(_x)
+#define	__LE_TO_CPU_16(_x)	(uint16_t)__NOSWAP16(_x)
+#define	__CPU_TO_BE_16(_x)	(uint16_t)__SWAP16(_x)
+#define	__BE_TO_CPU_16(_x)	(uint16_t)__SWAP16(_x)
+
+#define	__CPU_TO_LE_32(_x)	(uint32_t)__NOSWAP32(_x)
+#define	__LE_TO_CPU_32(_x)	(uint32_t)__NOSWAP32(_x)
+#define	__CPU_TO_BE_32(_x)	(uint32_t)__SWAP32(_x)
+#define	__BE_TO_CPU_32(_x)	(uint32_t)__SWAP32(_x)
+
+#define	__CPU_TO_LE_64(_x)	(uint64_t)__NOSWAP64(_x)
+#define	__LE_TO_CPU_64(_x)	(uint64_t)__NOSWAP64(_x)
+#define	__CPU_TO_BE_64(_x)	(uint64_t)__SWAP64(_x)
+#define	__BE_TO_CPU_64(_x)	(uint64_t)__SWAP64(_x)
+
+#else
+
+#error "Neither of EFSYS_IS_{BIG,LITTLE}_ENDIAN is set"
+
+#endif
+
+#define	__NATIVE_8(_x)	(uint8_t)(_x)
+
+/* Format string for printing an efx_byte_t */
+#define	EFX_BYTE_FMT "0x%02x"
+
+/* Format string for printing an efx_word_t */
+#define	EFX_WORD_FMT "0x%04x"
+
+/* Format string for printing an efx_dword_t */
+#define	EFX_DWORD_FMT "0x%08x"
+
+/* Format string for printing an efx_qword_t */
+#define	EFX_QWORD_FMT "0x%08x:%08x"
+
+/* Format string for printing an efx_oword_t */
+#define	EFX_OWORD_FMT "0x%08x:%08x:%08x:%08x"
+
+/* Parameters for printing an efx_byte_t */
+#define	EFX_BYTE_VAL(_byte)					\
+	((unsigned int)__NATIVE_8((_byte).eb_u8[0]))
+
+/* Parameters for printing an efx_word_t */
+#define	EFX_WORD_VAL(_word)					\
+	((unsigned int)__LE_TO_CPU_16((_word).ew_u16[0]))
+
+/* Parameters for printing an efx_dword_t */
+#define	EFX_DWORD_VAL(_dword)					\
+	((unsigned int)__LE_TO_CPU_32((_dword).ed_u32[0]))
+
+/* Parameters for printing an efx_qword_t */
+#define	EFX_QWORD_VAL(_qword)					\
+	((unsigned int)__LE_TO_CPU_32((_qword).eq_u32[1])),	\
+	((unsigned int)__LE_TO_CPU_32((_qword).eq_u32[0]))
+
+/* Parameters for printing an efx_oword_t */
+#define	EFX_OWORD_VAL(_oword)					\
+	((unsigned int)__LE_TO_CPU_32((_oword).eo_u32[3])),	\
+	((unsigned int)__LE_TO_CPU_32((_oword).eo_u32[2])),	\
+	((unsigned int)__LE_TO_CPU_32((_oword).eo_u32[1])),	\
+	((unsigned int)__LE_TO_CPU_32((_oword).eo_u32[0]))
+
+/*
+ * Stop lint complaining about some shifts.
+ */
+#ifdef	__lint
+extern int fix_lint;
+#define	FIX_LINT(_x)	(_x + fix_lint)
+#else
+#define	FIX_LINT(_x)	(_x)
+#endif
+
+/*
+ * Extract bit field portion [low,high) from the native-endian element
+ * which contains bits [min,max).
+ *
+ * For example, suppose "element" represents the high 32 bits of a
+ * 64-bit value, and we wish to extract the bits belonging to the bit
+ * field occupying bits 28-45 of this 64-bit value.
+ *
+ * Then EFX_EXTRACT(_element, 32, 63, 28, 45) would give
+ *
+ *   (_element) << 4
+ *
+ * The result will contain the relevant bits filled in in the range
+ * [0,high-low), with garbage in bits [high-low+1,...).
+ */
+#define	EFX_EXTRACT_NATIVE(_element, _min, _max, _low, _high)		\
+	((FIX_LINT(_low > _max) || FIX_LINT(_high < _min)) ?		\
+		0U :							\
+		((_low > _min) ?					\
+			((_element) >> (_low - _min)) :			\
+			((_element) << (_min - _low))))
+
+/*
+ * Extract bit field portion [low,high) from the 64-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define	EFX_EXTRACT64(_element, _min, _max, _low, _high)		\
+	EFX_EXTRACT_NATIVE(__LE_TO_CPU_64(_element), _min, _max, _low, _high)
+
+/*
+ * Extract bit field portion [low,high) from the 32-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define	EFX_EXTRACT32(_element, _min, _max, _low, _high)		\
+	EFX_EXTRACT_NATIVE(__LE_TO_CPU_32(_element), _min, _max, _low, _high)
+
+/*
+ * Extract bit field portion [low,high) from the 16-bit little-endian
+ * element which contains bits [min,max)
+ */
+#define	EFX_EXTRACT16(_element, _min, _max, _low, _high)		\
+	EFX_EXTRACT_NATIVE(__LE_TO_CPU_16(_element), _min, _max, _low, _high)
+
+/*
+ * Extract bit field portion [low,high) from the 8-bit
+ * element which contains bits [min,max)
+ */
+#define	EFX_EXTRACT8(_element, _min, _max, _low, _high)			\
+	EFX_EXTRACT_NATIVE(__NATIVE_8(_element), _min, _max, _low, _high)
+
+#define	EFX_EXTRACT_OWORD64(_oword, _low, _high)			\
+	(EFX_EXTRACT64((_oword).eo_u64[0], FIX_LINT(0), FIX_LINT(63),	\
+	    _low, _high) |						\
+	EFX_EXTRACT64((_oword).eo_u64[1], FIX_LINT(64), FIX_LINT(127),	\
+	    _low, _high))
+
+#define	EFX_EXTRACT_OWORD32(_oword, _low, _high)			\
+	(EFX_EXTRACT32((_oword).eo_u32[0], FIX_LINT(0), FIX_LINT(31),	\
+	    _low, _high) |						\
+	EFX_EXTRACT32((_oword).eo_u32[1], FIX_LINT(32), FIX_LINT(63),	\
+	    _low, _high) |						\
+	EFX_EXTRACT32((_oword).eo_u32[2], FIX_LINT(64), FIX_LINT(95),	\
+	    _low, _high) |						\
+	EFX_EXTRACT32((_oword).eo_u32[3], FIX_LINT(96), FIX_LINT(127),	\
+	    _low, _high))
+
+#define	EFX_EXTRACT_QWORD64(_qword, _low, _high)			\
+	(EFX_EXTRACT64((_qword).eq_u64[0], FIX_LINT(0), FIX_LINT(63),	\
+	    _low, _high))
+
+#define	EFX_EXTRACT_QWORD32(_qword, _low, _high)			\
+	(EFX_EXTRACT32((_qword).eq_u32[0], FIX_LINT(0), FIX_LINT(31),	\
+	    _low, _high) |						\
+	EFX_EXTRACT32((_qword).eq_u32[1], FIX_LINT(32), FIX_LINT(63),	\
+	    _low, _high))
+
+#define	EFX_EXTRACT_DWORD(_dword, _low, _high)				\
+	(EFX_EXTRACT32((_dword).ed_u32[0], FIX_LINT(0), FIX_LINT(31),	\
+	    _low, _high))
+
+#define	EFX_EXTRACT_WORD(_word, _low, _high)				\
+	(EFX_EXTRACT16((_word).ew_u16[0], FIX_LINT(0), FIX_LINT(15),	\
+	    _low, _high))
+
+#define	EFX_EXTRACT_BYTE(_byte, _low, _high)				\
+	(EFX_EXTRACT8((_byte).eb_u8[0], FIX_LINT(0), FIX_LINT(7),	\
+	    _low, _high))
+
+
+#define	EFX_OWORD_FIELD64(_oword, _field)				\
+	((uint32_t)EFX_EXTRACT_OWORD64(_oword, EFX_LOW_BIT(_field),	\
+	    EFX_HIGH_BIT(_field)) & EFX_MASK32(_field))
+
+#define	EFX_OWORD_FIELD32(_oword, _field)				\
+	(EFX_EXTRACT_OWORD32(_oword, EFX_LOW_BIT(_field),		\
+	    EFX_HIGH_BIT(_field)) & EFX_MASK32(_field))
+
+#define	EFX_QWORD_FIELD64(_qword, _field)				\
+	((uint32_t)EFX_EXTRACT_QWORD64(_qword, EFX_LOW_BIT(_field),	\
+	    EFX_HIGH_BIT(_field)) & EFX_MASK32(_field))
+
+#define	EFX_QWORD_FIELD32(_qword, _field)				\
+	(EFX_EXTRACT_QWORD32(_qword, EFX_LOW_BIT(_field),		\
+	    EFX_HIGH_BIT(_field)) & EFX_MASK32(_field))
+
+#define	EFX_DWORD_FIELD(_dword, _field)					\
+	(EFX_EXTRACT_DWORD(_dword, EFX_LOW_BIT(_field),			\
+	    EFX_HIGH_BIT(_field)) & EFX_MASK32(_field))
+
+#define	EFX_WORD_FIELD(_word, _field)					\
+	(EFX_EXTRACT_WORD(_word, EFX_LOW_BIT(_field),			\
+	    EFX_HIGH_BIT(_field)) & EFX_MASK16(_field))
+
+#define	EFX_BYTE_FIELD(_byte, _field)					\
+	(EFX_EXTRACT_BYTE(_byte, EFX_LOW_BIT(_field),			\
+	    EFX_HIGH_BIT(_field)) & EFX_MASK8(_field))
+
+
+#define	EFX_OWORD_IS_EQUAL64(_oword_a, _oword_b)			\
+	((_oword_a).eo_u64[0] == (_oword_b).eo_u64[0] &&		\
+	    (_oword_a).eo_u64[1] == (_oword_b).eo_u64[1])
+
+#define	EFX_OWORD_IS_EQUAL32(_oword_a, _oword_b)			\
+	((_oword_a).eo_u32[0] == (_oword_b).eo_u32[0] &&		\
+	    (_oword_a).eo_u32[1] == (_oword_b).eo_u32[1] &&		\
+	    (_oword_a).eo_u32[2] == (_oword_b).eo_u32[2] &&		\
+	    (_oword_a).eo_u32[3] == (_oword_b).eo_u32[3])
+
+#define	EFX_QWORD_IS_EQUAL64(_qword_a, _qword_b)			\
+	((_qword_a).eq_u64[0] == (_qword_b).eq_u64[0])
+
+#define	EFX_QWORD_IS_EQUAL32(_qword_a, _qword_b)			\
+	((_qword_a).eq_u32[0] == (_qword_b).eq_u32[0] &&		\
+	    (_qword_a).eq_u32[1] == (_qword_b).eq_u32[1])
+
+#define	EFX_DWORD_IS_EQUAL(_dword_a, _dword_b)				\
+	((_dword_a).ed_u32[0] == (_dword_b).ed_u32[0])
+
+#define	EFX_WORD_IS_EQUAL(_word_a, _word_b)				\
+	((_word_a).ew_u16[0] == (_word_b).ew_u16[0])
+
+#define	EFX_BYTE_IS_EQUAL(_byte_a, _byte_b)				\
+	((_byte_a).eb_u8[0] == (_byte_b).eb_u8[0])
+
+
+#define	EFX_OWORD_IS_ZERO64(_oword)					\
+	(((_oword).eo_u64[0] |						\
+	    (_oword).eo_u64[1]) == 0)
+
+#define	EFX_OWORD_IS_ZERO32(_oword)					\
+	(((_oword).eo_u32[0] |						\
+	    (_oword).eo_u32[1] |					\
+	    (_oword).eo_u32[2] |					\
+	    (_oword).eo_u32[3]) == 0)
+
+#define	EFX_QWORD_IS_ZERO64(_qword)					\
+	(((_qword).eq_u64[0]) == 0)
+
+#define	EFX_QWORD_IS_ZERO32(_qword)					\
+	(((_qword).eq_u32[0] |						\
+	    (_qword).eq_u32[1]) == 0)
+
+#define	EFX_DWORD_IS_ZERO(_dword)					\
+	(((_dword).ed_u32[0]) == 0)
+
+#define	EFX_WORD_IS_ZERO(_word)						\
+	(((_word).ew_u16[0]) == 0)
+
+#define	EFX_BYTE_IS_ZERO(_byte)						\
+	(((_byte).eb_u8[0]) == 0)
+
+
+#define	EFX_OWORD_IS_SET64(_oword)					\
+	(((_oword).eo_u64[0] &						\
+	    (_oword).eo_u64[1]) == ~((uint64_t)0))
+
+#define	EFX_OWORD_IS_SET32(_oword)					\
+	(((_oword).eo_u32[0] &						\
+	    (_oword).eo_u32[1] &					\
+	    (_oword).eo_u32[2] &					\
+	    (_oword).eo_u32[3]) == ~((uint32_t)0))
+
+#define	EFX_QWORD_IS_SET64(_qword)					\
+	(((_qword).eq_u64[0]) == ~((uint32_t)0))
+
+#define	EFX_QWORD_IS_SET32(_qword)					\
+	(((_qword).eq_u32[0] &						\
+	    (_qword).eq_u32[1]) == ~((uint32_t)0))
+
+#define	EFX_DWORD_IS_SET(_dword)					\
+	((_dword).ed_u32[0] == ~((uint32_t)0))
+
+#define	EFX_WORD_IS_SET(_word)						\
+	((_word).ew_u16[0] == ~((uint16_t)0))
+
+#define	EFX_BYTE_IS_SET(_byte)						\
+	((_byte).eb_u8[0] == ~((uint8_t)0))
+
+/*
+ * Construct bit field portion
+ *
+ * Creates the portion of the bit field [low,high) that lies within
+ * the range [min,max).
+ */
+
+#define	EFX_INSERT_NATIVE64(_min, _max, _low, _high, _value)		\
+	(((_low > _max) || (_high < _min)) ?				\
+		0U :							\
+		((_low > _min) ?					\
+			(((uint64_t)(_value)) << (_low - _min)) :	\
+			(((uint64_t)(_value)) >> (_min - _low))))
+
+#define	EFX_INSERT_NATIVE32(_min, _max, _low, _high, _value)		\
+	(((_low > _max) || (_high < _min)) ?				\
+		0U :							\
+		((_low > _min) ?					\
+			(((uint32_t)(_value)) << (_low - _min)) :	\
+			(((uint32_t)(_value)) >> (_min - _low))))
+
+#define	EFX_INSERT_NATIVE16(_min, _max, _low, _high, _value)		\
+	(((_low > _max) || (_high < _min)) ?				\
+		0U :							\
+		(uint16_t)((_low > _min) ?				\
+				((_value) << (_low - _min)) :		\
+				((_value) >> (_min - _low))))
+
+#define	EFX_INSERT_NATIVE8(_min, _max, _low, _high, _value)		\
+	(((_low > _max) || (_high < _min)) ?				\
+		0U :							\
+		(uint8_t)((_low > _min) ?				\
+				((_value) << (_low - _min)) :	\
+				((_value) >> (_min - _low))))
+
+/*
+ * Construct bit field portion
+ *
+ * Creates the portion of the named bit field that lies within the
+ * range [min,max).
+ */
+#define	EFX_INSERT_FIELD_NATIVE64(_min, _max, _field, _value)		\
+	EFX_INSERT_NATIVE64(_min, _max, EFX_LOW_BIT(_field),		\
+	    EFX_HIGH_BIT(_field), _value)
+
+#define	EFX_INSERT_FIELD_NATIVE32(_min, _max, _field, _value)		\
+	EFX_INSERT_NATIVE32(_min, _max, EFX_LOW_BIT(_field),		\
+	    EFX_HIGH_BIT(_field), _value)
+
+#define	EFX_INSERT_FIELD_NATIVE16(_min, _max, _field, _value)		\
+	EFX_INSERT_NATIVE16(_min, _max, EFX_LOW_BIT(_field),		\
+	    EFX_HIGH_BIT(_field), _value)
+
+#define	EFX_INSERT_FIELD_NATIVE8(_min, _max, _field, _value)		\
+	EFX_INSERT_NATIVE8(_min, _max, EFX_LOW_BIT(_field),		\
+	    EFX_HIGH_BIT(_field), _value)
+
+/*
+ * Construct bit field
+ *
+ * Creates the portion of the named bit fields that lie within the
+ * range [min,max).
+ */
+#define	EFX_INSERT_FIELDS64(_min, _max,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	__CPU_TO_LE_64(							\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field1, _value1) |	\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field2, _value2) |	\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field3, _value3) |	\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field4, _value4) |	\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field5, _value5) |	\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field6, _value6) |	\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field7, _value7) |	\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field8, _value8) |	\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field9, _value9) |	\
+	    EFX_INSERT_FIELD_NATIVE64(_min, _max, _field10, _value10))
+
+#define	EFX_INSERT_FIELDS32(_min, _max,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	__CPU_TO_LE_32(							\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field1, _value1) |	\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field2, _value2) |	\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field3, _value3) |	\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field4, _value4) |	\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field5, _value5) |	\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field6, _value6) |	\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field7, _value7) |	\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field8, _value8) |	\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field9, _value9) |	\
+	    EFX_INSERT_FIELD_NATIVE32(_min, _max, _field10, _value10))
+
+#define	EFX_INSERT_FIELDS16(_min, _max,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	__CPU_TO_LE_16(							\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field1, _value1) |	\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field2, _value2) |	\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field3, _value3) |	\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field4, _value4) |	\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field5, _value5) |	\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field6, _value6) |	\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field7, _value7) |	\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field8, _value8) |	\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field9, _value9) |	\
+	    EFX_INSERT_FIELD_NATIVE16(_min, _max, _field10, _value10))
+
+#define	EFX_INSERT_FIELDS8(_min, _max,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	__NATIVE_8(							\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field1, _value1) |	\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field2, _value2) |	\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field3, _value3) |	\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field4, _value4) |	\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field5, _value5) |	\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field6, _value6) |	\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field7, _value7) |	\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field8, _value8) |	\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field9, _value9) |	\
+	    EFX_INSERT_FIELD_NATIVE8(_min, _max, _field10, _value10))
+
+#define	EFX_POPULATE_OWORD64(_oword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u64[0] = EFX_INSERT_FIELDS64(0, 63,		\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u64[1] = EFX_INSERT_FIELDS64(64, 127,	\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_POPULATE_OWORD32(_oword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[0] = EFX_INSERT_FIELDS32(0, 31,		\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[1] = EFX_INSERT_FIELDS32(32, 63,	\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[2] = EFX_INSERT_FIELDS32(64, 95,	\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[3] = EFX_INSERT_FIELDS32(96, 127,	\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_POPULATE_QWORD64(_qword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u64[0] = EFX_INSERT_FIELDS64(0, 63,		\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_POPULATE_QWORD32(_qword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u32[0] = EFX_INSERT_FIELDS32(0, 31,		\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u32[1] = EFX_INSERT_FIELDS32(32, 63,	\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_POPULATE_DWORD(_dword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_dword).ed_u32[0] = EFX_INSERT_FIELDS32(0, 31,		\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_POPULATE_WORD(_word,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_word).ew_u16[0] = EFX_INSERT_FIELDS16(0, 15,		\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+#define	EFX_POPULATE_BYTE(_byte,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9,	\
+	    _field10, _value10)						\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_byte).eb_u8[0] = EFX_INSERT_FIELDS8(0, 7,		\
+		    _field1, _value1, _field2, _value2,			\
+		    _field3, _value3, _field4, _value4,			\
+		    _field5, _value5, _field6, _value6,			\
+		    _field7, _value7, _field8, _value8,			\
+		    _field9, _value9, _field10, _value10);		\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+/* Populate an octword field with various numbers of arguments */
+#define	EFX_POPULATE_OWORD_10 EFX_POPULATE_OWORD
+
+#define	EFX_POPULATE_OWORD_9(_oword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)	\
+	EFX_POPULATE_OWORD_10(_oword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)
+
+#define	EFX_POPULATE_OWORD_8(_oword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)				\
+	EFX_POPULATE_OWORD_9(_oword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)
+
+#define	EFX_POPULATE_OWORD_7(_oword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)						\
+	EFX_POPULATE_OWORD_8(_oword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)
+
+#define	EFX_POPULATE_OWORD_6(_oword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)	\
+	EFX_POPULATE_OWORD_7(_oword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)
+
+#define	EFX_POPULATE_OWORD_5(_oword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)				\
+	EFX_POPULATE_OWORD_6(_oword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)
+
+#define	EFX_POPULATE_OWORD_4(_oword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)						\
+	EFX_POPULATE_OWORD_5(_oword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)
+
+#define	EFX_POPULATE_OWORD_3(_oword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3)	\
+	EFX_POPULATE_OWORD_4(_oword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3)
+
+#define	EFX_POPULATE_OWORD_2(_oword,					\
+	    _field1, _value1, _field2, _value2)				\
+	EFX_POPULATE_OWORD_3(_oword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2)
+
+#define	EFX_POPULATE_OWORD_1(_oword,					\
+	    _field1, _value1)						\
+	EFX_POPULATE_OWORD_2(_oword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1)
+
+#define	EFX_ZERO_OWORD(_oword)						\
+	EFX_POPULATE_OWORD_1(_oword, EFX_DUMMY_FIELD, 0)
+
+#define	EFX_SET_OWORD64(_oword)						\
+	EFX_POPULATE_OWORD_2(_oword,					\
+	    EFX_QWORD_0, (uint64_t)-1, EFX_QWORD_1, (uint64_t)-1)
+
+#define	EFX_SET_OWORD32(_oword)						\
+	EFX_POPULATE_OWORD_4(_oword,					\
+	    EFX_DWORD_0, 0xffffffff, EFX_DWORD_1, 0xffffffff,		\
+	    EFX_DWORD_2, 0xffffffff, EFX_DWORD_3, 0xffffffff)
+
+/* Populate a quadword field with various numbers of arguments */
+#define	EFX_POPULATE_QWORD_10 EFX_POPULATE_QWORD
+
+#define	EFX_POPULATE_QWORD_9(_qword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)	\
+	EFX_POPULATE_QWORD_10(_qword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)
+
+#define	EFX_POPULATE_QWORD_8(_qword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)				\
+	EFX_POPULATE_QWORD_9(_qword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)
+
+#define	EFX_POPULATE_QWORD_7(_qword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)						\
+	EFX_POPULATE_QWORD_8(_qword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)
+
+#define	EFX_POPULATE_QWORD_6(_qword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)	\
+	EFX_POPULATE_QWORD_7(_qword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)
+
+#define	EFX_POPULATE_QWORD_5(_qword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)				\
+	EFX_POPULATE_QWORD_6(_qword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)
+
+#define	EFX_POPULATE_QWORD_4(_qword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)						\
+	EFX_POPULATE_QWORD_5(_qword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)
+
+#define	EFX_POPULATE_QWORD_3(_qword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3)	\
+	EFX_POPULATE_QWORD_4(_qword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3)
+
+#define	EFX_POPULATE_QWORD_2(_qword,					\
+	    _field1, _value1, _field2, _value2)				\
+	EFX_POPULATE_QWORD_3(_qword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2)
+
+#define	EFX_POPULATE_QWORD_1(_qword,					\
+	    _field1, _value1)						\
+	EFX_POPULATE_QWORD_2(_qword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1)
+
+#define	EFX_ZERO_QWORD(_qword)						\
+	EFX_POPULATE_QWORD_1(_qword, EFX_DUMMY_FIELD, 0)
+
+#define	EFX_SET_QWORD64(_qword)						\
+	EFX_POPULATE_QWORD_1(_qword,					\
+	    EFX_QWORD_0, (uint64_t)-1)
+
+#define	EFX_SET_QWORD32(_qword)						\
+	EFX_POPULATE_QWORD_2(_qword,					\
+	    EFX_DWORD_0, 0xffffffff, EFX_DWORD_1, 0xffffffff)
+
+/* Populate a dword field with various numbers of arguments */
+#define	EFX_POPULATE_DWORD_10 EFX_POPULATE_DWORD
+
+#define	EFX_POPULATE_DWORD_9(_dword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)	\
+	EFX_POPULATE_DWORD_10(_dword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)
+
+#define	EFX_POPULATE_DWORD_8(_dword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)				\
+	EFX_POPULATE_DWORD_9(_dword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)
+
+#define	EFX_POPULATE_DWORD_7(_dword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)						\
+	EFX_POPULATE_DWORD_8(_dword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)
+
+#define	EFX_POPULATE_DWORD_6(_dword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)	\
+	EFX_POPULATE_DWORD_7(_dword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)
+
+#define	EFX_POPULATE_DWORD_5(_dword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)				\
+	EFX_POPULATE_DWORD_6(_dword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)
+
+#define	EFX_POPULATE_DWORD_4(_dword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)						\
+	EFX_POPULATE_DWORD_5(_dword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)
+
+#define	EFX_POPULATE_DWORD_3(_dword,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3)	\
+	EFX_POPULATE_DWORD_4(_dword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2, _field3, _value3)
+
+#define	EFX_POPULATE_DWORD_2(_dword,					\
+	    _field1, _value1, _field2, _value2)				\
+	EFX_POPULATE_DWORD_3(_dword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1, _field2, _value2)
+
+#define	EFX_POPULATE_DWORD_1(_dword,					\
+	    _field1, _value1)						\
+	EFX_POPULATE_DWORD_2(_dword, EFX_DUMMY_FIELD, 0,		\
+	    _field1, _value1)
+
+#define	EFX_ZERO_DWORD(_dword)						\
+	EFX_POPULATE_DWORD_1(_dword, EFX_DUMMY_FIELD, 0)
+
+#define	EFX_SET_DWORD(_dword)						\
+	EFX_POPULATE_DWORD_1(_dword,					\
+	    EFX_DWORD_0, 0xffffffff)
+
+/* Populate a word field with various numbers of arguments */
+#define	EFX_POPULATE_WORD_10 EFX_POPULATE_WORD
+
+#define	EFX_POPULATE_WORD_9(_word,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)	\
+	EFX_POPULATE_WORD_10(_word, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)
+
+#define	EFX_POPULATE_WORD_8(_word,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)				\
+	EFX_POPULATE_WORD_9(_word, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)
+
+#define	EFX_POPULATE_WORD_7(_word,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)						\
+	EFX_POPULATE_WORD_8(_word, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)
+
+#define	EFX_POPULATE_WORD_6(_word,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)	\
+	EFX_POPULATE_WORD_7(_word, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)
+
+#define	EFX_POPULATE_WORD_5(_word,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)				\
+	EFX_POPULATE_WORD_6(_word, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)
+
+#define	EFX_POPULATE_WORD_4(_word,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)						\
+	EFX_POPULATE_WORD_5(_word, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)
+
+#define	EFX_POPULATE_WORD_3(_word,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3)	\
+	EFX_POPULATE_WORD_4(_word, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3)
+
+#define	EFX_POPULATE_WORD_2(_word,					\
+	    _field1, _value1, _field2, _value2)				\
+	EFX_POPULATE_WORD_3(_word, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2)
+
+#define	EFX_POPULATE_WORD_1(_word,					\
+	    _field1, _value1)						\
+	EFX_POPULATE_WORD_2(_word, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1)
+
+#define	EFX_ZERO_WORD(_word)						\
+	EFX_POPULATE_WORD_1(_word, EFX_DUMMY_FIELD, 0)
+
+#define	EFX_SET_WORD(_word)						\
+	EFX_POPULATE_WORD_1(_word,					\
+	    EFX_WORD_0, 0xffff)
+
+/* Populate a byte field with various numbers of arguments */
+#define	EFX_POPULATE_BYTE_10 EFX_POPULATE_BYTE
+
+#define	EFX_POPULATE_BYTE_9(_byte,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)	\
+	EFX_POPULATE_BYTE_10(_byte, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8,	_field9, _value9)
+
+#define	EFX_POPULATE_BYTE_8(_byte,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)				\
+	EFX_POPULATE_BYTE_9(_byte, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7, _field8, _value8)
+
+#define	EFX_POPULATE_BYTE_7(_byte,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)						\
+	EFX_POPULATE_BYTE_8(_byte, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6,	\
+	    _field7, _value7)
+
+#define	EFX_POPULATE_BYTE_6(_byte,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)	\
+	EFX_POPULATE_BYTE_7(_byte, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5,	_field6, _value6)
+
+#define	EFX_POPULATE_BYTE_5(_byte,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)				\
+	EFX_POPULATE_BYTE_6(_byte, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4, _field5, _value5)
+
+#define	EFX_POPULATE_BYTE_4(_byte,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)						\
+	EFX_POPULATE_BYTE_5(_byte, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3,	\
+	    _field4, _value4)
+
+#define	EFX_POPULATE_BYTE_3(_byte,					\
+	    _field1, _value1, _field2, _value2, _field3, _value3)	\
+	EFX_POPULATE_BYTE_4(_byte, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2, _field3, _value3)
+
+#define	EFX_POPULATE_BYTE_2(_byte,					\
+	    _field1, _value1, _field2, _value2)				\
+	EFX_POPULATE_BYTE_3(_byte, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1, _field2, _value2)
+
+#define	EFX_POPULATE_BYTE_1(_byte,					\
+	    _field1, _value1)						\
+	EFX_POPULATE_BYTE_2(_byte, EFX_DUMMY_FIELD, 0,			\
+	    _field1, _value1)
+
+#define	EFX_ZERO_BYTE(_byte)						\
+	EFX_POPULATE_BYTE_1(_byte, EFX_DUMMY_FIELD, 0)
+
+#define	EFX_SET_BYTE(_byte)						\
+	EFX_POPULATE_BYTE_1(_byte,					\
+	    EFX_BYTE_0, 0xff)
+
+/*
+ * Modify a named field within an already-populated structure.  Used
+ * for read-modify-write operations.
+ */
+
+#define	EFX_INSERT_FIELD64(_min, _max, _field, _value)			\
+	__CPU_TO_LE_64(EFX_INSERT_FIELD_NATIVE64(_min, _max, _field, _value))
+
+#define	EFX_INSERT_FIELD32(_min, _max, _field, _value)			\
+	__CPU_TO_LE_32(EFX_INSERT_FIELD_NATIVE32(_min, _max, _field, _value))
+
+#define	EFX_INSERT_FIELD16(_min, _max, _field, _value)			\
+	__CPU_TO_LE_16(EFX_INSERT_FIELD_NATIVE16(_min, _max, _field, _value))
+
+#define	EFX_INSERT_FIELD8(_min, _max, _field, _value)			\
+	__NATIVE_8(EFX_INSERT_FIELD_NATIVE8(_min, _max, _field, _value))
+
+#define	EFX_INPLACE_MASK64(_min, _max, _field)			       	\
+	EFX_INSERT_FIELD64(_min, _max, _field, EFX_MASK64(_field))
+
+#define	EFX_INPLACE_MASK32(_min, _max, _field)			       	\
+	EFX_INSERT_FIELD32(_min, _max, _field, EFX_MASK32(_field))
+
+#define	EFX_INPLACE_MASK16(_min, _max, _field)			       	\
+	EFX_INSERT_FIELD16(_min, _max, _field, EFX_MASK16(_field))
+
+#define	EFX_INPLACE_MASK8(_min, _max, _field)			       	\
+	EFX_INSERT_FIELD8(_min, _max, _field, EFX_MASK8(_field))
+
+#define	EFX_SET_OWORD_FIELD64(_oword, _field, _value)			\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u64[0] = (((_oword).eo_u64[0] &		\
+		    ~EFX_INPLACE_MASK64(0, 63, _field)) |		\
+		    EFX_INSERT_FIELD64(0, 63, _field, _value));		\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u64[1] = (((_oword).eo_u64[1] &		\
+		    ~EFX_INPLACE_MASK64(64, 127, _field)) |		\
+		    EFX_INSERT_FIELD64(64, 127, _field, _value));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_OWORD_FIELD32(_oword, _field, _value)			\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[0] = (((_oword).eo_u32[0] &		\
+		    ~EFX_INPLACE_MASK32(0, 31, _field)) |		\
+		    EFX_INSERT_FIELD32(0, 31, _field, _value));		\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[1] = (((_oword).eo_u32[1] &		\
+		    ~EFX_INPLACE_MASK32(32, 63, _field)) |		\
+		    EFX_INSERT_FIELD32(32, 63, _field, _value));	\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[2] = (((_oword).eo_u32[2] &		\
+		    ~EFX_INPLACE_MASK32(64, 95, _field)) |		\
+		    EFX_INSERT_FIELD32(64, 95, _field, _value));	\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[3] = (((_oword).eo_u32[3] &		\
+		    ~EFX_INPLACE_MASK32(96, 127, _field)) |		\
+		    EFX_INSERT_FIELD32(96, 127, _field, _value));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_QWORD_FIELD64(_qword, _field, _value)			\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u64[0] = (((_qword).eq_u64[0] &		\
+		    ~EFX_INPLACE_MASK64(0, 63, _field)) |		\
+		    EFX_INSERT_FIELD64(0, 63, _field, _value));		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_QWORD_FIELD32(_qword, _field, _value)			\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u32[0] = (((_qword).eq_u32[0] &		\
+		    ~EFX_INPLACE_MASK32(0, 31, _field)) |		\
+		    EFX_INSERT_FIELD32(0, 31, _field, _value));		\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u32[1] = (((_qword).eq_u32[1] &		\
+		    ~EFX_INPLACE_MASK32(32, 63, _field)) |		\
+		    EFX_INSERT_FIELD32(32, 63, _field, _value));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_DWORD_FIELD(_dword, _field, _value)			\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_dword).ed_u32[0] = (((_dword).ed_u32[0] &		\
+		    ~EFX_INPLACE_MASK32(0, 31, _field)) |		\
+		    EFX_INSERT_FIELD32(0, 31, _field, _value));		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_WORD_FIELD(_word, _field, _value)			\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_word).ew_u16[0] = (((_word).ew_u16[0] &		\
+		    ~EFX_INPLACE_MASK16(0, 15, _field)) |		\
+		    EFX_INSERT_FIELD16(0, 15, _field, _value));		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_BYTE_FIELD(_byte, _field, _value)			\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_byte).eb_u8[0] = (((_byte).eb_u8[0] &			\
+		    ~EFX_INPLACE_MASK8(0, 7, _field)) |			\
+		    EFX_INSERT_FIELD8(0, 7, _field, _value));		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+/*
+ * Set or clear a numbered bit within an octword.
+ */
+ 
+#define	EFX_SHIFT64(_bit, _base)					\
+	(((_bit) >= (_base) && (_bit) < (_base) + 64) ?			\
+		((uint64_t)1 << ((_bit) - (_base))) :			\
+		0U)
+
+#define	EFX_SHIFT32(_bit, _base)					\
+	(((_bit) >= (_base) && (_bit) < (_base) + 32) ?			\
+		((uint32_t)1 << ((_bit) - (_base))) :			\
+		0U)
+
+#define	EFX_SHIFT16(_bit, _base)					\
+	(((_bit) >= (_base) && (_bit) < (_base) + 16) ?			\
+		(uint16_t)(1 << ((_bit) - (_base))) :			\
+		0U)
+
+#define	EFX_SHIFT8(_bit, _base)						\
+	(((_bit) >= (_base) && (_bit) < (_base) + 8) ?			\
+		(uint8_t)(1 << ((_bit) - (_base))) :			\
+		0U)
+
+#define	EFX_SET_OWORD_BIT64(_oword, _bit)				\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u64[0] |=					\
+		    __CPU_TO_LE_64(EFX_SHIFT64(_bit, FIX_LINT(0)));	\
+		(_oword).eo_u64[1] |=					\
+		    __CPU_TO_LE_64(EFX_SHIFT64(_bit, FIX_LINT(64)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_OWORD_BIT32(_oword, _bit)				\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[0] |=					\
+		    __CPU_TO_LE_32(EFX_SHIFT32(_bit, FIX_LINT(0)));	\
+		(_oword).eo_u32[1] |=					\
+		    __CPU_TO_LE_32(EFX_SHIFT32(_bit, FIX_LINT(32)));	\
+		(_oword).eo_u32[2] |=					\
+		    __CPU_TO_LE_32(EFX_SHIFT32(_bit, FIX_LINT(64)));	\
+		(_oword).eo_u32[3] |=					\
+		    __CPU_TO_LE_32(EFX_SHIFT32(_bit, FIX_LINT(96)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_CLEAR_OWORD_BIT64(_oword, _bit)				\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u64[0] &=					\
+		    __CPU_TO_LE_64(~EFX_SHIFT64(_bit, FIX_LINT(0)));	\
+		(_oword).eo_u64[1] &=					\
+		    __CPU_TO_LE_64(~EFX_SHIFT64(_bit, FIX_LINT(64)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_CLEAR_OWORD_BIT32(_oword, _bit)				\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_oword).eo_u32[0] &=					\
+		    __CPU_TO_LE_32(~EFX_SHIFT32(_bit, FIX_LINT(0)));	\
+		(_oword).eo_u32[1] &=					\
+		    __CPU_TO_LE_32(~EFX_SHIFT32(_bit, FIX_LINT(32)));	\
+		(_oword).eo_u32[2] &=					\
+		    __CPU_TO_LE_32(~EFX_SHIFT32(_bit, FIX_LINT(64)));	\
+		(_oword).eo_u32[3] &=					\
+		    __CPU_TO_LE_32(~EFX_SHIFT32(_bit, FIX_LINT(96)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_QWORD_BIT64(_qword, _bit)				\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u64[0] |=					\
+		    __CPU_TO_LE_64(EFX_SHIFT64(_bit, FIX_LINT(0)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_QWORD_BIT32(_qword, _bit)				\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u32[0] |=					\
+		    __CPU_TO_LE_32(EFX_SHIFT32(_bit, FIX_LINT(0)));	\
+		(_qword).eq_u32[1] |=					\
+		    __CPU_TO_LE_32(EFX_SHIFT32(_bit, FIX_LINT(32)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_CLEAR_QWORD_BIT64(_qword, _bit)				\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u64[0] &=					\
+		    __CPU_TO_LE_64(~EFX_SHIFT64(_bit, FIX_LINT(0)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_CLEAR_QWORD_BIT32(_qword, _bit)				\
+	do {								\
+		_NOTE(CONSTANTCONDITION) 				\
+		(_qword).eq_u32[0] &=					\
+		    __CPU_TO_LE_32(~EFX_SHIFT32(_bit, FIX_LINT(0)));	\
+		(_qword).eq_u32[1] &=					\
+		    __CPU_TO_LE_32(~EFX_SHIFT32(_bit, FIX_LINT(32)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_DWORD_BIT(_dword, _bit)					\
+	do {								\
+		(_dword).ed_u32[0] |=					\
+		    __CPU_TO_LE_32(EFX_SHIFT32(_bit, FIX_LINT(0)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_CLEAR_DWORD_BIT(_dword, _bit)				\
+	do {								\
+		(_dword).ed_u32[0] &=					\
+		    __CPU_TO_LE_32(~EFX_SHIFT32(_bit, FIX_LINT(0)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_WORD_BIT(_word, _bit)					\
+	do {								\
+		(_word).ew_u16[0] |=					\
+		    __CPU_TO_LE_16(EFX_SHIFT16(_bit, FIX_LINT(0)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_CLEAR_WORD_BIT(_word, _bit)					\
+	do {								\
+		(_word).ew_u32[0] &=					\
+		    __CPU_TO_LE_16(~EFX_SHIFT16(_bit, FIX_LINT(0)));	\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_SET_BYTE_BIT(_byte, _bit)					\
+	do {								\
+		(_byte).eb_u8[0] |=					\
+		    __NATIVE_8(EFX_SHIFT8(_bit, FIX_LINT(0)));		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_CLEAR_BYTE_BIT(_byte, _bit)					\
+	do {								\
+		(_byte).eb_u8[0] &=					\
+		    __NATIVE_8(~EFX_SHIFT8(_bit, FIX_LINT(0)));		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_OR_OWORD64(_oword1, _oword2)				\
+	do {								\
+		(_oword1).eo_u64[0] |= (_oword2).eo_u64[0];		\
+		(_oword1).eo_u64[1] |= (_oword2).eo_u64[1];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_OR_OWORD32(_oword1, _oword2)				\
+	do {								\
+		(_oword1).eo_u32[0] |= (_oword2).eo_u32[0];		\
+		(_oword1).eo_u32[1] |= (_oword2).eo_u32[1];		\
+		(_oword1).eo_u32[2] |= (_oword2).eo_u32[2];		\
+		(_oword1).eo_u32[3] |= (_oword2).eo_u32[3];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_AND_OWORD64(_oword1, _oword2)				\
+	do {								\
+		(_oword1).eo_u64[0] &= (_oword2).eo_u64[0];		\
+		(_oword1).eo_u64[1] &= (_oword2).eo_u64[1];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_AND_OWORD32(_oword1, _oword2)				\
+	do {								\
+		(_oword1).eo_u32[0] &= (_oword2).eo_u32[0];		\
+		(_oword1).eo_u32[1] &= (_oword2).eo_u32[1];		\
+		(_oword1).eo_u32[2] &= (_oword2).eo_u32[2];		\
+		(_oword1).eo_u32[3] &= (_oword2).eo_u32[3];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_OR_QWORD64(_qword1, _qword2)				\
+	do {								\
+		(_qword1).eq_u64[0] |= (_qword2).eq_u64[0];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_OR_QWORD32(_qword1, _qword2)				\
+	do {								\
+		(_qword1).eq_u32[0] |= (_qword2).eq_u32[0];		\
+		(_qword1).eq_u32[1] |= (_qword2).eq_u32[1];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_AND_QWORD64(_qword1, _qword2)				\
+	do {								\
+		(_qword1).eq_u64[0] &= (_qword2).eq_u64[0];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_AND_QWORD32(_qword1, _qword2)				\
+	do {								\
+		(_qword1).eq_u32[0] &= (_qword2).eq_u32[0];		\
+		(_qword1).eq_u32[1] &= (_qword2).eq_u32[1];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_OR_DWORD(_dword1, _dword2)					\
+	do {								\
+		(_dword1).ed_u32[0] |= (_dword2).ed_u32[0];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_AND_DWORD(_dword1, _dword2)					\
+	do {								\
+		(_dword1).ed_u32[0] &= (_dword2).ed_u32[0];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_OR_WORD(_word1, _word2)					\
+	do {								\
+		(_word1).ew_u16[0] |= (_word2).ew_u16[0];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_AND_WORD(_word1, _word2)					\
+	do {								\
+		(_word1).ew_u16[0] &= (_word2).ew_u16[0];		\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_OR_BYTE(_byte1, _byte2)					\
+	do {								\
+		(_byte1).eb_u8[0] &= (_byte2).eb_u8[0];			\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#define	EFX_AND_BYTE(_byte1, _byte2)					\
+	do {								\
+		(_byte1).eb_u8[0] &= (_byte2).eb_u8[0];			\
+	_NOTE(CONSTANTCONDITION) 					\
+	} while (B_FALSE)
+
+#if EFSYS_USE_UINT64
+#define	EFX_OWORD_FIELD		EFX_OWORD_FIELD64
+#define	EFX_QWORD_FIELD		EFX_QWORD_FIELD64
+#define	EFX_OWORD_IS_EQUAL	EFX_OWORD_IS_EQUAL64
+#define	EFX_QWORD_IS_EQUAL	EFX_QWORD_IS_EQUAL64
+#define	EFX_OWORD_IS_ZERO	EFX_OWORD_IS_ZERO64
+#define	EFX_QWORD_IS_ZERO	EFX_QWORD_IS_ZERO64
+#define	EFX_OWORD_IS_SET	EFX_OWORD_IS_SET64
+#define	EFX_QWORD_IS_SET	EFX_QWORD_IS_SET64
+#define	EFX_POPULATE_OWORD	EFX_POPULATE_OWORD64
+#define	EFX_POPULATE_QWORD	EFX_POPULATE_QWORD64
+#define	EFX_SET_OWORD		EFX_SET_OWORD64
+#define	EFX_SET_QWORD		EFX_SET_QWORD64
+#define	EFX_SET_OWORD_FIELD	EFX_SET_OWORD_FIELD64
+#define	EFX_SET_QWORD_FIELD	EFX_SET_QWORD_FIELD64
+#define	EFX_SET_OWORD_BIT	EFX_SET_OWORD_BIT64
+#define	EFX_CLEAR_OWORD_BIT	EFX_CLEAR_OWORD_BIT64
+#define	EFX_SET_QWORD_BIT	EFX_SET_QWORD_BIT64
+#define	EFX_CLEAR_QWORD_BIT	EFX_CLEAR_QWORD_BIT64
+#define	EFX_OR_OWORD		EFX_OR_OWORD64
+#define	EFX_AND_OWORD		EFX_AND_OWORD64
+#define	EFX_OR_QWORD		EFX_OR_QWORD64
+#define	EFX_AND_QWORD		EFX_OR_QWORD64
+#else
+#define	EFX_OWORD_FIELD		EFX_OWORD_FIELD32
+#define	EFX_QWORD_FIELD		EFX_QWORD_FIELD32
+#define	EFX_OWORD_IS_EQUAL	EFX_OWORD_IS_EQUAL32
+#define	EFX_QWORD_IS_EQUAL	EFX_QWORD_IS_EQUAL32
+#define	EFX_OWORD_IS_ZERO	EFX_OWORD_IS_ZERO32
+#define	EFX_QWORD_IS_ZERO	EFX_QWORD_IS_ZERO32
+#define	EFX_OWORD_IS_SET	EFX_OWORD_IS_SET32
+#define	EFX_QWORD_IS_SET	EFX_QWORD_IS_SET32
+#define	EFX_POPULATE_OWORD	EFX_POPULATE_OWORD32
+#define	EFX_POPULATE_QWORD	EFX_POPULATE_QWORD32
+#define	EFX_SET_OWORD		EFX_SET_OWORD32
+#define	EFX_SET_QWORD		EFX_SET_QWORD32
+#define	EFX_SET_OWORD_FIELD	EFX_SET_OWORD_FIELD32
+#define	EFX_SET_QWORD_FIELD	EFX_SET_QWORD_FIELD32
+#define	EFX_SET_OWORD_BIT	EFX_SET_OWORD_BIT32
+#define	EFX_CLEAR_OWORD_BIT	EFX_CLEAR_OWORD_BIT32
+#define	EFX_SET_QWORD_BIT	EFX_SET_QWORD_BIT32
+#define	EFX_CLEAR_QWORD_BIT	EFX_CLEAR_QWORD_BIT32
+#define	EFX_OR_OWORD		EFX_OR_OWORD32
+#define	EFX_AND_OWORD		EFX_AND_OWORD32
+#define	EFX_OR_QWORD		EFX_OR_QWORD32
+#define	EFX_AND_QWORD		EFX_OR_QWORD32
+#endif
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_EFX_TYPES_H */
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_vpd.c	2013-08-22 18:57:29.490546931 -0400
@@ -0,0 +1,999 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_VPD
+
+#define	TAG_TYPE_LBN 7
+#define	TAG_TYPE_WIDTH 1
+#define	TAG_TYPE_LARGE_ITEM_DECODE 1
+#define	TAG_TYPE_SMALL_ITEM_DECODE 0
+
+#define	TAG_SMALL_ITEM_NAME_LBN 3
+#define	TAG_SMALL_ITEM_NAME_WIDTH 4
+#define	TAG_SMALL_ITEM_SIZE_LBN 0
+#define	TAG_SMALL_ITEM_SIZE_WIDTH 3
+
+#define	TAG_LARGE_ITEM_NAME_LBN 0
+#define	TAG_LARGE_ITEM_NAME_WIDTH 7
+
+#define	TAG_NAME_END_DECODE 0x0f
+#define	TAG_NAME_ID_STRING_DECODE 0x02
+#define	TAG_NAME_VPD_R_DECODE 0x10
+#define	TAG_NAME_VPD_W_DECODE 0x11
+
+#if EFSYS_OPT_FALCON
+
+static efx_vpd_ops_t	__cs	__efx_vpd_falcon_ops = {
+	NULL,			/* evpdo_init */
+	falcon_vpd_size,	/* evpdo_size */
+	falcon_vpd_read,	/* evpdo_read */
+	falcon_vpd_verify,	/* evpdo_verify */
+	NULL,			/* evpdo_reinit */
+	falcon_vpd_get,		/* evpdo_get */
+	falcon_vpd_set,		/* evpdo_set */
+	falcon_vpd_next,	/* evpdo_next */
+	falcon_vpd_write,	/* evpdo_write */
+	NULL,			/* evpdo_fini */
+};
+
+#endif	/* EFSYS_OPT_FALCON */
+
+#if EFSYS_OPT_SIENA
+
+static efx_vpd_ops_t	__cs	__efx_vpd_siena_ops = {
+	siena_vpd_init,		/* evpdo_init */
+	siena_vpd_size,		/* evpdo_size */
+	siena_vpd_read,		/* evpdo_read */
+	siena_vpd_verify,	/* evpdo_verify */
+	siena_vpd_reinit,	/* evpdo_reinit */
+	siena_vpd_get,		/* evpdo_get */
+	siena_vpd_set,		/* evpdo_set */
+	siena_vpd_next,		/* evpdo_next */
+	siena_vpd_write,	/* evpdo_write */
+	siena_vpd_fini,		/* evpdo_fini */
+};
+
+#endif	/* EFSYS_OPT_SIENA */
+
+	__checkReturn		int
+efx_vpd_init(
+	__in			efx_nic_t *enp)
+{
+	efx_vpd_ops_t *evpdop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_VPD));
+
+	switch (enp->en_family) {
+#if EFSYS_OPT_FALCON
+	case EFX_FAMILY_FALCON:
+		evpdop = (efx_vpd_ops_t *)&__efx_vpd_falcon_ops;
+		break;
+#endif	/* EFSYS_OPT_FALCON */
+
+#if EFSYS_OPT_SIENA
+	case EFX_FAMILY_SIENA:
+		evpdop = (efx_vpd_ops_t *)&__efx_vpd_siena_ops;
+		break;
+#endif	/* EFSYS_OPT_SIENA */
+
+	default:
+		EFSYS_ASSERT(0);
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (evpdop->evpdo_init != NULL) {
+		if ((rc = evpdop->evpdo_init(enp)) != 0)
+			goto fail2;
+	}
+
+	enp->en_evpdop = evpdop;
+	enp->en_mod_flags |= EFX_MOD_VPD;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep)
+{
+	efx_vpd_ops_t *evpdop = enp->en_evpdop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
+
+	if ((rc = evpdop->evpdo_size(enp, sizep)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_read(
+	__in			efx_nic_t *enp,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_vpd_ops_t *evpdop = enp->en_evpdop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
+
+	if ((rc = evpdop->evpdo_read(enp, data, size)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_verify(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_vpd_ops_t *evpdop = enp->en_evpdop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
+
+	if ((rc = evpdop->evpdo_verify(enp, data, size)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_reinit(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_vpd_ops_t *evpdop = enp->en_evpdop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
+
+	if (evpdop->evpdo_reinit == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = evpdop->evpdo_reinit(enp, data, size)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_get(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__inout			efx_vpd_value_t *evvp)
+{
+	efx_vpd_ops_t *evpdop = enp->en_evpdop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
+
+	if ((rc = evpdop->evpdo_get(enp, data, size, evvp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_set(
+	__in			efx_nic_t *enp,
+	__inout_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_value_t *evvp)
+{
+	efx_vpd_ops_t *evpdop = enp->en_evpdop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
+
+	if ((rc = evpdop->evpdo_set(enp, data, size, evvp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_next(
+	__in			efx_nic_t *enp,
+	__inout_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out			efx_vpd_value_t *evvp,
+	__inout			unsigned int *contp)
+{
+	efx_vpd_ops_t *evpdop = enp->en_evpdop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
+
+	if ((rc = evpdop->evpdo_next(enp, data, size, evvp, contp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_write(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_vpd_ops_t *evpdop = enp->en_evpdop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
+
+	if ((rc = evpdop->evpdo_write(enp, data, size)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+efx_vpd_next_tag(
+	__in			caddr_t data,
+	__in			size_t size,
+	__inout			unsigned int *offsetp,
+	__out			efx_vpd_tag_t *tagp,
+	__out			uint16_t *lengthp)
+{
+	efx_byte_t byte;
+	efx_word_t word;
+	uint8_t name;
+	uint16_t length;
+	size_t headlen;
+	int rc;
+
+	if (*offsetp >= size) {
+		rc = EFAULT;
+		goto fail1;
+	}
+
+	EFX_POPULATE_BYTE_1(byte, EFX_BYTE_0, data[*offsetp]);
+
+	switch (EFX_BYTE_FIELD(byte, TAG_TYPE)) {
+	case TAG_TYPE_SMALL_ITEM_DECODE:
+		headlen = 1;
+
+		name = EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_NAME);
+		length = (uint16_t)EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_SIZE);
+
+		break;
+
+	case TAG_TYPE_LARGE_ITEM_DECODE:
+		headlen = 3;
+
+		if (*offsetp + headlen > size) {
+			rc = EFAULT;
+			goto fail2;
+		}
+
+		name = EFX_BYTE_FIELD(byte, TAG_LARGE_ITEM_NAME);
+		EFX_POPULATE_WORD_2(word,
+				    EFX_BYTE_0, data[*offsetp + 1],
+				    EFX_BYTE_1, data[*offsetp + 2]);
+		length = EFX_WORD_FIELD(word, EFX_WORD_0);
+
+		break;
+
+	default:
+		rc = EFAULT;
+		goto fail2;
+	}
+
+	if (*offsetp + headlen + length > size) {
+		rc = EFAULT;
+		goto fail3;
+	}
+
+	EFX_STATIC_ASSERT(TAG_NAME_END_DECODE == EFX_VPD_END);
+	EFX_STATIC_ASSERT(TAG_NAME_ID_STRING_DECODE == EFX_VPD_ID);
+	EFX_STATIC_ASSERT(TAG_NAME_VPD_R_DECODE == EFX_VPD_RO);
+	EFX_STATIC_ASSERT(TAG_NAME_VPD_W_DECODE == EFX_VPD_RW);
+	if (name != EFX_VPD_END && name != EFX_VPD_ID &&
+	    name != EFX_VPD_RO) {
+		rc = EFAULT;
+		goto fail4;
+	}
+
+	*tagp = name;
+	*lengthp = length;
+	*offsetp += headlen;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+efx_vpd_next_keyword(
+	__in_bcount(size)	caddr_t tag,
+	__in			size_t size,
+	__in			unsigned int pos,
+	__out			efx_vpd_keyword_t *keywordp,
+	__out			uint8_t *lengthp)
+{
+	efx_vpd_keyword_t keyword;
+	uint8_t length;
+	int rc;
+
+	if (pos + 3U > size) {
+		rc = EFAULT;
+		goto fail1;
+	}
+
+	keyword = EFX_VPD_KEYWORD(tag[pos], tag[pos + 1]);
+	length = tag[pos + 2];
+
+	if (length == 0 || pos + 3U + length > size) {
+		rc = EFAULT;
+		goto fail2;
+	}
+
+	*keywordp = keyword;
+	*lengthp = length;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_hunk_length(
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out			size_t *lengthp)
+{
+	efx_vpd_tag_t tag;
+	unsigned int offset;
+	uint16_t taglen;
+	int rc;
+
+	offset = 0;
+	_NOTE(CONSTANTCONDITION)
+	while (1) {
+		if ((rc = efx_vpd_next_tag(data, size, &offset,
+		    &tag, &taglen)) != 0)
+			goto fail1;
+		offset += taglen;
+		if (tag == EFX_VPD_END)
+			break;
+	}
+
+	*lengthp = offset;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_hunk_verify(
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out_opt		boolean_t *cksummedp)
+{
+	efx_vpd_tag_t tag;
+	efx_vpd_keyword_t keyword;
+	unsigned int offset;
+	unsigned int pos;
+	unsigned int i;
+	uint16_t taglen;
+	uint8_t keylen;
+	uint8_t cksum;
+	boolean_t cksummed = B_FALSE;
+	int rc;
+
+	/*
+	 * Parse every tag,keyword in the existing VPD. If the csum is present,
+	 * the assert it is correct, and is the final keyword in the RO block.
+	 */
+	offset = 0;
+	_NOTE(CONSTANTCONDITION)
+	while (1) {
+		if ((rc = efx_vpd_next_tag(data, size, &offset,
+		    &tag, &taglen)) != 0)
+			goto fail1;
+		if (tag == EFX_VPD_END)
+			break;
+		else if (tag == EFX_VPD_ID)
+			goto done;
+
+		for (pos = 0; pos != taglen; pos += 3 + keylen) {
+			/* RV keyword must be the last in the block */
+			if (cksummed)
+				goto fail2;
+
+			if ((rc = efx_vpd_next_keyword(data + offset,
+			    taglen, pos, &keyword, &keylen)) != 0)
+				goto fail3;
+
+			if (keyword == EFX_VPD_KEYWORD('R', 'V')) {
+				cksum = 0;
+				for (i = 0; i < offset + pos + 4; i++)
+					cksum += data[i];
+
+				if (cksum != 0) {
+					rc = EFAULT;
+					goto fail4;
+				}
+
+				cksummed = B_TRUE;
+			}
+		}
+
+	done:
+		offset += taglen;
+	}
+
+	if (!cksummed) {
+		rc = EFAULT;
+		goto fail5;
+	}
+
+	if (cksummedp != NULL)
+		*cksummedp = cksummed;
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	uint8_t	__cs	__efx_vpd_blank_pid[] = {
+	/* Large resource type ID length 1 */
+	0x82, 0x01, 0x00,
+	/* Product name ' ' */
+	0x32,
+};
+
+static uint8_t __cs	__efx_vpd_blank_r[] = {
+	/* Large resource type VPD-R length 4 */
+	0x90, 0x04, 0x00,
+	/* RV keyword length 1 */
+	'R', 'V', 0x01,
+	/* RV payload checksum */
+	0x00,
+};
+
+	__checkReturn		int
+efx_vpd_hunk_reinit(
+	__in			caddr_t data,
+	__in			size_t size,
+	__in			boolean_t wantpid)
+{
+	unsigned int offset = 0;
+	unsigned int pos;
+	efx_byte_t byte;
+	uint8_t cksum;
+	int rc;
+
+	if (size < 0x100) {
+		rc = ENOSPC;
+		goto fail1;
+	}
+
+	if (wantpid) {
+		memcpy(data + offset, __efx_vpd_blank_pid,
+		    sizeof (__efx_vpd_blank_pid));
+		offset += sizeof (__efx_vpd_blank_pid);
+	}
+
+	memcpy(data + offset, __efx_vpd_blank_r, sizeof (__efx_vpd_blank_r));
+	offset += sizeof (__efx_vpd_blank_r);
+
+	/* Update checksum */
+	cksum = 0;
+	for (pos = 0; pos < offset; pos++)
+		cksum += data[pos];
+	data[offset - 1] -= cksum;
+
+	/* Append trailing tag */
+	EFX_POPULATE_BYTE_3(byte,
+			    TAG_TYPE, TAG_TYPE_SMALL_ITEM_DECODE,
+			    TAG_SMALL_ITEM_NAME, TAG_NAME_END_DECODE,
+			    TAG_SMALL_ITEM_SIZE, 0);
+	data[offset] = EFX_BYTE_FIELD(byte, EFX_BYTE_0);
+	offset++;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+efx_vpd_hunk_next(
+	__in_bcount(size)		caddr_t data,
+	__in				size_t size,
+	__out				efx_vpd_tag_t *tagp,
+	__out				efx_vpd_keyword_t *keywordp,
+	__out_bcount_opt(*paylenp)	unsigned int *payloadp,
+	__out_opt			uint8_t *paylenp,
+	__inout				unsigned int *contp)
+{
+	efx_vpd_tag_t tag;
+	efx_vpd_keyword_t keyword = 0;
+	unsigned int offset;
+	unsigned int pos;
+	unsigned int index;
+	uint16_t taglen;
+	uint8_t keylen;
+	uint8_t paylen;
+	int rc;
+
+	offset = index = 0;
+	_NOTE(CONSTANTCONDITION)
+	while (1) {
+		if ((rc = efx_vpd_next_tag(data, size, &offset,
+		    &tag, &taglen)) != 0)
+			goto fail1;
+		if (tag == EFX_VPD_END)
+			break;
+
+		if (tag == EFX_VPD_ID) {
+			if (index == *contp) {
+				EFSYS_ASSERT3U(taglen, <, 0x100);
+				paylen = (uint8_t)MIN(taglen, 0xff);
+
+				goto done;
+			}
+		} else {
+			for (pos = 0; pos != taglen; pos += 3 + keylen) {
+				if ((rc = efx_vpd_next_keyword(data + offset,
+				    taglen, pos, &keyword, &keylen)) != 0)
+					goto fail2;
+
+				if (index == *contp) {
+					offset += pos + 3;
+					paylen = keylen;
+
+					goto done;
+				}
+			}
+		}
+
+		offset += taglen;
+	}
+
+	*contp = 0;
+	return (0);
+
+done:
+	*tagp = tag;
+	*keywordp = keyword;
+	if (payloadp != NULL)
+		*payloadp = offset;
+	if (paylenp != NULL)
+		*paylenp = paylen;
+
+	++(*contp);
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_hunk_get(
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_tag_t tag,
+	__in			efx_vpd_keyword_t keyword,
+	__out			unsigned int *payloadp,
+	__out			uint8_t *paylenp)
+{
+	efx_vpd_tag_t itag;
+	efx_vpd_keyword_t ikeyword;
+	unsigned int offset;
+	unsigned int pos;
+	uint16_t taglen;
+	uint8_t keylen;
+	int rc;
+
+	offset = 0;
+	_NOTE(CONSTANTCONDITION)
+	while (1) {
+		if ((rc = efx_vpd_next_tag(data, size, &offset,
+		    &itag, &taglen)) != 0)
+			goto fail1;
+		if (itag == EFX_VPD_END)
+			break;
+
+		if (itag == tag) {
+			if (itag == EFX_VPD_ID) {
+				EFSYS_ASSERT3U(taglen, <, 0x100);
+
+				*paylenp = (uint8_t)MIN(taglen, 0xff);
+				*payloadp = offset;
+				return (0);
+			}
+
+			for (pos = 0; pos != taglen; pos += 3 + keylen) {
+				if ((rc = efx_vpd_next_keyword(data + offset,
+				    taglen, pos, &ikeyword, &keylen)) != 0)
+					goto fail2;
+
+				if (ikeyword == keyword) {
+					*paylenp = keylen;
+					*payloadp = offset + pos + 3;
+					return (0);
+				}
+			}
+		}
+
+		offset += taglen;
+	}
+
+	/* Not an error */
+	return (ENOENT);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+efx_vpd_hunk_set(
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_value_t *evvp)
+{
+	efx_word_t word;
+	efx_vpd_tag_t tag;
+	efx_vpd_keyword_t keyword;
+	unsigned int offset;
+	unsigned int pos;
+	unsigned int taghead;
+	unsigned int source;
+	unsigned int dest;
+	unsigned int i;
+	uint16_t taglen;
+	uint8_t keylen;
+	uint8_t cksum;
+	size_t used;
+	int rc;
+
+	switch (evvp->evv_tag) {
+	case EFX_VPD_ID:
+		if (evvp->evv_keyword != 0) {
+			rc = EINVAL;
+			goto fail1;
+		}
+
+		/* Can't delete the ID keyword */
+		if (evvp->evv_length == 0) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+
+	case EFX_VPD_RO:
+		if (evvp->evv_keyword == EFX_VPD_KEYWORD('R', 'V')) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+
+	default:
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	/* Determine total size of all current tags */
+	if ((rc = efx_vpd_hunk_length(data, size, &used)) != 0)
+		goto fail2;
+
+	offset = 0;
+	_NOTE(CONSTANTCONDITION)
+	while (1) {
+		taghead = offset;
+		if ((rc = efx_vpd_next_tag(data, size, &offset,
+		    &tag, &taglen)) != 0)
+			goto fail3;
+		if (tag == EFX_VPD_END)
+			break;
+		else if (tag != evvp->evv_tag) {
+			offset += taglen;
+			continue;
+		}
+
+		/* We only support modifying large resource tags */
+		if (offset - taghead != 3) {
+			rc = EINVAL;
+			goto fail4;
+		}
+
+		/*
+		 * Work out the offset of the byte immediately after the
+		 * old (=source) and new (=dest) new keyword/tag
+		 */
+		pos = 0;
+		if (tag == EFX_VPD_ID) {
+			source = offset + taglen;
+			dest = offset + evvp->evv_length;
+			goto check_space;
+		}
+
+		EFSYS_ASSERT3U(tag, ==, EFX_VPD_RO);
+		source = dest = 0;
+		for (pos = 0; pos != taglen; pos += 3 + keylen) {
+			if ((rc = efx_vpd_next_keyword(data + offset,
+			    taglen, pos, &keyword, &keylen)) != 0)
+				goto fail5;
+
+			if (keyword == evvp->evv_keyword &&
+			    evvp->evv_length == 0) {
+				/* Deleting this keyword */
+				source = offset + pos + 3 + keylen;
+				dest = offset + pos;
+				break;
+
+			} else if (keyword == evvp->evv_keyword) {
+				/* Adjusting this keyword */
+				source = offset + pos + 3 + keylen;
+				dest = offset + pos + 3 + evvp->evv_length;
+				break;
+
+			} else if (keyword == EFX_VPD_KEYWORD('R', 'V')) {
+				/* The RV keyword must be at the end */
+				EFSYS_ASSERT3U(pos + 3 + keylen, ==, taglen);
+
+				/*
+				 * The keyword doesn't already exist. If the
+				 * user deleting a non-existant keyword then
+				 * this is a no-op.
+				 */
+				if (evvp->evv_length == 0)
+					return (0);
+
+				/* Insert this keyword before the RV keyword */
+				source = offset + pos;
+				dest = offset + pos + 3 + evvp->evv_length;
+				break;
+			}
+		}
+
+	check_space:
+		if (used + dest > size + source) {
+			rc = ENOSPC;
+			goto fail6;
+		}
+
+		/* Move trailing data */
+		(void) memmove(data + dest, data + source, used - source);
+
+		/* Copy contents */
+		memcpy(data + dest - evvp->evv_length, evvp->evv_value,
+		    evvp->evv_length);
+
+		/* Insert new keyword header if required */
+		if (tag != EFX_VPD_ID && evvp->evv_length > 0) {
+			EFX_POPULATE_WORD_1(word, EFX_WORD_0,
+					    evvp->evv_keyword);
+			data[offset + pos + 0] =
+			    EFX_WORD_FIELD(word, EFX_BYTE_0);
+			data[offset + pos + 1] =
+			    EFX_WORD_FIELD(word, EFX_BYTE_1);
+			data[offset + pos + 2] = evvp->evv_length;
+		}
+
+		/* Modify tag length (large resource type) */
+		taglen += (dest - source);
+		EFX_POPULATE_WORD_1(word, EFX_WORD_0, taglen);
+		data[offset - 2] = EFX_WORD_FIELD(word, EFX_BYTE_0);
+		data[offset - 1] = EFX_WORD_FIELD(word, EFX_BYTE_1);
+
+		goto checksum;
+	}
+
+	/* Unable to find the matching tag */
+	rc = ENOENT;
+	goto fail7;
+
+checksum:
+	/* Find the RV tag, and update the checksum */
+	offset = 0;
+	_NOTE(CONSTANTCONDITION)
+	while (1) {
+		if ((rc = efx_vpd_next_tag(data, size, &offset,
+		    &tag, &taglen)) != 0)
+			goto fail8;
+		if (tag == EFX_VPD_END)
+			break;
+		if (tag == EFX_VPD_RO) {
+			for (pos = 0; pos != taglen; pos += 3 + keylen) {
+				if ((rc = efx_vpd_next_keyword(data + offset,
+				    taglen, pos, &keyword, &keylen)) != 0)
+					goto fail9;
+
+				if (keyword == EFX_VPD_KEYWORD('R', 'V')) {
+					cksum = 0;
+					for (i = 0; i < offset + pos + 3; i++)
+						cksum += data[i];
+					data[i] = -cksum;
+					break;
+				}
+			}
+		}
+
+		offset += taglen;
+	}
+
+	/* Zero out the unused portion */
+	(void) memset(data + offset + taglen, 0xff, size - offset - taglen);
+
+	return (0);
+
+fail9:
+	EFSYS_PROBE(fail9);
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+				void
+efx_vpd_fini(
+	__in			efx_nic_t *enp)
+{
+	efx_vpd_ops_t *evpdop = enp->en_evpdop;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);
+
+	if (evpdop->evpdo_fini != NULL)
+		evpdop->evpdo_fini(enp);
+
+	enp->en_evpdop = NULL;
+	enp->en_mod_flags &= ~EFX_MOD_VPD;
+}
+
+#endif	/* EFSYS_OPT_VPD */
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/efx_wol.c	2013-08-22 18:57:29.583964375 -0400
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_WOL
+
+	__checkReturn	int
+efx_wol_init(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_WOL));
+
+	if (~(encp->enc_features) & EFX_FEATURE_WOL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	/* Current implementation is Siena specific */
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+
+	enp->en_mod_flags |= EFX_MOD_WOL;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_wol_filter_clear(
+	__in		efx_nic_t *enp)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_WOL_FILTER_RESET_IN_LEN];
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
+
+	req.emr_cmd = MC_CMD_WOL_FILTER_RESET;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_WOL_FILTER_RESET_IN_LEN;
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, WOL_FILTER_RESET_IN_MASK,
+			    MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS |
+			    MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_wol_filter_add(
+	__in		efx_nic_t *enp,
+	__in		efx_wol_type_t type,
+	__in		efx_wol_param_t *paramp,
+	__out		uint32_t *filter_idp)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MAX(MC_CMD_WOL_FILTER_SET_IN_LEN,
+			    MC_CMD_WOL_FILTER_SET_OUT_LEN)];
+	efx_byte_t link_mask;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
+
+	req.emr_cmd = MC_CMD_WOL_FILTER_SET;
+	(void) memset(payload, '\0', sizeof (payload));
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_WOL_FILTER_SET_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_WOL_FILTER_SET_OUT_LEN;
+
+	switch (type) {
+	case EFX_WOL_TYPE_MAGIC:
+		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_FILTER_MODE,
+				    MC_CMD_FILTER_MODE_SIMPLE);
+		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_WOL_TYPE,
+				    MC_CMD_WOL_TYPE_MAGIC);
+		EFX_MAC_ADDR_COPY(
+			MCDI_IN2(req, uint8_t, WOL_FILTER_SET_IN_MAGIC_MAC),
+			paramp->ewp_magic.mac_addr);
+		break;
+
+	case EFX_WOL_TYPE_BITMAP: {
+		uint32_t swapped = 0;
+		efx_dword_t *dwordp;
+		unsigned int pos, bit;
+
+		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_FILTER_MODE,
+				    MC_CMD_FILTER_MODE_SIMPLE);
+		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_WOL_TYPE,
+				    MC_CMD_WOL_TYPE_BITMAP);
+
+		/*
+		 * MC bitmask is supposed to be bit swapped
+		 * amongst 32 bit words(!)
+		 */
+
+		dwordp = MCDI_IN2(req, efx_dword_t,
+				    WOL_FILTER_SET_IN_BITMAP_MASK);
+
+		EFSYS_ASSERT3U(EFX_WOL_BITMAP_MASK_SIZE % 4, ==, 0);
+
+		for (pos = 0; pos < EFX_WOL_BITMAP_MASK_SIZE; ++pos) {
+			uint8_t native = paramp->ewp_bitmap.mask[pos];
+
+			for (bit = 0; bit < 8; ++bit) {
+				swapped <<= 1;
+				swapped |= (native & 0x1);
+				native >>= 1;
+			}
+
+			if ((pos & 3) == 3) {
+				EFX_POPULATE_DWORD_1(dwordp[pos >> 2],
+				    EFX_DWORD_0, swapped);
+				swapped = 0;
+			}
+		}
+
+		memcpy(MCDI_IN2(req, uint8_t, WOL_FILTER_SET_IN_BITMAP_BITMAP),
+		    paramp->ewp_bitmap.value,
+		    sizeof (paramp->ewp_bitmap.value));
+
+		EFSYS_ASSERT3U(paramp->ewp_bitmap.value_len, <=,
+				    sizeof (paramp->ewp_bitmap.value));
+		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_BITMAP_LEN,
+				    paramp->ewp_bitmap.value_len);
+		}
+		break;
+
+	case EFX_WOL_TYPE_LINK:
+		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_FILTER_MODE,
+				    MC_CMD_FILTER_MODE_SIMPLE);
+		MCDI_IN_SET_DWORD(req, WOL_FILTER_SET_IN_WOL_TYPE,
+				    MC_CMD_WOL_TYPE_LINK);
+
+		EFX_ZERO_BYTE(link_mask);
+		EFX_SET_BYTE_FIELD(link_mask, MC_CMD_WOL_FILTER_SET_IN_LINK_UP,
+		    1);
+		MCDI_IN_SET_BYTE(req, WOL_FILTER_SET_IN_LINK_MASK,
+		    link_mask.eb_u8[0]);
+		break;
+
+	default:
+		EFSYS_ASSERT3U(type, !=, type);
+	}
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_WOL_FILTER_SET_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	*filter_idp = MCDI_OUT_DWORD(req, WOL_FILTER_SET_OUT_FILTER_ID);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+efx_wol_filter_remove(
+	__in		efx_nic_t *enp,
+	__in		uint32_t filter_id)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_WOL_FILTER_REMOVE_IN_LEN];
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
+
+	req.emr_cmd = MC_CMD_WOL_FILTER_REMOVE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_WOL_FILTER_REMOVE_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_WOL_FILTER_REMOVE_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, WOL_FILTER_REMOVE_IN_FILTER_ID, filter_id);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+	__checkReturn	int
+efx_lightsout_offload_add(
+	__in		efx_nic_t *enp,
+	__in		efx_lightsout_offload_type_t type,
+	__in		efx_lightsout_offload_param_t *paramp,
+	__out		uint32_t *filter_idp)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MAX(MAX(MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN,
+				MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN),
+			    MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN)];
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
+
+	req.emr_cmd = MC_CMD_ADD_LIGHTSOUT_OFFLOAD;
+	req.emr_in_buf = payload;
+	req.emr_in_length = sizeof (type);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN;
+
+	switch (type) {
+	case EFX_LIGHTSOUT_OFFLOAD_TYPE_ARP:
+		req.emr_in_length = MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN;
+		MCDI_IN_SET_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
+				    MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP);
+		EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t,
+					    ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC),
+				    paramp->elop_arp.mac_addr);
+		MCDI_IN_SET_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_IN_ARP_IP,
+				    paramp->elop_arp.ip);
+		break;
+	case EFX_LIGHTSOUT_OFFLOAD_TYPE_NS:
+		req.emr_in_length = MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN;
+		MCDI_IN_SET_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
+				    MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS);
+		EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t,
+					    ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC),
+				    paramp->elop_ns.mac_addr);
+		memcpy(MCDI_IN2(req, uint8_t,
+		    ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6),
+		    paramp->elop_ns.solicited_node,
+		    sizeof (paramp->elop_ns.solicited_node));
+		memcpy(MCDI_IN2(req, uint8_t, ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6),
+		    paramp->elop_ns.ip, sizeof (paramp->elop_ns.ip));
+		break;
+	default:
+		EFSYS_ASSERT3U(type, !=, type);
+	}
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	*filter_idp = MCDI_OUT_DWORD(req, ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+	__checkReturn	int
+efx_lightsout_offload_remove(
+	__in		efx_nic_t *enp,
+	__in		efx_lightsout_offload_type_t type,
+	__in		uint32_t filter_id)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN];
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
+
+	req.emr_cmd = MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD;
+	req.emr_in_buf = payload;
+	req.emr_in_length = sizeof (payload);
+	EFX_STATIC_ASSERT(MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	switch (type) {
+	case EFX_LIGHTSOUT_OFFLOAD_TYPE_ARP:
+		MCDI_IN_SET_DWORD(req, REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
+				    MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP);
+		break;
+	case EFX_LIGHTSOUT_OFFLOAD_TYPE_NS:
+		MCDI_IN_SET_DWORD(req, REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL,
+				    MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS);
+		break;
+	default:
+		EFSYS_ASSERT3U(type, !=, type);
+	}
+
+	MCDI_IN_SET_DWORD(req, REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID,
+			    filter_id);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+			void
+efx_wol_fini(
+	__in		efx_nic_t *enp)
+{
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_WOL);
+
+	enp->en_mod_flags &= ~EFX_MOD_WOL;
+}
+
+#endif	/* EFSYS_OPT_WOL */
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_gmac.c	2013-08-22 18:57:29.671076915 -0400
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "falcon_gmac.h"
+#include "falcon_stats.h"
+
+#if EFSYS_OPT_MAC_FALCON_GMAC
+
+	__checkReturn	int
+falcon_gmac_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_GMAC);
+
+	EFSYS_PROBE(reset);
+
+	/* Ensure that the GMAC registers are accessible */
+	EFX_BAR_READO(enp, FR_AB_NIC_STAT_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_BB_EE_STRAP_EN, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_BB_EE_STRAP, 0x3);
+	EFX_BAR_WRITEO(enp, FR_AB_NIC_STAT_REG, &oword);
+
+	if ((rc = falcon_mac_wrapper_disable(enp)) != 0)
+	    goto fail1;
+
+	enp->en_reset_flags |= EFX_RESET_MAC;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static			void
+falcon_gmac_core_reconfigure(
+	__in	efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_oword_t oword;
+	boolean_t full_duplex;
+	boolean_t byte_mode;
+
+	full_duplex = (epp->ep_link_mode == EFX_LINK_100FDX ||
+	    epp->ep_link_mode == EFX_LINK_1000FDX);
+	byte_mode = (epp->ep_link_mode == EFX_LINK_1000HDX ||
+	    epp->ep_link_mode == EFX_LINK_1000FDX);
+#if EFSYS_OPT_LOOPBACK
+	byte_mode |= (epp->ep_loopback_type == EFX_LOOPBACK_GMAC);
+
+	EFX_POPULATE_OWORD_5(oword,
+	    FRF_AB_GM_LOOP,
+	    (epp->ep_loopback_type == EFX_LOOPBACK_GMAC) ? 1 : 0,
+	    FRF_AB_GM_TX_EN, 1,
+	    FRF_AB_GM_TX_FC_EN, (epp->ep_fcntl & EFX_FCNTL_GENERATE) ? 1 : 0,
+	    FRF_AB_GM_RX_EN, 1,
+	    FRF_AB_GM_RX_FC_EN, (epp->ep_fcntl & EFX_FCNTL_RESPOND) ? 1 : 0);
+
+#else	/* EFSYS_OPT_LOOPBACK */
+
+	EFX_POPULATE_OWORD_4(oword,
+	    FRF_AB_GM_TX_EN, 1,
+	    FRF_AB_GM_TX_FC_EN, (epp->ep_fcntl & EFX_FCNTL_GENERATE) ? 1 : 0,
+	    FRF_AB_GM_RX_EN, 1,
+	    FRF_AB_GM_RX_FC_EN, (epp->ep_fcntl & EFX_FCNTL_RESPOND) ? 1 : 0);
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	EFX_BAR_WRITEO(enp, FR_AB_GM_CFG1_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_OWORD_4(oword,
+	    FRF_AB_GM_IF_MODE, (byte_mode) ?
+	    FRF_AB_GM_IF_MODE_BYTE_MODE : FRF_AB_GM_IF_MODE_NIBBLE_MODE,
+	    FRF_AB_GM_PAD_CRC_EN, 1,
+	    FRF_AB_GM_FD, full_duplex ? 1 : 0,
+	    FRF_AB_GM_PAMBL_LEN, 7);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GM_CFG2_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AB_GM_MAX_FLEN, epp->ep_mac_pdu);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GM_MAX_FLEN_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_OWORD_5(oword,
+	    FRF_AB_GMF_FTFENREQ, 1,
+	    FRF_AB_GMF_STFENREQ, 1,
+	    FRF_AB_GMF_FRFENREQ, 1,
+	    FRF_AB_GMF_SRFENREQ, 1,
+	    FRF_AB_GMF_WTMENREQ, 1);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GMF_CFG0_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_OWORD_2(oword,
+	    FRF_AB_GMF_CFGFRTH, 0x12,
+	    FRF_AB_GMF_CFGXOFFRTX, 0xffff);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GMF_CFG1_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_OWORD_2(oword,
+	    FRF_AB_GMF_CFGHWM, 0x3f,
+	    FRF_AB_GMF_CFGLWM, 0x0a);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GMF_CFG2_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_OWORD_2(oword,
+	    FRF_AB_GMF_CFGHWMFT, 0x1c,
+	    FRF_AB_GMF_CFGFTTH, 0x08);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GMF_CFG3_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AB_GMF_HSTFLTRFRM, 0x1000);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GMF_CFG4_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_BAR_READO(enp, FR_AB_GMF_CFG5_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GMF_CFGBYTMODE, byte_mode ? 1 : 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GMF_CFGHDPLX, full_duplex ? 0 : 1);
+	EFX_SET_OWORD_FIELD(oword,
+	    FRF_AB_GMF_HSTDRPLT64, full_duplex ? 0 : 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GMF_HSTFLTRFRMDC, 0x3efff);
+	EFX_BAR_WRITEO(enp, FR_AB_GMF_CFG5_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_OWORD_4(oword,
+	    FRF_AB_GM_ADR_B0, epp->ep_mac_addr[5],
+	    FRF_AB_GM_ADR_B1, epp->ep_mac_addr[4],
+	    FRF_AB_GM_ADR_B2, epp->ep_mac_addr[3],
+	    FRF_AB_GM_ADR_B3, epp->ep_mac_addr[2]);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GM_ADR1_REG, &oword);
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_OWORD_2(oword,
+	    FRF_AB_GM_ADR_B4, epp->ep_mac_addr[1],
+	    FRF_AB_GM_ADR_B5, epp->ep_mac_addr[0]);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GM_ADR2_REG, &oword);
+	EFSYS_SPIN(10);
+}
+
+	__checkReturn	int
+falcon_gmac_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+
+	_NOTE(ARGUNUSED(upp))
+
+	EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_GMAC);
+
+	return (ENOTSUP);
+}
+
+	__checkReturn	int
+falcon_gmac_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+
+	EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_GMAC);
+	EFSYS_ASSERT3U(epp->ep_link_mode, !=, EFX_LINK_10000FDX);
+
+	EFSYS_PROBE(reconfigure);
+
+	falcon_gmac_core_reconfigure(enp);
+	falcon_mac_wrapper_enable(enp);
+
+	return (0);
+}
+
+		void
+falcon_gmac_downlink_reset(
+	__in	efx_nic_t *enp,
+	__in	boolean_t hold)
+{
+	_NOTE(ARGUNUSED(enp, hold))
+}
+
+#if EFSYS_OPT_MAC_STATS
+static		uint32_t
+falcon_gmac_stat_read(
+	__in	efsys_mem_t *esmp,
+	__in	unsigned int offset,
+	__in	unsigned int width)
+{
+	uint32_t val;
+
+	switch (width) {
+	case 2: {
+		efx_dword_t dword;
+
+		EFSYS_MEM_READD(esmp, offset, &dword);
+
+		val = (uint16_t)EFX_DWORD_FIELD(dword, EFX_WORD_0);
+		break;
+	}
+	case 4: {
+		efx_dword_t dword;
+
+		EFSYS_MEM_READD(esmp, offset, &dword);
+
+		val = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+		break;
+	}
+	case 6: {
+		efx_qword_t qword;
+
+		EFSYS_MEM_READQ(esmp, offset, &qword);
+
+		val = EFX_QWORD_FIELD(qword, EFX_DWORD_0);
+		break;
+	}
+	default:
+		EFSYS_ASSERT(B_FALSE);
+
+		val = 0;
+		break;
+	}
+
+	return (val);
+}
+
+#define	GMAC_STAT_READ(_esmp, _id)					\
+	falcon_gmac_stat_read((_esmp), G_STAT_OFFSET(_id),		\
+	    G_STAT_WIDTH(_id))
+
+#define	GMAC_STAT_INCR(_esmp, _stat, _id)				\
+	do {								\
+		delta = GMAC_STAT_READ(_esmp, _id);			\
+		EFSYS_STAT_INCR(&(_stat), delta);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (0)
+
+#define	GMAC_STAT_DECR(_esmp, _stat, _id)				\
+	do {								\
+		delta = GMAC_STAT_READ(_esmp, _id);			\
+		EFSYS_STAT_DECR(&(_stat), delta);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (0)
+
+	__checkReturn			int
+falcon_gmac_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *stat,
+	__out_opt			uint32_t *generationp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_oword_t oword;
+	uint32_t delta;
+
+	_NOTE(ARGUNUSED(generationp));
+	EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_GMAC);
+
+	/* Check the DMA flag */
+	if (GMAC_STAT_READ(esmp, DMA_DONE) != DMA_IS_DONE)
+		return (EAGAIN);
+	EFSYS_MEM_READ_BARRIER();
+
+	/* RX */
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_OCTETS], RX_GOOD_OCT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_OCTETS], RX_BAD_OCT);
+
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_GOOD_LT_64_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_64_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_65_TO_127_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_128_TO_255_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_256_TO_511_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_512_TO_1023_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_1024_TO_15XX_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_15XX_TO_JUMBO_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_GT_JUMBO_PKT);
+
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_UNICST_PKTS], RX_UCAST_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_MULTICST_PKTS], RX_MCAST_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_BRDCST_PKTS], RX_BCAST_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PAUSE_PKTS], RX_PAUSE_PKT);
+
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_LE_64_PKTS], RX_GOOD_LT_64_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_LE_64_PKTS], RX_BAD_LT_64_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_LE_64_PKTS], RX_64_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_65_TO_127_PKTS],
+	    RX_65_TO_127_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_128_TO_255_PKTS],
+	    RX_128_TO_255_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_256_TO_511_PKTS],
+	    RX_256_TO_511_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_512_TO_1023_PKTS],
+	    RX_512_TO_1023_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_1024_TO_15XX_PKTS],
+	    RX_1024_TO_15XX_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_GE_15XX_PKTS],
+	    RX_15XX_TO_JUMBO_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_GE_15XX_PKTS], RX_GT_JUMBO_PKT);
+
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_ERRORS], RX_BAD_PKT);
+	GMAC_STAT_DECR(esmp, stat[EFX_MAC_RX_ERRORS], RX_PAUSE_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_FCS_ERRORS],
+	    RX_FCS_ERR_64_TO_15XX_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_FCS_ERRORS],
+	    RX_FCS_ERR_15XX_TO_JUMBO_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_FCS_ERRORS],
+	    RX_FCS_ERR_GT_JUMBO_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_DROP_EVENTS], RX_MISS_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_FALSE_CARRIER_ERRORS],
+	    RX_FALSE_CRS);
+
+	EFX_BAR_READO(enp, FR_AZ_RX_NODESC_DROP_REG, &oword);
+	delta = (uint32_t)EFX_OWORD_FIELD(oword, FRF_AZ_RX_NODESC_DROP_CNT);
+	EFSYS_STAT_INCR(&(stat[EFX_MAC_RX_NODESC_DROP_CNT]), delta);
+
+	/* TX */
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_OCTETS], TX_GOOD_BAD_OCT);
+
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_LT_64_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_64_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_65_TO_127_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_128_TO_255_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_256_TO_511_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_512_TO_1023_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_1024_TO_15XX_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_15XX_TO_JUMBO_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_GT_JUMBO_PKT);
+
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_UNICST_PKTS], TX_UCAST_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_MULTICST_PKTS], TX_MCAST_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_BRDCST_PKTS], TX_BCAST_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PAUSE_PKTS], TX_PAUSE_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_LE_64_PKTS], TX_LT_64_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_LE_64_PKTS], TX_64_PKT);
+
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_65_TO_127_PKTS],
+	    TX_65_TO_127_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_128_TO_255_PKTS],
+	    TX_128_TO_255_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_256_TO_511_PKTS],
+	    TX_256_TO_511_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_512_TO_1023_PKTS],
+	    TX_512_TO_1023_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_1024_TO_15XX_PKTS],
+	    TX_1024_TO_15XX_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_GE_15XX_PKTS],
+	    TX_15XX_TO_JUMBO_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_GE_15XX_PKTS],
+	    TX_GT_JUMBO_PKT);
+
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_ERRORS], TX_BAD_PKT);
+	GMAC_STAT_DECR(esmp, stat[EFX_MAC_TX_ERRORS], TX_PAUSE_PKT);
+
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_SGL_COL_PKTS], TX_SGL_COL_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_MULT_COL_PKTS], TX_MULT_COL_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_EX_COL_PKTS], TX_EX_COL_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_LATE_COL_PKTS], TX_LATE_COL);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_DEF_PKTS], TX_DEF_PKT);
+	GMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_EX_DEF_PKTS], TX_EX_DEF_PKT);
+
+	return (0);
+}
+
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+#endif	/* EFSYS_OPT_MAC_FALCON_GMAC */
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_gmac.h	2013-08-22 18:57:29.759116195 -0400
@@ -0,0 +1,70 @@
+/*-
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_FALCON_GMAC_H
+#define	_SYS_FALCON_GMAC_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_MAC_FALCON_GMAC
+
+#if EFSYS_OPT_LOOPBACK
+
+#define	FALCON_GMAC_LOOPBACK_MASK						\
+	(1 << EFX_LOOPBACK_GMAC)
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+#define	GMAC_INTR_SUPPORTED	B_FALSE
+
+extern	__checkReturn	int
+falcon_gmac_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+falcon_gmac_reconfigure(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_MAC_STATS
+
+extern	__checkReturn			int
+falcon_gmac_stats_update(
+	__in				efx_nic_t *enp,
+ 	__in				efsys_mem_t *esmp,
+	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *essp,
+	__out_opt			uint32_t *generationp);
+#endif
+
+#endif	/* EFSYS_OPT_MAC_GMAC */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_FALCON_GMAC_H */
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_i2c.c	2013-08-22 18:57:29.844301338 -0400
@@ -0,0 +1,842 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_FALCON
+
+#define	I2C_READ_CMD(_devid)	(((_devid) << 1) | 1)
+#define	I2C_WRITE_CMD(_devid)	(((_devid) << 1) | 0)
+
+#define	I2C_PERIOD	100
+
+#define	I2C_RETRY_LIMIT	10
+
+static			void
+falcon_i2c_set_sda_scl(
+	__in		efx_nic_t *enp,
+	__in		falcon_i2c_t *fip,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	efx_oword_t oword;
+	efsys_timestamp_t delta = 0;
+
+	EFSYS_SPIN(I2C_PERIOD);
+	delta += I2C_PERIOD;
+
+	/* Set the pin state */
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO3_OUT, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO3_OEN,
+			    fip->fi_sda ? 0 : 1);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO0_OEN, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO0_OUT,
+			    fip->fi_scl ? 1 : 0);
+
+	EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
+
+	EFSYS_SPIN(I2C_PERIOD);
+	delta += I2C_PERIOD;
+
+	if (timep != NULL)
+		*timep += delta;
+}
+
+static	__checkReturn	boolean_t
+falcon_i2c_get_sda(
+	__in		efx_nic_t *enp,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	efx_oword_t oword;
+	efsys_timestamp_t delta = 0;
+	boolean_t state;
+
+	EFSYS_SPIN(I2C_PERIOD);
+	delta += I2C_PERIOD;
+
+	/* Get the pin state */
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	state = (EFX_OWORD_FIELD(oword, FRF_AB_GPIO3_IN) != 0);
+
+	EFSYS_SPIN(I2C_PERIOD);
+	delta += I2C_PERIOD;
+
+	if (timep != NULL)
+		*timep += delta;
+
+	return (state);
+}
+
+static	__checkReturn	boolean_t
+falcon_i2c_get_scl(
+	__in		efx_nic_t *enp,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	efx_oword_t oword;
+	efsys_timestamp_t delta = 0;
+	boolean_t state;
+
+	EFSYS_SPIN(I2C_PERIOD);
+	delta += I2C_PERIOD;
+
+	/* Get the pin state */
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	state = (EFX_OWORD_FIELD(oword, FRF_AB_GPIO0_IN) != 0);
+
+	EFSYS_SPIN(I2C_PERIOD);
+	delta += I2C_PERIOD;
+
+	if (timep != NULL)
+		*timep += delta;
+
+	return (state);
+}
+
+static			void
+falcon_i2c_sda_write(
+	__in		efx_nic_t *enp,
+	__in		boolean_t on,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	falcon_i2c_t *fip = &(enp->en_u.falcon.enu_fip);
+
+	fip->fi_sda = on;
+	falcon_i2c_set_sda_scl(enp, fip, timep);
+}
+
+static			void
+falcon_i2c_scl_write(
+	__in		efx_nic_t *enp,
+	__in   		boolean_t on,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	falcon_i2c_t *fip = &(enp->en_u.falcon.enu_fip);
+
+	fip->fi_scl = on;
+	falcon_i2c_set_sda_scl(enp, fip, timep);
+}
+
+static			void
+falcon_i2c_start(
+	__in		efx_nic_t *enp,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	falcon_i2c_t *fip = &(enp->en_u.falcon.enu_fip);
+
+	EFSYS_ASSERT(timep != NULL);
+
+	EFSYS_ASSERT(fip->fi_sda);
+
+	falcon_i2c_scl_write(enp, B_TRUE, timep);
+	falcon_i2c_sda_write(enp, B_FALSE, timep);
+	falcon_i2c_scl_write(enp, B_FALSE, timep);
+	falcon_i2c_sda_write(enp, B_TRUE, timep);
+}
+
+static			void
+falcon_i2c_bit_out(
+	__in		efx_nic_t *enp,
+	__in		boolean_t bit,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	falcon_i2c_t *fip = &(enp->en_u.falcon.enu_fip);
+
+	EFSYS_ASSERT(timep != NULL);
+
+	EFSYS_ASSERT(!(fip->fi_scl));
+
+	falcon_i2c_sda_write(enp, bit, timep);
+	falcon_i2c_scl_write(enp, B_TRUE, timep);
+	falcon_i2c_scl_write(enp, B_FALSE, timep);
+	falcon_i2c_sda_write(enp, B_TRUE, timep);
+}
+
+static			boolean_t
+falcon_i2c_bit_in(
+	__in		efx_nic_t *enp,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	falcon_i2c_t *fip = &(enp->en_u.falcon.enu_fip);
+	boolean_t bit;
+
+	EFSYS_ASSERT(timep != NULL);
+
+	EFSYS_ASSERT(!(fip->fi_scl));
+	EFSYS_ASSERT(fip->fi_sda);
+
+	falcon_i2c_scl_write(enp, B_TRUE, timep);
+	bit = falcon_i2c_get_sda(enp, timep);
+	falcon_i2c_scl_write(enp, B_FALSE, timep);
+
+	return (bit);
+}
+
+static			void
+falcon_i2c_stop(
+	__in		efx_nic_t *enp,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	falcon_i2c_t *fip = &(enp->en_u.falcon.enu_fip);
+
+	EFSYS_ASSERT(timep != NULL);
+
+	EFSYS_ASSERT(!(fip->fi_scl));
+
+	falcon_i2c_sda_write(enp, B_FALSE, timep);
+	falcon_i2c_scl_write(enp, B_TRUE, timep);
+	falcon_i2c_sda_write(enp, B_TRUE, timep);
+}
+
+static			void
+falcon_i2c_release(
+	__in		efx_nic_t *enp,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	falcon_i2c_t *fip = &(enp->en_u.falcon.enu_fip);
+
+	EFSYS_ASSERT(timep != NULL);
+
+	falcon_i2c_scl_write(enp, B_TRUE, timep);
+	falcon_i2c_sda_write(enp, B_TRUE, timep);
+
+	EFSYS_ASSERT(falcon_i2c_get_sda(enp, timep));
+	EFSYS_ASSERT(falcon_i2c_get_scl(enp, timep));
+
+	EFSYS_ASSERT(fip->fi_scl);
+	EFSYS_ASSERT(fip->fi_sda);
+
+	EFSYS_SPIN(10000);
+	*timep += 10000;
+}
+
+static	__checkReturn	int
+falcon_i2c_wait(
+	__in		efx_nic_t *enp)
+{
+	falcon_i2c_t *fip = &(enp->en_u.falcon.enu_fip);
+	int count;
+	int rc;
+
+	if (enp->en_u.falcon.enu_i2c_locked) {
+		rc = EBUSY;
+		goto fail1;
+	}
+
+	EFSYS_ASSERT(fip->fi_scl);
+	EFSYS_ASSERT(fip->fi_sda);
+
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		if (falcon_i2c_get_scl(enp, NULL) &&
+		    falcon_i2c_get_sda(enp, NULL))
+			goto done;
+
+		/* Spin for 1 ms */
+		EFSYS_SPIN(1000);
+
+	} while (++count < 20);
+
+	rc = ETIMEDOUT;
+	goto fail2;
+
+done:
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+falcon_i2c_byte_out(
+	__in		efx_nic_t *enp,
+	__in		uint8_t byte,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	unsigned int bit;
+
+	for (bit = 0; bit < 8; bit++) {
+		falcon_i2c_bit_out(enp, ((byte & 0x80) != 0), timep);
+		byte <<= 1;
+	}
+
+	/* Check for acknowledgement */
+	return ((falcon_i2c_bit_in(enp, timep)) ? EIO : 0);
+}
+
+static			uint8_t
+falcon_i2c_byte_in(
+	__in		efx_nic_t *enp,
+	__in		boolean_t ack,
+	__inout_opt	efsys_timestamp_t *timep)
+{
+	uint8_t byte;
+	unsigned int bit;
+
+	byte = 0;
+	for (bit = 0; bit < 8; bit++) {
+		byte <<= 1;
+		byte |= falcon_i2c_bit_in(enp, timep);
+	}
+
+	/* Send acknowledgement */
+	falcon_i2c_bit_out(enp, !ack, timep);
+
+	return (byte);
+}
+
+	__checkReturn	int
+falcon_i2c_check(
+	__in		efx_nic_t *enp,
+	__in		uint8_t devid)
+{
+	int pstate;
+	int lstate;
+	efsys_timestamp_t start;
+	efsys_timestamp_t end;
+	efsys_timestamp_t expected;
+	unsigned int attempt;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFSYS_LOCK(enp->en_eslp, lstate);
+	EFSYS_PREEMPT_DISABLE(pstate);
+
+	/* Check the state of the I2C bus */
+	if ((rc = falcon_i2c_wait(enp)) != 0)
+		goto fail1;
+
+	attempt = 0;
+
+again:
+	EFSYS_TIMESTAMP(&start);
+	expected = 0;
+
+	/* Select device and write cycle */
+	falcon_i2c_start(enp, &expected);
+
+	if ((rc = falcon_i2c_byte_out(enp, I2C_WRITE_CMD(devid),
+	    &expected)) != 0)
+		goto fail2;
+
+	/* Abort the cycle since we're only testing the target is there */
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+		goto fail3;
+	}
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+
+	EFSYS_PROBE(success);
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+
+	goto fail1;
+
+fail2:
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+	}
+
+	EFSYS_PROBE(fail2);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_i2c_read(
+	__in			efx_nic_t *enp,
+	__in			uint8_t devid,
+	__in			uint8_t addr,
+	__out_bcount(size)	caddr_t base,
+	__in			size_t size)
+{
+	int pstate;
+	int lstate;
+	efsys_timestamp_t start;
+	efsys_timestamp_t end;
+	efsys_timestamp_t expected;
+	unsigned int attempt;
+	unsigned int i;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFSYS_ASSERT(size != 0);
+
+	EFSYS_LOCK(enp->en_eslp, lstate);
+	EFSYS_PREEMPT_DISABLE(pstate);
+
+	/* Check the state of the I2C bus */
+	if ((rc = falcon_i2c_wait(enp)) != 0)
+		goto fail1;
+
+	attempt = 0;
+
+again:
+	EFSYS_TIMESTAMP(&start);
+	expected = 0;
+
+	/* Select device and write cycle */
+	falcon_i2c_start(enp, &expected);
+
+	if ((rc = falcon_i2c_byte_out(enp, I2C_WRITE_CMD(devid),
+	    &expected)) != 0)
+		goto fail2;
+
+	/* Write address */
+	if ((rc = falcon_i2c_byte_out(enp, addr, &expected)) != 0)
+		goto fail3;
+
+	/* Select device and read cycle */
+	falcon_i2c_start(enp, &expected);
+
+	if ((rc = falcon_i2c_byte_out(enp, I2C_READ_CMD(devid),
+	    &expected)) != 0)
+		goto fail4;
+
+	/* Read bytes */
+	for (i = 0; i < size; i++)
+		*(uint8_t *)(base + i) =
+			falcon_i2c_byte_in(enp, (i < size - 1), &expected);
+
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+		goto fail5;
+	}
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+
+	goto fail1;
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+	}
+
+	EFSYS_PROBE(fail2);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_i2c_write(
+	__in			efx_nic_t *enp,
+	__in			uint8_t devid,
+	__in			uint8_t addr,
+	__in_bcount(size)	caddr_t base,
+	__in			size_t size)
+{
+	int pstate;
+	int lstate;
+	efsys_timestamp_t start;
+	efsys_timestamp_t end;
+	efsys_timestamp_t expected;
+	unsigned int attempt;
+	unsigned int i;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFSYS_ASSERT(size != 0);
+
+	EFSYS_LOCK(enp->en_eslp, lstate);
+	EFSYS_PREEMPT_DISABLE(pstate);
+
+	/* Check the state of the I2C bus */
+	if ((rc = falcon_i2c_wait(enp)) != 0)
+		goto fail1;
+
+	attempt = 0;
+
+again:
+	EFSYS_TIMESTAMP(&start);
+	expected = 0;
+
+	/* Select device and write cycle */
+	falcon_i2c_start(enp, &expected);
+
+	if ((rc = falcon_i2c_byte_out(enp, I2C_WRITE_CMD(devid),
+	    &expected)) != 0)
+		goto fail2;
+
+	/* Write address */
+	if ((rc = falcon_i2c_byte_out(enp, addr, &expected)) != 0)
+		goto fail3;
+
+	/* Write bytes */
+	for (i = 0; i < size; i++) {
+		if ((rc = falcon_i2c_byte_out(enp, *(uint8_t *)(base + i),
+		    &expected)) != 0)
+			goto fail4;
+	}
+
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+		goto fail5;
+	}
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+
+	goto fail1;
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+	}
+
+	EFSYS_PROBE(fail2);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+	return (rc);
+}
+
+#if EFSYS_OPT_PHY_NULL
+
+	__checkReturn		int
+falcon_i2c_recv(
+	__in			efx_nic_t *enp,
+	__in			uint8_t devid,
+	__out_bcount(size)	caddr_t base,
+	__in			size_t size)
+{
+	int pstate;
+	int lstate;
+	efsys_timestamp_t start;
+	efsys_timestamp_t end;
+	efsys_timestamp_t expected;
+	unsigned int attempt;
+	unsigned int i;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFSYS_ASSERT(size != 0);
+
+	EFSYS_LOCK(enp->en_eslp, lstate);
+	EFSYS_PREEMPT_DISABLE(pstate);
+
+	/* Check the state of the I2C bus */
+	if ((rc = falcon_i2c_wait(enp)) != 0)
+		goto fail1;
+
+	attempt = 0;
+
+again:
+	EFSYS_TIMESTAMP(&start);
+	expected = 0;
+
+	/* Select device and read cycle */
+	falcon_i2c_start(enp, &expected);
+
+	if ((rc = falcon_i2c_byte_out(enp, I2C_READ_CMD(devid), &expected))
+	    != 0)
+		goto fail2;
+
+	/* Read bytes */
+	for (i = 0; i < size; i++)
+		*(uint8_t *)(base + i) = falcon_i2c_byte_in(enp, (i < size - 1),
+		    &expected);
+
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+		goto fail3;
+	}
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail5);
+
+	goto fail1;
+
+fail2:
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+	}
+
+	EFSYS_PROBE(fail2);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_i2c_send(
+	__in			efx_nic_t *enp,
+	__in			uint8_t devid,
+	__in_bcount(size)	caddr_t base,
+	__in			size_t size)
+{
+	int pstate;
+	int lstate;
+	efsys_timestamp_t start;
+	efsys_timestamp_t end;
+	efsys_timestamp_t expected;
+	unsigned int attempt;
+	unsigned int i;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFSYS_ASSERT(size != 0);
+
+	EFSYS_LOCK(enp->en_eslp, lstate);
+	EFSYS_PREEMPT_DISABLE(pstate);
+
+	/* Check the state of the I2C bus */
+	if ((rc = falcon_i2c_wait(enp)) != 0)
+		goto fail1;
+
+	attempt = 0;
+
+again:
+	EFSYS_TIMESTAMP(&start);
+	expected = 0;
+
+	/* Select device and write cycle */
+	falcon_i2c_start(enp, &expected);
+
+	if ((rc = falcon_i2c_byte_out(enp, I2C_WRITE_CMD(devid), &expected))
+	    != 0)
+		goto fail2;
+
+	/* Write bytes */
+	for (i = 0; i < size; i++)
+		if ((rc = falcon_i2c_byte_out(enp,	*(uint8_t *)(base + i),
+		    &expected)) != 0)
+			goto fail3;
+
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+		goto fail4;
+	}
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail5);
+
+	goto fail1;
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	falcon_i2c_stop(enp, &expected);
+	falcon_i2c_release(enp, &expected);
+
+	EFSYS_TIMESTAMP(&end);
+
+	/* The transaction may have timed out */
+	if (end - start > expected * 2) {
+		if (++attempt < I2C_RETRY_LIMIT) {
+			EFSYS_PROBE1(retry, unsigned int, attempt);
+
+			goto again;
+		}
+
+		rc = ETIMEDOUT;
+	}
+
+	EFSYS_PROBE(fail2);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	EFSYS_PREEMPT_ENABLE(pstate);
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+	return (rc);
+}
+#endif	/* EFSYS_OPT_PHY_NULL */
+
+#endif	/* EFSYS_OPT_FALCON */
--- /dev/null	2013-08-22 18:57:29.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_impl.h	2013-08-22 18:57:29.934311026 -0400
@@ -0,0 +1,382 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_FALCON_IMPL_H
+#define	_SYS_FALCON_IMPL_H
+
+#include "efx.h"
+#include "efx_regs.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct falcon_i2c_s {
+	boolean_t	fi_sda;
+	boolean_t	fi_scl;
+} falcon_i2c_t;
+
+typedef struct falcon_spi_dev_s {
+	uint32_t	fsd_sf_sel;
+	size_t		fsd_size;
+	uint32_t	fsd_adbcnt;
+	boolean_t	fsd_munge;
+	uint32_t	fsd_erase_cmd;
+	size_t 		fsd_erase_size;
+	size_t		fsd_write_size;
+} falcon_spi_dev_t;
+
+extern	__checkReturn	int
+falcon_nic_probe(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_PCIE_TUNE
+
+extern 			int
+falcon_nic_pcie_tune(
+	__in		efx_nic_t *enp,
+	__in		unsigned int nlanes);
+
+#endif
+
+#define	FALCON_NIC_CFG_RAW_SZ 0x400
+
+extern	__checkReturn	int
+falcon_nic_cfg_raw_read_verify(
+	__in		efx_nic_t *enp,
+	__in		uint32_t offset,
+	__in		uint32_t size,
+	__out		uint8_t *cfg);
+
+extern	__checkReturn	int
+falcon_nic_cfg_build(
+	__in		efx_nic_t *enp,
+	__out		efx_nic_cfg_t *encp);
+
+extern	__checkReturn	int
+falcon_nic_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+falcon_nic_init(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_DIAG
+
+extern	__checkReturn	int
+falcon_nic_register_test(
+	__in		efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+extern			void
+falcon_nic_fini(
+	__in		efx_nic_t *enp);
+
+extern			void
+falcon_nic_unprobe(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+falcon_nic_mac_reset(
+	__in		efx_nic_t *enp);
+
+extern			void
+falcon_mac_wrapper_enable(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+falcon_mac_wrapper_disable(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_LOOPBACK
+
+extern	__checkReturn	int
+falcon_mac_loopback_set(
+	__in		efx_nic_t *enp,
+	__in		efx_link_mode_t link_mode,
+	__in		efx_loopback_type_t loopback_type);
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+extern			void
+falcon_nic_phy_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn		int
+falcon_nvram_init(
+	__in			efx_nic_t *enp);
+
+#if EFSYS_OPT_NVRAM
+
+#if EFSYS_OPT_DIAG
+
+extern	__checkReturn		int
+falcon_nvram_test(
+	__in			efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+extern	__checkReturn		int
+falcon_nvram_size(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *sizep);
+
+extern	__checkReturn		int
+falcon_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4]);
+
+extern	__checkReturn		int
+falcon_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *pref_chunkp);
+
+extern	__checkReturn		int
+falcon_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	 __checkReturn		int
+falcon_nvram_erase(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type);
+
+extern	__checkReturn		int
+falcon_nvram_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+ 	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern				void
+falcon_nvram_rw_finish(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type);
+
+extern	__checkReturn		int
+falcon_nvram_set_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint16_t version[4]);
+
+#endif	/* EFSYS_OPT_NVRAM */
+
+extern				void
+falcon_nvram_fini(
+	__in			efx_nic_t *enp);
+
+#if EFSYS_OPT_VPD
+
+extern	__checkReturn		int
+falcon_vpd_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep);
+
+extern	__checkReturn		int
+falcon_vpd_read(
+	__in			efx_nic_t *enp,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+falcon_vpd_verify(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+falcon_vpd_get(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__inout			efx_vpd_value_t *evvp);
+
+extern	__checkReturn		int
+falcon_vpd_set(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_value_t *evvp);
+
+extern	__checkReturn		int
+falcon_vpd_next(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out			efx_vpd_value_t *evvp,
+	__inout			unsigned int *contp);
+
+extern __checkReturn		int
+falcon_vpd_write(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+#endif	/* EFSYS_OPT_VPD */
+
+extern	__checkReturn	int
+falcon_sram_init(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_DIAG
+
+extern	__checkReturn	int
+falcon_sram_test(
+	__in		efx_nic_t *enp,
+	__in		efx_sram_pattern_fn_t func);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+extern		void
+falcon_sram_fini(
+	__in	efx_nic_t *enp);
+
+extern	__checkReturn	int
+falcon_i2c_check(
+	__in		efx_nic_t *enp,
+	__in		uint8_t devid);
+
+extern	__checkReturn		int
+falcon_i2c_read(
+	__in			efx_nic_t *enp,
+	__in			uint8_t devid,
+	__in			uint8_t addr,
+	__out_bcount(size)	caddr_t base,
+	__in			size_t size);
+
+extern	__checkReturn		int
+falcon_i2c_write(
+	__in			efx_nic_t *enp,
+	__in			uint8_t devid,
+	__in			uint8_t addr,
+	__in_bcount(size)	caddr_t base,
+	__in			size_t size);
+
+#if EFSYS_OPT_PHY_NULL
+
+extern	__checkReturn		int
+falcon_i2c_recv(
+	__in			efx_nic_t *enp,
+	__in			uint8_t devid,
+	__out_bcount(size)	caddr_t base,
+	__in			size_t size);
+
+extern	__checkReturn		int
+falcon_i2c_send(
+	__in			efx_nic_t *enp,
+	__in			uint8_t devid,
+	__in_bcount(size)	caddr_t base,
+	__in			size_t size);
+
+#endif	/* EFSYS_OPT_PHY_NULL */
+
+extern	__checkReturn	int
+falcon_mdio_write(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__in		uint16_t reg,
+	__in		efx_word_t *ewp);
+
+extern	__checkReturn	int
+falcon_mdio_read(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__in		uint16_t reg,
+	__out		efx_word_t *ewp);
+
+#if EFSYS_OPT_MAC_STATS
+
+extern	__checkReturn			int
+falcon_mac_stats_upload(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp);
+
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+extern	__checkReturn	int
+falcon_mac_poll(
+       __in		efx_nic_t *enp,
+       __out		efx_link_mode_t	*link_modep);
+
+extern	__checkReturn	int
+falcon_mac_up(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *mac_upp);
+
+#if EFSYS_OPT_LOOPBACK
+
+extern	__checkReturn	int
+falcon_mac_loopback_set(
+	__in		efx_nic_t *enp,
+	__in		efx_link_mode_t link_mode,
+	__in		efx_loopback_type_t loopback_type);
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+typedef enum falcon_spi_type_e {
+	FALCON_SPI_FLASH = 0,
+	FALCON_SPI_EEPROM,
+	FALCON_SPI_NTYPES
+} falcon_spi_type_t;
+
+extern	__checkReturn		int
+falcon_spi_dev_read(
+	__in			efx_nic_t *enp,
+	__in			falcon_spi_type_t type,
+	__in			uint32_t addr,
+	__out_bcount(size)	caddr_t base,
+	__in			size_t size);
+
+extern	__checkReturn		int
+falcon_spi_dev_write(
+	__in			efx_nic_t *enp,
+	__in			falcon_spi_type_t type,
+	__in			uint32_t addr,
+	__in_bcount(size)	caddr_t base,
+	__in			size_t size);
+
+extern	__checkReturn		int
+falcon_spi_dev_erase(
+	__in			efx_nic_t *enp,
+	__in			falcon_spi_type_t type,
+	__in			uint32_t addr,
+	__in			size_t size);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_FALCON_IMPL_H */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_mac.c	2013-08-22 18:57:30.021592780 -0400
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_FALCON
+
+#if EFSYS_OPT_MAC_FALCON_GMAC
+#include "falcon_gmac.h"
+#endif
+
+#if EFSYS_OPT_MAC_FALCON_XMAC
+#include "falcon_xmac.h"
+#endif
+
+	__checkReturn	int
+falcon_mac_poll(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t	*link_modep)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+	efx_link_mode_t	link_mode;
+	unsigned int fcntl;
+	uint32_t lp_cap_mask;
+	boolean_t mac_up = B_TRUE;
+	boolean_t reconfigure_mac = B_FALSE;
+	int rc;
+
+	/* Poll PHY for link state changes */
+	rc = epop->epo_downlink_check(enp, &link_mode, &fcntl, &lp_cap_mask);
+	if (rc != 0) {
+		fcntl = epp->ep_fcntl;
+		lp_cap_mask = epp->ep_lp_cap_mask;
+		link_mode = EFX_LINK_UNKNOWN;
+	}
+
+#if EFSYS_OPT_LOOPBACK
+	/* Ignore the phy link state in MAC level loopback */
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_GMAC:
+		link_mode = EFX_LINK_1000FDX;
+		break;
+
+	case EFX_LOOPBACK_XGMII:
+	case EFX_LOOPBACK_XGXS:
+	case EFX_LOOPBACK_XAUI:
+		link_mode = EFX_LINK_10000FDX;
+		break;
+
+	default:
+		break;
+	}
+
+	if (epp->ep_loopback_type != EFX_LOOPBACK_OFF) {
+		/*
+		 * We've already configured the correct MAC for the correct
+		 * speed, so all we need to do is wait for the phy loopback
+		 * to come up. Keep ep_link_mode et al. at the values forced
+		 * by falcon_mac_loopback_set(), but return the current value
+		 * of link up vs link down.
+		 */
+		goto poll_mac;
+	}
+#endif
+
+	/* Hook in the correct MAC and reconfigure for the new link speed. */
+	epp->ep_lp_cap_mask = lp_cap_mask;
+
+	if (link_mode != epp->ep_link_mode) {
+		epp->ep_link_mode = link_mode;
+
+		if ((rc = efx_mac_select(enp)) != 0)
+			goto fail1;
+
+		reconfigure_mac = B_TRUE;
+	}
+
+	if (fcntl != epp->ep_fcntl) {
+		epp->ep_fcntl = fcntl;
+		reconfigure_mac = B_TRUE;
+	}
+
+	if (reconfigure_mac)
+		epp->ep_emop->emo_reconfigure(enp);
+
+#if EFSYS_OPT_LOOPBACK
+poll_mac:
+#endif
+	/* The XMAC requires additional polling */
+	if (epp->ep_mac_type == EFX_MAC_FALCON_XMAC)
+		falcon_xmac_poll(enp, &mac_up);
+	else
+		mac_up = B_TRUE;
+
+	epp->ep_mac_up = mac_up;
+	*link_modep = link_mode;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+falcon_mac_up(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *mac_upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+
+	/* falcon_mac_poll() *must* be run on Falcon */
+	*mac_upp = epp->ep_mac_up;
+
+	return (0);
+}
+
+			void
+falcon_mac_wrapper_enable(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_oword_t oword;
+	uint32_t speed;
+	boolean_t drain = epp->ep_mac_drain;
+
+	switch (epp->ep_link_mode) {
+	case EFX_LINK_100FDX:
+	case EFX_LINK_100HDX:
+		speed = FRF_AB_MAC_SPEED_100M;
+		break;
+
+	case EFX_LINK_1000FDX:
+	case EFX_LINK_1000HDX:
+		speed = FRF_AB_MAC_SPEED_1G;
+		break;
+
+	case EFX_LINK_10000FDX:
+		speed = FRF_AB_MAC_SPEED_10G;
+		break;
+
+	default:
+#if EFSYS_OPT_LOOPBACK
+		EFSYS_ASSERT3U(epp->ep_loopback_type, ==, EFX_LOOPBACK_OFF);
+#endif	/* EFSYS_OPT_LOOPBACK */
+		drain = B_TRUE;
+		speed = FRF_AB_MAC_SPEED_10M;
+	};
+
+	/* Bring the mac wrapper out of reset and configure it */
+	switch (epp->ep_mac_type) {
+	case EFX_MAC_FALCON_GMAC:
+		EFX_POPULATE_OWORD_6(oword,
+		    FRF_AB_MAC_XOFF_VAL, 0xffff,
+		    FRF_AB_MAC_XG_DISTXCRC, 0,
+		    FRF_AB_MAC_BCAD_ACPT, (epp->ep_brdcst) ? 1 : 0,
+		    FRF_AB_MAC_UC_PROM, (epp->ep_unicst) ? 1 : 0,
+		    FRF_AB_MAC_LINK_STATUS, 1,
+		    FRF_AB_MAC_SPEED, speed);
+		break;
+
+	case EFX_MAC_FALCON_XMAC:
+		EFX_POPULATE_OWORD_6(oword,
+		    FRF_AB_MAC_XOFF_VAL, 0xffff,
+		    FRF_AB_MAC_XG_DISTXCRC, 0,
+		    FRF_AB_MAC_BCAD_ACPT, 1,
+		    FRF_AB_MAC_UC_PROM, 0,
+		    FRF_AB_MAC_LINK_STATUS, 1,
+		    FRF_AB_MAC_SPEED, speed);
+		break;
+
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		break;
+	}
+
+	/* Open TX_DRAIN if the link is up */
+	if (enp->en_family == EFX_FAMILY_FALCON)
+		EFX_SET_OWORD_FIELD(oword, FRF_BB_TXFIFO_DRAIN_EN,
+				    drain ? 1 : 0);
+	EFX_BAR_WRITEO(enp, FR_AB_MAC_CTRL_REG, &oword);
+
+	/* Push multicast hash. Set the broadcast bit (0xff) appropriately */
+	EFX_BAR_WRITEO(enp, FR_AB_MAC_MC_HASH0_REG,
+	    &(epp->ep_multicst_hash[0]));
+	memcpy(&oword, &(epp->ep_multicst_hash[1]), sizeof (oword));
+	if (epp->ep_brdcst)
+		EFX_SET_OWORD_BIT(oword, 0x7f);
+	EFX_BAR_WRITEO(enp, FR_AB_MAC_MC_HASH1_REG, &oword);
+
+	/* Configure RX <-> mac_wrapper link */
+	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_XON_TX_TH, 25);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_XOFF_TX_TH, 20);
+	/* Send XON and XOFF at ~3 * max MTU away from empty/full */
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_XON_MAC_TH, 27648 >> 8);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_XOFF_MAC_TH, 54272 >> 8);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_XOFF_MAC_EN,
+	    (epp->ep_fcntl & EFX_FCNTL_GENERATE) ? 1 : 0);
+
+	if (enp->en_family == EFX_FAMILY_FALCON)
+		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, drain ? 0 : 1);
+
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
+}
+
+	__checkReturn	int
+falcon_mac_wrapper_disable(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	int rc;
+
+	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
+
+	/* There is no point in draining more than once */
+	EFX_BAR_READO(enp, FR_AB_MAC_CTRL_REG, &oword);
+	if (EFX_OWORD_FIELD(oword, FRF_BB_TXFIFO_DRAIN_EN))
+		return (0);
+
+	if ((rc = falcon_nic_mac_reset(enp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_LOOPBACK
+
+	__checkReturn	int
+falcon_mac_loopback_set(
+	__in		efx_nic_t *enp,
+	__in		efx_link_mode_t link_mode,
+	__in		efx_loopback_type_t loopback_type)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+	const efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_loopback_type_t old_loopback_type;
+	efx_link_mode_t old_loopback_link_mode;
+	uint32_t phy_loopback_mask;
+	boolean_t phy_loopback_changed;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	old_loopback_type = epp->ep_loopback_type;
+	old_loopback_link_mode = epp->ep_loopback_link_mode;
+
+	phy_loopback_mask = EFX_LOOPBACK_MASK &
+		~(EFX_LOOPBACK_MAC_MASK | (1 << EFX_LOOPBACK_OFF));
+	phy_loopback_changed = (phy_loopback_mask &
+		((1 << loopback_type) ^ (1 << epp->ep_loopback_type))) != 0;
+	epp->ep_loopback_type = loopback_type;
+	epp->ep_loopback_link_mode = link_mode;
+
+	if (loopback_type == EFX_LOOPBACK_OFF)
+		link_mode = EFX_LINK_DOWN;
+	else if (link_mode == EFX_LINK_UNKNOWN) {
+		for (link_mode = EFX_LINK_NMODES - 1;
+		    link_mode > EFX_LINK_UNKNOWN; --link_mode) {
+		if ((1 << loopback_type) &
+		    encp->enc_loopback_types[link_mode])
+			break;
+		}
+	}
+
+	EFSYS_ASSERT(((1 << loopback_type) & ~FALCON_GMAC_LOOPBACK_MASK) ||
+			link_mode == EFX_LINK_1000FDX);
+	EFSYS_ASSERT(((1 << loopback_type) & ~FALCON_XMAC_LOOPBACK_MASK) ||
+			link_mode == EFX_LINK_10000FDX);
+
+	/*
+	 * In loopback, a PHY typically requires the correct MAC and link
+	 * to be initialized before they will report link up. Determine
+	 * the expected link speed and select the correct MAC. Ensure that
+	 * ep_link_mode != LINK_DOWN in loopback so that TXDRAIN isn't enabled,
+	 * because we'll never again run efx_mac_select() to subsequently
+	 * reset the EM block.
+	 */
+	epp->ep_link_mode = link_mode;
+	if ((rc = efx_mac_select(enp)) != 0)
+		goto fail1;
+
+	/*
+	 * Don't reset and reconfigure the PHY unless it's
+	 * configuration has actually changed
+	 */
+	if (phy_loopback_changed) {
+		if ((rc = epop->epo_reset(enp)) != 0)
+			goto fail2;
+
+		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY);
+		enp->en_reset_flags &= ~EFX_RESET_PHY;
+
+		if ((rc = epop->epo_reconfigure(enp)) != 0)
+			goto fail3;
+	}
+
+	epp->ep_emop->emo_reconfigure(enp);
+
+	/* Ensure that the MAC is subsequently polled */
+	epp->ep_mac_poll_needed = B_TRUE;
+	epp->ep_mac_up = B_FALSE;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	epp->ep_loopback_type = old_loopback_type;
+	epp->ep_loopback_link_mode = old_loopback_link_mode;
+	epp->ep_link_mode = EFX_LINK_DOWN;
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+#if EFSYS_OPT_MAC_STATS
+
+	__checkReturn			int
+falcon_mac_stats_upload(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp)
+{
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFX_POPULATE_OWORD_3(oword,
+	    FRF_AB_MAC_STAT_DMA_ADR_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff,
+	    FRF_AB_MAC_STAT_DMA_ADR_DW1, EFSYS_MEM_ADDR(esmp) >> 32,
+	    FRF_AB_MAC_STAT_DMA_CMD, 1);
+
+	EFX_BAR_WRITEO(enp, FR_AB_MAC_STAT_DMA_REG, &oword);
+
+	return (0);
+}
+
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+#endif	/* EFSYS_OPT_FALCON */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_mdio.c	2013-08-22 18:57:30.110242915 -0400
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_FALCON
+
+static	__checkReturn	int
+falcon_mdio_wait(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	unsigned int count;
+	int rc;
+
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		EFX_BAR_READO(enp, FR_AB_MD_STAT_REG, &oword);
+
+		if (EFX_OWORD_FIELD(oword, FRF_AB_MD_BSY) == 0)
+			goto done;
+
+		/* Spin for 100 us */
+		EFSYS_SPIN(100);
+
+	} while (++count < 100);
+
+	rc = ETIMEDOUT;
+	goto fail1;
+
+done:
+	if (EFX_OWORD_FIELD(oword, FRF_AB_MD_LNFL) != 0) {
+		rc = EIO;
+		goto fail2;
+	}
+
+	if (EFX_OWORD_FIELD(oword, FRF_AB_MD_BSERR) != 0) {
+		rc = EIO;
+		goto fail3;
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+falcon_mdio_write(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__in		uint16_t reg,
+	__in		efx_word_t *ewp)
+{
+	int state;
+	efx_oword_t oword;
+	uint32_t prtad;
+	uint32_t devad;
+	uint32_t addr;
+	uint16_t val;
+	int rc;
+
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	/* Check MDIO is not currently being accessed */
+	if ((rc = falcon_mdio_wait(enp)) != 0)
+		goto fail1;
+
+	prtad = port;
+	devad = mmd;
+
+	/* Write address */
+	EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_PRT_ADR, prtad,
+	    FRF_AB_MD_DEV_ADR, devad);
+	EFX_BAR_WRITEO(enp, FR_AB_MD_ID_REG, &oword);
+
+	addr = reg;
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AB_MD_PHY_ADR, addr);
+	EFX_BAR_WRITEO(enp, FR_AB_MD_PHY_ADR_REG, &oword);
+
+	/* Write data */
+	val = EFX_WORD_FIELD(*ewp, EFX_WORD_0);
+
+	EFSYS_PROBE4(mdio_write, uint8_t, port, uint8_t, mmd,
+	    uint16_t, reg, uint16_t, val);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AB_MD_TXD, (uint32_t)val);
+	EFX_BAR_WRITEO(enp, FR_AB_MD_TXD_REG, &oword);
+
+	/* Select clause 45 write cycle */
+	EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_WRC, 1, FRF_AB_MD_GC, 0);
+	EFX_BAR_WRITEO(enp, FR_AB_MD_CS_REG, &oword);
+
+	/* Wait for the cycle to complete */
+	if ((rc = falcon_mdio_wait(enp)) != 0)
+		goto fail2;
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+	return (rc);
+}
+
+	__checkReturn	int
+falcon_mdio_read(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__in		uint16_t reg,
+	__out		efx_word_t *ewp)
+{
+	int state;
+	efx_oword_t oword;
+	uint32_t prtad;
+	uint32_t devad;
+	uint32_t addr;
+	uint16_t val;
+	int rc;
+
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	/* Check MDIO is not currently being accessed */
+	if ((rc = falcon_mdio_wait(enp)) != 0)
+		goto fail1;
+
+	prtad = port;
+	devad = mmd;
+
+	/* Write address */
+	EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_PRT_ADR, prtad,
+	    FRF_AB_MD_DEV_ADR, devad);
+	EFX_BAR_WRITEO(enp, FR_AB_MD_ID_REG, &oword);
+
+	addr = reg;
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AB_MD_PHY_ADR, addr);
+	EFX_BAR_WRITEO(enp, FR_AB_MD_PHY_ADR_REG, &oword);
+
+	/* Clear the data register */
+	EFX_SET_OWORD(oword);
+	EFX_BAR_WRITEO(enp, FR_AB_MD_RXD_REG, &oword);
+
+	/* Select clause 45 read cycle */
+	EFX_POPULATE_OWORD_2(oword, FRF_AB_MD_RDC, 1, FRF_AB_MD_GC, 0);
+	EFX_BAR_WRITEO(enp, FR_AB_MD_CS_REG, &oword);
+
+	/* Wait for the cycle to complete */
+	if ((rc = falcon_mdio_wait(enp)) != 0)
+		goto fail2;
+
+	/* Read data */
+	EFX_BAR_READO(enp, FR_AB_MD_RXD_REG, &oword);
+	val = (uint16_t)EFX_OWORD_FIELD(oword, FRF_AB_MD_RXD);
+
+	EFSYS_PROBE4(mdio_read, uint8_t, port, uint8_t, mmd,
+	    uint16_t, reg, uint16_t, val);
+
+	EFX_POPULATE_WORD_1(*ewp, EFX_WORD_0, val);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_FALCON */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_nic.c	2013-08-22 18:57:30.196496145 -0400
@@ -0,0 +1,1101 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "falcon_nvram.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_regs_pci.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_FALCON
+
+#if EFSYS_OPT_MAC_FALCON_XMAC
+#include "falcon_xmac.h"
+#endif
+
+#if EFSYS_OPT_MAC_FALCON_GMAC
+#include "falcon_gmac.h"
+#endif
+
+#if EFSYS_OPT_MON_LM87
+#include "lm87.h"
+#endif
+
+#if EFSYS_OPT_MON_MAX6647
+#include "max6647.h"
+#endif
+
+#if EFSYS_OPT_PHY_NULL
+#include "nullphy.h"
+#endif
+
+#if EFSYS_OPT_PHY_QT2022C2
+#include "qt2022c2.h"
+#endif
+
+#if EFSYS_OPT_PHY_SFX7101
+#include "sfx7101.h"
+#endif
+
+#if EFSYS_OPT_PHY_TXC43128
+#include "txc43128.h"
+#endif
+
+#if EFSYS_OPT_PHY_SFT9001
+#include "sft9001.h"
+#endif
+
+#if EFSYS_OPT_PHY_QT2025C
+#include "qt2025c.h"
+#endif
+
+static	__checkReturn		int
+falcon_nic_cfg_raw_read(
+	__in			efx_nic_t *enp,
+	__in			uint32_t offset,
+	__in			uint32_t size,
+	__out			void *cfg)
+{
+	EFSYS_ASSERT3U(offset + size, <=, FALCON_NIC_CFG_RAW_SZ);
+
+#if EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE
+	if (enp->en_u.falcon.enu_forced_cfg != NULL) {
+		memcpy(cfg, enp->en_u.falcon.enu_forced_cfg + offset, size);
+		return (0);
+	}
+#endif	/* EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE */
+
+	return falcon_spi_dev_read(enp, FALCON_SPI_FLASH, offset,
+		    (caddr_t)cfg, size);
+}
+
+	__checkReturn		int
+falcon_nic_cfg_raw_read_verify(
+	__in			efx_nic_t *enp,
+	__in			uint32_t offset,
+	__in			uint32_t size,
+	__out			uint8_t *cfg)
+{
+	uint32_t csum_offset;
+	uint16_t magic, version, cksum;
+	int rc;
+	efx_word_t word;
+
+	if ((rc = falcon_nic_cfg_raw_read(enp, CFG_MAGIC_REG_SF_OFST,
+		    sizeof (word), &word)) != 0)
+		goto fail1;
+
+	magic = EFX_WORD_FIELD(word, MAGIC);
+
+	if ((rc = falcon_nic_cfg_raw_read(enp, CFG_VERSION_REG_SF_OFST,
+		    sizeof (word), &word)) != 0)
+		goto fail2;
+
+	version = EFX_WORD_FIELD(word, VERSION);
+
+	cksum = 0;
+	for (csum_offset = (version < 4) ? CFG_MAGIC_REG_SF_OFST : 0;
+	    csum_offset < FALCON_NIC_CFG_RAW_SZ;
+	    csum_offset += sizeof (efx_word_t)) {
+
+		if ((rc = falcon_nic_cfg_raw_read(enp, csum_offset,
+			    sizeof (word), &word)) != 0)
+			goto fail3;
+
+		cksum += EFX_WORD_FIELD(word, EFX_WORD_0);
+	}
+	if (magic != MAGIC_DECODE || version < 2 || cksum != 0xffff) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	if ((rc = falcon_nic_cfg_raw_read(enp, offset, size, cfg)) != 0)
+		goto fail5;
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+falcon_nic_probe(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	/* Initialise the nvram */
+	if ((rc = falcon_nvram_init(enp)) != 0)
+		goto fail1;
+
+	/* Probe the board configuration */
+	if ((rc = falcon_nic_cfg_build(enp, encp)) != 0)
+		goto fail2;
+	epp->ep_adv_cap_mask = epp->ep_default_adv_cap_mask;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#define	FALCON_NIC_CFG_BUILD_LOWEST_REG				\
+	MIN(CFG_BOARD_REV_REG_SF_OFST,				\
+	    MIN(CFG_BOARD_TYPE_REG_SF_OFST,			\
+		MIN(CFG_PHY_PORT_REG_SF_OFST,			\
+		    MIN(CFG_PHY_TYPE_REG_SF_OFST,		\
+			MIN(MAC_ADDRESS_SF_OFST,		\
+			    MIN(NIC_STAT_SF_OFST,		\
+				SRAM_CFG_SF_OFST))))))
+
+
+#define	FALCON_NIC_CFG_BUILD_HIGHEST_REG			\
+	MAX(CFG_BOARD_REV_REG_SF_OFST + 1,			\
+	    MAX(CFG_BOARD_TYPE_REG_SF_OFST + 1,			\
+		MAX(CFG_PHY_PORT_REG_SF_OFST + 1,		\
+		    MAX(CFG_PHY_TYPE_REG_SF_OFST + 1,		\
+			MAX(MAC_ADDRESS_SF_OFST + 6,		\
+			    MAX(NIC_STAT_SF_OFST + 16,		\
+				SRAM_CFG_SF_OFST + 16))))))
+
+#define	FALCON_NIC_CFG_BUILD_NEEDED_CFG_SIZE		\
+	(FALCON_NIC_CFG_BUILD_HIGHEST_REG -		\
+	    FALCON_NIC_CFG_BUILD_LOWEST_REG)
+
+	__checkReturn	int
+falcon_nic_cfg_build(
+	__in		efx_nic_t *enp,
+	__out		efx_nic_cfg_t *encp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	uint8_t cfg[FALCON_NIC_CFG_BUILD_NEEDED_CFG_SIZE];
+	uint8_t *origin = cfg - FALCON_NIC_CFG_BUILD_LOWEST_REG;
+	efx_oword_t *owordp;
+	uint8_t major;
+	uint8_t minor;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	(void) memset(encp, 0, sizeof (efx_nic_cfg_t));
+
+	if ((rc = falcon_nic_cfg_raw_read_verify(enp,
+	    FALCON_NIC_CFG_BUILD_LOWEST_REG,
+	    FALCON_NIC_CFG_BUILD_NEEDED_CFG_SIZE, cfg)) != 0)
+		goto fail1;
+
+	encp->enc_board_type = EFX_BYTE_FIELD(
+		((efx_byte_t *)origin)[CFG_BOARD_TYPE_REG_SF_OFST],
+		EFX_BYTE_0);
+
+	/* Read board revision */
+	major = EFX_BYTE_FIELD(
+	    ((efx_byte_t *)origin)[CFG_BOARD_REV_REG_SF_OFST],
+	    BOARD_REV_MAJOR);
+	minor = EFX_BYTE_FIELD(
+	    ((efx_byte_t *)origin)[CFG_BOARD_REV_REG_SF_OFST],
+	    BOARD_REV_MINOR);
+	enp->en_u.falcon.enu_board_rev = (major << 4) | minor;
+
+	/* Sram mode */
+	owordp = (efx_oword_t *)(origin + NIC_STAT_SF_OFST);
+	enp->en_u.falcon.enu_internal_sram =
+	    EFX_OWORD_FIELD(*owordp, FRF_AB_ONCHIP_SRAM) != 0;
+	if (enp->en_u.falcon.enu_internal_sram) {
+		enp->en_u.falcon.enu_sram_num_bank = 0;
+		enp->en_u.falcon.enu_sram_bank_size = 0;
+
+		/* Resource limits */
+		encp->enc_evq_limit = 64;	/* Interrupt-capable */
+		encp->enc_txq_limit = 512;
+		encp->enc_rxq_limit = 384;
+		encp->enc_buftbl_limit = 4096;
+	} else {
+		uint32_t sram_rows;
+
+		owordp = (efx_oword_t *)(origin + SRAM_CFG_SF_OFST);
+		enp->en_u.falcon.enu_sram_num_bank =
+		    (uint8_t)EFX_OWORD_FIELD(*owordp, FRF_AZ_SRM_NUM_BANK);
+		enp->en_u.falcon.enu_sram_bank_size =
+		    (uint8_t)EFX_OWORD_FIELD(*owordp, FRF_AZ_SRM_BANK_SIZE);
+		sram_rows = (enp->en_u.falcon.enu_sram_num_bank + 1)
+		    << (18 + enp->en_u.falcon.enu_sram_bank_size);
+
+		/* Resource limits */
+		encp->enc_evq_limit = 64;	/* Interrupt-capable */
+		encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
+		encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
+		encp->enc_buftbl_limit = sram_rows -
+		    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE) +
+		    encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
+	}
+
+	encp->enc_clk_mult = 1;
+	encp->enc_evq_timer_quantum_ns =
+		EFX_EVQ_FALCON_TIMER_QUANTUM_NS / encp->enc_clk_mult;
+	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
+		FRF_AB_TIMER_VAL_WIDTH) / 1000;
+
+	/* Determine system monitor configuration */
+	switch (encp->enc_board_type) {
+#if EFSYS_OPT_MON_LM87
+	case BOARD_TYPE_SFE4002_DECODE:
+	case BOARD_TYPE_SFE4003_DECODE:
+	case BOARD_TYPE_SFE4005_DECODE:
+	case BOARD_TYPE_SFN4112F_DECODE:
+		encp->enc_mon_type = EFX_MON_LM87;
+		enp->en_u.falcon.enu_mon_devid = LM87_DEVID;
+#if EFSYS_OPT_MON_STATS
+		encp->enc_mon_stat_mask = LM87_STAT_MASK;
+#endif
+		break;
+#endif	/* EFSYS_OPT_MON_LM87 */
+
+#if EFSYS_OPT_MON_MAX6647
+	case BOARD_TYPE_SFE4001_DECODE:
+		encp->enc_mon_type = EFX_MON_MAX6647;
+		enp->en_u.falcon.enu_mon_devid = MAX6647_DEVID;
+#if EFSYS_OPT_MON_STATS
+		encp->enc_mon_stat_mask = MAX6647_STAT_MASK;
+#endif
+		break;
+#endif	/* EFSYS_OPT_MON_MAX6647 */
+
+#if EFSYS_OPT_MON_MAX6647
+	case BOARD_TYPE_SFN4111T_DECODE:
+		encp->enc_mon_type = EFX_MON_MAX6647;
+#if EFSYS_OPT_MON_STATS
+		encp->enc_mon_stat_mask = MAX6647_STAT_MASK;
+#endif
+		/*
+		 * MAX6646 chips are identical to MAX6647 chips in every way
+		 * that matters to the driver so we pretend that the chip
+		 * is always a MAX6647, but adjust the identifier accordingly
+		 */
+		enp->en_u.falcon.enu_mon_devid = (major == 0 && minor < 5) ?
+		    MAX6647_DEVID : MAX6646_DEVID;
+		break;
+#endif	/* EFSYS_OPT_MON_MAX6647 */
+
+	default:
+		encp->enc_mon_type = EFX_MON_NULL;
+		enp->en_u.falcon.enu_mon_devid = 0;
+#if EFSYS_OPT_MON_STATS
+		encp->enc_mon_stat_mask = 0;
+#endif
+		break;
+	}
+
+	/* Copy the feature flags */
+	encp->enc_features = enp->en_features;
+
+	/* Read PHY MII prt and type, and mac address */
+	encp->enc_port = EFX_BYTE_FIELD(
+		((efx_byte_t *)origin)[CFG_PHY_PORT_REG_SF_OFST], EFX_BYTE_0);
+	encp->enc_phy_type = EFX_BYTE_FIELD(
+		((efx_byte_t *)origin)[CFG_PHY_TYPE_REG_SF_OFST], EFX_BYTE_0);
+
+	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, origin + MAC_ADDRESS_SF_OFST);
+
+	/* Populate phy capabalities */
+	EFX_STATIC_ASSERT(EFX_PHY_NULL == PHY_TYPE_NONE_DECODE);
+	EFX_STATIC_ASSERT(EFX_PHY_TXC43128 == PHY_TYPE_TXC43128_DECODE);
+	EFX_STATIC_ASSERT(EFX_PHY_SFX7101 == PHY_TYPE_SFX7101_DECODE);
+	EFX_STATIC_ASSERT(EFX_PHY_QT2022C2 == PHY_TYPE_QT2022C2_DECODE);
+	EFX_STATIC_ASSERT(EFX_PHY_SFT9001A == PHY_TYPE_SFT9001A_DECODE);
+	EFX_STATIC_ASSERT(EFX_PHY_QT2025C == PHY_TYPE_QT2025C_DECODE);
+	EFX_STATIC_ASSERT(EFX_PHY_SFT9001B == PHY_TYPE_SFT9001B_DECODE);
+
+	switch (encp->enc_phy_type) {
+#if EFSYS_OPT_PHY_NULL
+	case PHY_TYPE_NONE_DECODE:
+		epp->ep_fixed_port_type = EFX_PHY_MEDIA_XAUI;
+		epp->ep_default_adv_cap_mask = NULLPHY_ADV_CAP_MASK;
+		epp->ep_phy_cap_mask =
+			NULLPHY_ADV_CAP_MASK | NULLPHY_ADV_CAP_PERM;
+#if EFSYS_OPT_NAMES
+		(void) strncpy(encp->enc_phy_name, "nullphy",
+		    sizeof (encp->enc_phy_name));
+#endif	/* EFSYS_OPT_NAMES */
+#if EFSYS_OPT_PHY_LED_CONTROL
+		encp->enc_led_mask = NULLPHY_LED_MASK;
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+#if EFSYS_OPT_LOOPBACK
+		encp->enc_loopback_types[EFX_LINK_10000FDX] =
+		    NULLPHY_LOOPBACK_MASK;
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_PHY_STATS
+		encp->enc_phy_stat_mask = NULLPHY_STAT_MASK;
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+		encp->enc_phy_nprops = NULLPHY_NPROPS;
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+		encp->enc_bist_mask = NULLPHY_BIST_MASK;
+#endif	/* EFSYS_OPT_PHY_BIST */
+		break;
+#endif	/* EFSYS_OPT_PHY_NULL */
+
+#if EFSYS_OPT_PHY_QT2022C2
+	case PHY_TYPE_QT2022C2_DECODE:
+		epp->ep_fixed_port_type = EFX_PHY_MEDIA_XFP;
+		epp->ep_default_adv_cap_mask = QT2022C2_ADV_CAP_MASK;
+		epp->ep_phy_cap_mask =
+			QT2022C2_ADV_CAP_MASK | QT2022C2_ADV_CAP_PERM;
+#if EFSYS_OPT_NAMES
+		(void) strncpy(encp->enc_phy_name, "qt2022c2",
+		    sizeof (encp->enc_phy_name));
+#endif	/* EFSYS_OPT_NAMES */
+#if EFSYS_OPT_PHY_LED_CONTROL
+		encp->enc_led_mask = QT2022C2_LED_MASK;
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+#if EFSYS_OPT_LOOPBACK
+		encp->enc_loopback_types[EFX_LINK_10000FDX] =
+		    QT2022C2_LOOPBACK_MASK;
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_PHY_STATS
+		encp->enc_phy_stat_mask = QT2022C2_STAT_MASK;
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+		encp->enc_phy_nprops = QT2022C2_NPROPS;
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+		encp->enc_bist_mask = QT2022C2_BIST_MASK;
+#endif	/* EFSYS_OPT_PHY_BIST */
+		break;
+#endif	/* EFSYS_OPT_PHY_QT2022C2 */
+
+#if EFSYS_OPT_PHY_SFX7101
+	case PHY_TYPE_SFX7101_DECODE:
+		epp->ep_fixed_port_type = EFX_PHY_MEDIA_BASE_T;
+		epp->ep_default_adv_cap_mask = SFX7101_ADV_CAP_MASK;
+		epp->ep_phy_cap_mask =
+			SFX7101_ADV_CAP_MASK | SFX7101_ADV_CAP_PERM;
+#if EFSYS_OPT_NAMES
+		(void) strncpy(encp->enc_phy_name, "sfx7101",
+		    sizeof (encp->enc_phy_name));
+#endif	/* EFSYS_OPT_NAMES */
+#if EFSYS_OPT_PHY_LED_CONTROL
+		encp->enc_led_mask = SFX7101_LED_MASK;
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+#if EFSYS_OPT_LOOPBACK
+		encp->enc_loopback_types[EFX_LINK_10000FDX] =
+		    SFX7101_LOOPBACK_MASK;
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_PHY_STATS
+		encp->enc_phy_stat_mask = SFX7101_STAT_MASK;
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+		encp->enc_phy_nprops = SFX7101_NPROPS;
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+		encp->enc_bist_mask = SFX7101_BIST_MASK;
+#endif	/* EFSYS_OPT_PHY_BIST */
+		break;
+#endif	/* EFSYS_OPT_PHY_SFX7101 */
+
+#if EFSYS_OPT_PHY_TXC43128
+	case PHY_TYPE_TXC43128_DECODE:
+		epp->ep_fixed_port_type = EFX_PHY_MEDIA_CX4;
+		epp->ep_default_adv_cap_mask = TXC43128_ADV_CAP_MASK;
+		epp->ep_phy_cap_mask =
+			TXC43128_ADV_CAP_MASK | TXC43128_ADV_CAP_PERM;
+#if EFSYS_OPT_NAMES
+		(void) strncpy(encp->enc_phy_name, "txc43128",
+		    sizeof (encp->enc_phy_name));
+#endif	/* EFSYS_OPT_NAMES */
+#if EFSYS_OPT_PHY_LED_CONTROL
+		encp->enc_led_mask = TXC43128_LED_MASK;
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+#if EFSYS_OPT_LOOPBACK
+		encp->enc_loopback_types[EFX_LINK_10000FDX] =
+		    TXC43128_LOOPBACK_MASK;
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_PHY_STATS
+		encp->enc_phy_stat_mask = TXC43128_STAT_MASK;
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+		encp->enc_phy_nprops = TXC43128_NPROPS;
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+		encp->enc_bist_mask = TXC43128_BIST_MASK;
+#endif	/* EFSYS_OPT_PHY_BIST */
+		break;
+#endif	/* EFSYS_OPT_PHY_TXC43128 */
+
+#if EFSYS_OPT_PHY_SFT9001
+	case PHY_TYPE_SFT9001A_DECODE:
+	case PHY_TYPE_SFT9001B_DECODE:
+		epp->ep_fixed_port_type = EFX_PHY_MEDIA_BASE_T;
+		epp->ep_default_adv_cap_mask = SFT9001_ADV_CAP_MASK;
+		epp->ep_phy_cap_mask =
+			SFT9001_ADV_CAP_MASK | SFT9001_ADV_CAP_PERM;
+#if EFSYS_OPT_NAMES
+		(void) strncpy(encp->enc_phy_name, "sft9001",
+		    sizeof (encp->enc_phy_name));
+#endif	/* EFSYS_OPT_NAMES */
+#if EFSYS_OPT_PHY_LED_CONTROL
+		encp->enc_led_mask = SFT9001_LED_MASK;
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+#if EFSYS_OPT_LOOPBACK
+		encp->enc_loopback_types[EFX_LINK_10000FDX] =
+		    SFT9001_10G_LOOPBACK_MASK;
+		encp->enc_loopback_types[EFX_LINK_1000FDX] =
+		    SFT9001_1G_LOOPBACK_MASK;
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_PHY_STATS
+		encp->enc_phy_stat_mask = SFT9001_STAT_MASK;
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+		encp->enc_phy_nprops = SFT9001_NPROPS;
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+		encp->enc_bist_mask = SFT9001_BIST_MASK;
+#endif	/* EFSYS_OPT_PHY_BIST */
+		break;
+#endif	/* EFSYS_OPT_PHY_SFT9001 */
+
+#if EFSYS_OPT_PHY_QT2025C
+	case EFX_PHY_QT2025C:
+		epp->ep_fixed_port_type = EFX_PHY_MEDIA_SFP_PLUS;
+		epp->ep_default_adv_cap_mask = QT2025C_ADV_CAP_MASK;
+		epp->ep_phy_cap_mask =
+			QT2025C_ADV_CAP_MASK | QT2025C_ADV_CAP_PERM;
+#if EFSYS_OPT_NAMES
+		(void) strncpy(encp->enc_phy_name, "qt2025c",
+		    sizeof (encp->enc_phy_name));
+#endif	/* EFSYS_OPT_NAMES */
+#if EFSYS_OPT_PHY_LED_CONTROL
+		encp->enc_led_mask = QT2025C_LED_MASK;
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+#if EFSYS_OPT_LOOPBACK
+		encp->enc_loopback_types[EFX_LINK_10000FDX] =
+		    QT2025C_LOOPBACK_MASK;
+#endif	/* EFSYS_OPT_LOOPBACK */
+#if EFSYS_OPT_PHY_STATS
+		encp->enc_phy_stat_mask = QT2025C_STAT_MASK;
+#endif	/* EFSYS_OPT_PHY_STATS */
+#if EFSYS_OPT_PHY_PROPS
+		encp->enc_phy_nprops = QT2025C_NPROPS;
+#endif	/* EFSYS_OPT_PHY_PROPS */
+#if EFSYS_OPT_PHY_BIST
+		encp->enc_bist_mask = QT2025C_BIST_MASK;
+#endif	/* EFSYS_OPT_PHY_BIST */
+		break;
+#endif	/* EFSYS_OPT_PHY_QT2025C */
+
+	default:
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+#if EFSYS_OPT_LOOPBACK
+	encp->enc_loopback_types[EFX_LINK_UNKNOWN] =
+	    (1 << EFX_LOOPBACK_OFF) |
+	    encp->enc_loopback_types[EFX_LINK_1000FDX] |
+	    encp->enc_loopback_types[EFX_LINK_10000FDX];
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_PCIE_TUNE
+
+static			void
+falcon_nic_pcie_core_read(
+	__in		efx_nic_t *enp,
+	__in		uint32_t addr,
+	__out		efx_dword_t *edp)
+{
+	int lstate;
+	efx_oword_t oword;
+	uint32_t val;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFSYS_LOCK(enp->en_eslp, lstate);
+
+	EFX_POPULATE_OWORD_2(oword, FRF_BB_PCIE_CORE_TARGET_REG_ADRS, addr,
+	    FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR, 0);
+	EFX_BAR_WRITEO(enp, FR_BB_PCIE_CORE_INDIRECT_REG, &oword);
+
+	EFSYS_SPIN(10);
+
+	EFX_BAR_READO(enp, FR_BB_PCIE_CORE_INDIRECT_REG, &oword);
+	val = EFX_OWORD_FIELD(oword, FRF_BB_PCIE_CORE_TARGET_DATA);
+
+	EFX_POPULATE_DWORD_1(*edp, EFX_DWORD_0, val);
+
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+}
+
+static 			void
+falcon_nic_pcie_core_write(
+	__in		efx_nic_t *enp,
+	__in		uint32_t addr,
+	__out		efx_dword_t *edp)
+{
+	int lstate;
+	efx_oword_t oword;
+	uint32_t val;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFSYS_LOCK(enp->en_eslp, lstate);
+
+	val = EFX_DWORD_FIELD(*edp, EFX_DWORD_0);
+
+	EFX_POPULATE_OWORD_3(oword, FRF_BB_PCIE_CORE_TARGET_REG_ADRS, addr,
+	    FRF_BB_PCIE_CORE_TARGET_DATA, val,
+	    FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR, 0);
+	EFX_BAR_WRITEO(enp, FR_BB_PCIE_CORE_INDIRECT_REG, &oword);
+
+	EFSYS_UNLOCK(enp->en_eslp, lstate);
+}
+#endif	/* EFSYS_OPT_PCIE_TUNE || EFSYS_OPT_DIAG */
+
+#if EFSYS_OPT_PCIE_TUNE
+
+typedef struct falcon_pcie_rpl_s {
+	size_t		fpr_tlp_size;
+	uint32_t	fpr_value[4];
+} falcon_pcie_rpl_t;
+
+/*  TLP		1x	2x	4x	8x */
+static falcon_pcie_rpl_t	__cs falcon_nic_pcie_rpl[] = {
+	{ 128,	{ 421,	257,	174,	166 } },
+	{ 256,	{ 698,	391,	241,	225 } },
+	{ 512,	{ 903,	498,	295,	193 } },
+	{ 1024,	{ 1670,	881,	487,	290 } }
+};
+
+static			void
+falcon_nic_pcie_rpl_tl_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int nlanes)
+{
+	uint32_t index;
+	uint32_t current;
+	falcon_pcie_rpl_t *fprp;
+	uint32_t expected;
+	efx_dword_t dword;
+
+	EFSYS_ASSERT3U(nlanes, >, 0);
+	EFSYS_ASSERT3U(nlanes, <=, 8);
+	EFSYS_ASSERT(ISP2(nlanes));
+
+	/* Get the appropriate set of replay timer values */
+	falcon_nic_pcie_core_read(enp, PCR_AB_DEV_CTL_REG, &dword);
+
+	index = EFX_DWORD_FIELD(dword, PCRF_AZ_MAX_PAYL_SIZE);
+	if (index >= 4) {
+		EFSYS_PROBE1(fail1, int, EIO);
+		return;
+	}
+
+	fprp = (falcon_pcie_rpl_t *)&(falcon_nic_pcie_rpl[index]);
+
+	EFSYS_PROBE1(pcie_tlp_size, size_t, fprp->fpr_tlp_size);
+
+	for (index = 0; index < 4; index++)
+		if ((1 << index) == nlanes)
+			break;
+
+	/* Get the current replay timer value */
+	falcon_nic_pcie_core_read(enp, PCR_AC_ACK_LAT_TMR_REG, &dword);
+	current = EFX_DWORD_FIELD(dword, PCRF_AC_RT);
+
+	/* Get the appropriate replay timer value from the set */
+	expected = fprp->fpr_value[index];
+
+	EFSYS_PROBE2(pcie_rpl_tl, uint32_t, current, uint32_t, expected);
+
+	EFSYS_PROBE1(pcie_ack_tl,
+	    uint32_t, EFX_DWORD_FIELD(dword, PCRF_AC_ALT));
+
+	if (expected > current) {
+		EFX_SET_DWORD_FIELD(dword, PCRF_AC_RT, expected);
+		falcon_nic_pcie_core_write(enp, PCR_AC_ACK_LAT_TMR_REG,
+		    &dword);
+	}
+}
+
+static			void
+falcon_nic_pcie_ack_freq_set(
+	__in		efx_nic_t *enp,
+	__in		uint32_t freq)
+{
+	efx_dword_t dword;
+
+	falcon_nic_pcie_core_read(enp, PCR_AC_ACK_FREQ_REG, &dword);
+
+	EFSYS_PROBE2(pcie_ack_freq,
+	    uint32_t, EFX_DWORD_FIELD(dword, PCRF_AC_ACK_FREQ),
+	    uint32_t, freq);
+
+	/* Set to zero to ensure that we always ACK after timeout */
+	EFX_SET_DWORD_FIELD(dword, PCRF_AC_ACK_FREQ, freq);
+	falcon_nic_pcie_core_write(enp, PCR_AC_ACK_FREQ_REG, &dword);
+}
+
+			int
+falcon_nic_pcie_tune(
+	__in		efx_nic_t *enp,
+	__in		unsigned int nlanes)
+{
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	enp->en_u.falcon.enu_nlanes = nlanes;
+	return (0);
+}
+
+#endif	/* EFSYS_OPT_PCIE_TUNE */
+
+	__checkReturn	int
+falcon_nic_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	falcon_i2c_t *fip = &(enp->en_u.falcon.enu_fip);
+	efx_oword_t oword;
+	unsigned int count;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	/* Check the reset register */
+	EFX_BAR_READO(enp, FR_AB_GLB_CTL_REG, &oword);
+
+	/* Select units for reset */
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_CS, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_TX, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_XGTX, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_RX, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_XGRX, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_SR, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_EV, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_EM, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_PCIE_STKY, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_BB_RST_BIU, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_XAUI_SD, 1);
+
+	/* Initiate reset */
+	EFX_BAR_WRITEO(enp, FR_AB_GLB_CTL_REG, &oword);
+
+	/* Wait for the reset to complete */
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 10 us */
+		EFSYS_SPIN(10);
+
+		/* Test for reset complete */
+		EFX_BAR_READO(enp, FR_AB_GLB_CTL_REG, &oword);
+		if (EFX_OWORD_FIELD(oword, FRF_AB_RST_CS) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_TX) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_XGTX) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_RX) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_XGRX) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_SR) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_EV) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_EM) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_PCIE_STKY) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_BB_RST_BIU) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_XAUI_SD) == 0)
+			goto done;
+	} while (++count < 1000);
+
+	rc = ETIMEDOUT;
+	goto fail1;
+
+done:
+	/* GPIO initialization */
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+
+	/* Set I2C SCL to 1 */
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO0_OUT, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO0_OEN, 1);
+
+	/* Select external 1G MAC clock if it is available */
+	EFX_SET_OWORD_FIELD(oword, FRF_BB_USE_NIC_CLK,
+	    (encp->enc_board_type == BOARD_TYPE_SFN4111T_DECODE));
+
+	EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
+
+	fip->fi_sda = B_TRUE;
+	fip->fi_scl = B_TRUE;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static			void
+falcon_nic_timer_tbl_watchdog(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+
+	if (enp->en_family != EFX_FAMILY_FALCON)
+		return;
+
+	/*
+	 * Ensure that PCI writes to the event queue read pointers are spaced
+	 * out far enough to avoid write loss.
+	 */
+	EFX_BAR_READO(enp, FR_AZ_HW_INIT_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_POST_WR_MASK, 0xf);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_WD_TIMER, 0x10);
+	EFX_BAR_WRITEO(enp, FR_AZ_HW_INIT_REG, &oword);
+}
+
+static			void
+falcon_rx_reset_recovery_enable(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+
+	/*
+	 * Set number of channels for receive path and also set filter table
+	 * search limits to 8, to reduce the frequency of RX_RECOVERY events
+	 */
+	EFX_POPULATE_OWORD_4(oword,
+				FRF_AZ_UDP_FULL_SRCH_LIMIT, 8,
+				FRF_AZ_UDP_WILD_SRCH_LIMIT, 8,
+				FRF_AZ_TCP_FULL_SRCH_LIMIT, 8,
+				FRF_AZ_TCP_WILD_SRCH_LIMIT, 8);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
+
+	/*
+	 * Enable RX Self-Reset functionality.
+	 * Disable ISCSI digest to reduce RX_RECOVERY frequency
+	 */
+	EFX_BAR_READO(enp, FR_AZ_RX_SELF_RST_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_ISCSI_DIS, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RX_SW_RST_REG, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_SELF_RST_REG, &oword);
+}
+
+	__checkReturn	int
+falcon_nic_init(
+	__in		efx_nic_t *enp)
+{
+	int rc;
+
+	if ((rc = falcon_sram_init(enp)) != 0)
+		goto fail1;
+
+#if EFSYS_OPT_PCIE_TUNE
+	/* Tune up the PCIe core */
+	if (enp->en_u.falcon.enu_nlanes > 0) {
+		falcon_nic_pcie_rpl_tl_set(enp, enp->en_u.falcon.enu_nlanes);
+		falcon_nic_pcie_ack_freq_set(enp, 0);
+	}
+#endif
+	/* Fix NMI's due to premature timer_tbl biu watchdog */
+	falcon_nic_timer_tbl_watchdog(enp);
+
+	/* Enable RX_RECOVERY feature */
+	falcon_rx_reset_recovery_enable(enp);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+falcon_nic_mac_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	unsigned int count;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFX_BAR_READO(enp, FR_AB_MAC_CTRL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_BB_TXFIFO_DRAIN_EN, 1);
+	EFX_BAR_WRITEO(enp, FR_AB_MAC_CTRL_REG, &oword);
+
+	/* Reset the MAC and EM units */
+	EFX_BAR_READO(enp, FR_AB_GLB_CTL_REG, &oword);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_EM, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_XGRX, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_RST_XGTX, 1);
+
+	/* Initiate reset */
+	EFX_BAR_WRITEO(enp, FR_AB_GLB_CTL_REG, &oword);
+
+	/* Wait for the reset to complete */
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 10 us */
+		EFSYS_SPIN(10);
+
+		/* Test for reset complete */
+		EFX_BAR_READO(enp, FR_AB_GLB_CTL_REG, &oword);
+		if (EFX_OWORD_FIELD(oword, FRF_AB_RST_EM) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_XGRX) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_RST_XGTX) == 0)
+			goto done;
+	} while (++count < 1000);
+
+	rc = ETIMEDOUT;
+	goto fail1;
+
+done:
+	enp->en_reset_flags |= EFX_RESET_MAC;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+	return (rc);
+}
+
+			void
+falcon_nic_phy_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	int state;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	/* Set PHY_RSTn to 0 */
+	EFSYS_LOCK(enp->en_eslp, state);
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO2_OUT, 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO2_OEN, 1);
+	EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	EFSYS_SLEEP(500000);
+
+	EFSYS_LOCK(enp->en_eslp, state);
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO2_OEN, 0);
+	EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	EFSYS_SLEEP(100000);
+
+	enp->en_reset_flags |= EFX_RESET_PHY;
+}
+
+			void
+falcon_nic_fini(
+	__in		efx_nic_t *enp)
+{
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+#if EFSYS_OPT_PCIE_TUNE
+	falcon_nic_pcie_ack_freq_set(enp, 1);
+#endif	/* EFSYS_OPT_PCIE_TUNE */
+
+	falcon_sram_fini(enp);
+}
+
+			void
+falcon_nic_unprobe(
+	__in		efx_nic_t *enp)
+{
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	falcon_nvram_fini(enp);
+}
+
+#if EFSYS_OPT_DIAG
+
+static efx_register_set_t __cs	__falcon_b0_registers[] = {
+	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
+	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
+	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
+	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
+	{ FR_AB_MAC_CTRL_REG_OFST, 0, 1 },
+	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
+	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
+	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
+	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
+	{ FR_AB_GM_CFG2_REG_OFST, 0, 1 },
+	{ FR_AB_GMF_CFG0_REG_OFST, 0, 1 },
+	{ FR_AB_XM_GLB_CFG_REG_OFST, 0, 1 },
+	{ FR_AB_XM_TX_CFG_REG_OFST, 0, 1 },
+	{ FR_AB_XM_RX_CFG_REG_OFST, 0, 1 },
+	{ FR_AB_XM_RX_PARAM_REG_OFST, 0, 1 },
+	{ FR_AB_XM_FC_REG_OFST, 0, 1 },
+	{ FR_AB_XM_ADR_LO_REG_OFST, 0, 1 },
+	{ FR_AB_XX_SD_CTL_REG_OFST, 0, 1 },
+};
+
+static const uint32_t __cs	__falcon_b0_register_masks[] = {
+	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
+	0xFFFFFFFE, 0x00017FFF, 0x00000000, 0x00000000,
+	0x7FFF0037, 0x00000000, 0x00000000, 0x00000000,
+	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
+	0xFFFF0000, 0x00000000, 0x00000000, 0x00000000,
+	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
+	0x0000000F, 0x00000000, 0x00000000, 0x00000000,
+	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
+	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
+	0x00007337, 0x00000000, 0x00000000, 0x00000000,
+	0x00001F1F, 0x00000000, 0x00000000, 0x00000000,
+	0x00000C68, 0x00000000, 0x00000000, 0x00000000,
+	0x00080164, 0x00000000, 0x00000000, 0x00000000,
+	0x07100A0C, 0x00000000, 0x00000000, 0x00000000,
+	0x00001FF8, 0x00000000, 0x00000000, 0x00000000,
+	0xFFFF0001, 0x00000000, 0x00000000, 0x00000000,
+	0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000,
+	0x0003FF0F, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static efx_register_set_t __cs	__falcon_b0_tables[] = {
+	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
+	    FR_AZ_RX_FILTER_TBL0_ROWS },
+	{ FR_AB_RX_FILTER_TBL1_OFST, FR_AB_RX_FILTER_TBL1_STEP,
+	    FR_AB_RX_FILTER_TBL1_ROWS },
+	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
+	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_AB_RX_DESC_PTR_TBL_ROWS },
+	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
+	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_AB_TX_DESC_PTR_TBL_ROWS },
+};
+
+static const uint32_t __cs	__falcon_b0_table_masks[] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
+	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
+	0x3FFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
+};
+
+	__checkReturn	int
+falcon_nic_register_test(
+	__in		efx_nic_t *enp)
+{
+	efx_register_set_t *rsp;
+	const uint32_t *dwordp;
+	unsigned int nitems;
+	unsigned int count;
+	int rc;
+
+	/* Fill out the register mask entries */
+	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__falcon_b0_register_masks)
+		    == EFX_ARRAY_SIZE(__falcon_b0_registers) * 4);
+
+	nitems = EFX_ARRAY_SIZE(__falcon_b0_registers);
+	dwordp = __falcon_b0_register_masks;
+	for (count = 0; count < nitems; ++count) {
+		rsp = __falcon_b0_registers + count;
+		rsp->mask.eo_u32[0] = *dwordp++;
+		rsp->mask.eo_u32[1] = *dwordp++;
+		rsp->mask.eo_u32[2] = *dwordp++;
+		rsp->mask.eo_u32[3] = *dwordp++;
+	}
+
+	/* Fill out the register table entries */
+	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__falcon_b0_table_masks)
+		    == EFX_ARRAY_SIZE(__falcon_b0_tables) * 4);
+
+	nitems = EFX_ARRAY_SIZE(__falcon_b0_tables);
+	dwordp = __falcon_b0_table_masks;
+	for (count = 0; count < nitems; ++count) {
+		rsp = __falcon_b0_tables + count;
+		rsp->mask.eo_u32[0] = *dwordp++;
+		rsp->mask.eo_u32[1] = *dwordp++;
+		rsp->mask.eo_u32[2] = *dwordp++;
+		rsp->mask.eo_u32[3] = *dwordp++;
+	}
+
+	if ((rc = efx_nic_test_registers(enp, __falcon_b0_registers,
+	    EFX_ARRAY_SIZE(__falcon_b0_registers))) != 0)
+		goto fail1;
+
+	if ((rc = efx_nic_test_tables(enp, __falcon_b0_tables,
+	    EFX_PATTERN_BYTE_ALTERNATE,
+	    EFX_ARRAY_SIZE(__falcon_b0_tables))) != 0)
+		goto fail2;
+
+	if ((rc = efx_nic_test_tables(enp, __falcon_b0_tables,
+	    EFX_PATTERN_BYTE_CHANGING,
+	    EFX_ARRAY_SIZE(__falcon_b0_tables))) != 0)
+		goto fail3;
+
+	if ((rc = efx_nic_test_tables(enp, __falcon_b0_tables,
+	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__falcon_b0_tables))) != 0)
+		goto fail4;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_DIAG */
+
+#endif	/* EFSYS_OPT_FALCON */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_nvram.c	2013-08-22 18:57:30.291376576 -0400
@@ -0,0 +1,841 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "falcon_nvram.h"
+#include "efx_types.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_FALCON
+
+#if EFSYS_OPT_MON_LM87
+#include "lm87.h"
+#endif
+
+#if EFSYS_OPT_MON_MAX6647
+#include "max6647.h"
+#endif
+
+#if EFSYS_OPT_NVRAM_SFX7101
+#include "sfx7101.h"
+#endif
+
+#if EFSYS_OPT_NVRAM_SFT9001
+#include "sft9001.h"
+#endif
+
+#define	FALCON_NVRAM_INIT_LOWEST_REG				\
+	MIN(CFG_VERSION_REG_SF_OFST,				\
+	    MIN(CFG_FLASH_DEV_REG_SF_OFST,			\
+		CFG_EEPROM_DEV_REG_SF_OFST))
+
+#define	FALCON_NVRAM_INIT_HIGHEST_REG    			\
+	MAX(CFG_VERSION_REG_SF_OFST,				\
+	    MAX(CFG_FLASH_DEV_REG_SF_OFST,			\
+		CFG_EEPROM_DEV_REG_SF_OFST))
+
+#define	FALCON_NVRAM_INIT_NEEDED_CFG_SIZE 			\
+	(FALCON_NVRAM_INIT_HIGHEST_REG + sizeof (efx_oword_t) 	\
+	    - FALCON_NVRAM_INIT_LOWEST_REG)
+
+	__checkReturn	int
+falcon_nvram_init(
+	__in		efx_nic_t *enp)
+{
+	falcon_spi_dev_t *fsdp;
+	efx_oword_t oword;
+	uint16_t version;
+	int rc;
+	uint8_t cfg[FALCON_NVRAM_INIT_NEEDED_CFG_SIZE];
+	uint8_t *origin = cfg - FALCON_NVRAM_INIT_LOWEST_REG;
+
+	/* All boards have flash and EEPROM */
+	EFX_BAR_READO(enp, FR_AB_NIC_STAT_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_SF_PRST, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_EE_PRST, 1);
+	EFX_BAR_WRITEO(enp, FR_AB_NIC_STAT_REG, &oword);
+
+	/* Set up partial flash parameters */
+	fsdp = &(enp->en_u.falcon.enu_fsd[FALCON_SPI_FLASH]);
+	fsdp->fsd_sf_sel = 1;
+	fsdp->fsd_adbcnt = 3;
+	fsdp->fsd_munge = B_FALSE;
+
+	if ((rc = falcon_nic_cfg_raw_read_verify(enp,
+	    FALCON_NVRAM_INIT_LOWEST_REG,
+	    FALCON_NVRAM_INIT_NEEDED_CFG_SIZE, cfg)) != 0)
+		goto fail1;
+
+	version = EFX_WORD_FIELD(
+		*(efx_word_t *)(origin + CFG_VERSION_REG_SF_OFST), VERSION);
+
+	if (version < 3) {
+		fsdp->fsd_size = (size_t)1 << 17;
+		fsdp->fsd_erase_cmd = 0x52;
+		fsdp->fsd_erase_size = (size_t)1 << 15;
+		fsdp->fsd_write_size = (size_t)1 << 8;
+	} else {
+		efx_dword_t *dwordp =
+			(efx_dword_t *)(origin + CFG_FLASH_DEV_REG_SF_OFST);
+
+		if (EFX_DWORD_FIELD(*dwordp, SPI_DEV_ADBCNT) != 3 ||
+		    EFX_DWORD_FIELD(*dwordp, SPI_DEV_SIZE) >= 24) {
+			rc = EINVAL;
+			goto fail2;
+		}
+
+		fsdp->fsd_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
+		    SPI_DEV_SIZE);
+		fsdp->fsd_erase_cmd = EFX_DWORD_FIELD(*dwordp,
+					    SPI_DEV_ERASE_CMD);
+		fsdp->fsd_erase_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
+		    SPI_DEV_ERASE_SIZE);
+		fsdp->fsd_write_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
+		    SPI_DEV_WRITE_SIZE);
+	}
+
+	/* Configure the EEPROM */
+	fsdp = &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
+
+	fsdp->fsd_sf_sel = 0;
+	if (version < 3) {
+		fsdp->fsd_adbcnt = 1;
+		fsdp->fsd_size = (size_t)1 << 9;
+		fsdp->fsd_munge = B_TRUE;
+		fsdp->fsd_erase_cmd = 0;
+		fsdp->fsd_erase_size = 1;
+		fsdp->fsd_write_size = (size_t)1 << 3;
+	} else {
+		efx_dword_t *dwordp =
+			(efx_dword_t *)(origin + CFG_EEPROM_DEV_REG_SF_OFST);
+
+		fsdp->fsd_adbcnt = EFX_DWORD_FIELD(*dwordp, SPI_DEV_ADBCNT);
+		fsdp->fsd_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
+		    SPI_DEV_SIZE);
+		fsdp->fsd_munge = (EFX_DWORD_FIELD(*dwordp, SPI_DEV_SIZE) >
+		    fsdp->fsd_adbcnt * 8);
+		fsdp->fsd_erase_cmd = EFX_DWORD_FIELD(*dwordp,
+		    SPI_DEV_ERASE_CMD);
+		fsdp->fsd_erase_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
+		    SPI_DEV_ERASE_SIZE);
+		fsdp->fsd_write_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
+		    SPI_DEV_WRITE_SIZE);
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	(void) memset(enp->en_u.falcon.enu_fsd, 0,
+	    sizeof (enp->en_u.falcon.enu_fsd));
+
+	return (rc);
+}
+
+#if EFSYS_OPT_NVRAM
+
+typedef struct falcon_nvram_ops_s {
+	int	(*fnvo_size)(efx_nic_t *, size_t *);
+	int	(*fnvo_get_version)(efx_nic_t *, uint32_t *, uint16_t *);
+	int	(*fnvo_rw_start)(efx_nic_t *, size_t *);
+	int	(*fnvo_read_chunk)(efx_nic_t *, unsigned int,
+		    caddr_t, size_t);
+	int	(*fnvo_erase)(efx_nic_t *);
+	int	(*fnvo_write_chunk)(efx_nic_t *, unsigned int,
+		    caddr_t, size_t);
+	void	(*fnvo_rw_finish)(efx_nic_t *);
+} falcon_nvram_ops_t;
+
+#if EFSYS_OPT_NVRAM_FALCON_BOOTROM
+
+#define	FALCON_GPXE_IMAGE_OFFSET	0x8000
+#define	FALCON_GPXE_IMAGE_SIZE		0x18000
+
+static	__checkReturn		int
+falcon_nvram_bootrom_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT(sizep != NULL);
+	*sizep = FALCON_GPXE_IMAGE_SIZE;
+
+	return (0);
+}
+
+static	__checkReturn		int
+falcon_nvram_bootrom_get_version(
+	__in			efx_nic_t *enp,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4])
+{
+	const char prefix[] = "Solarstorm Boot Manager (v";
+	char buf[16], p;
+	size_t current, needle;
+	uint16_t *versionp;
+	int rc;
+
+	version[0] = version[1] = version[2] = version[3] = 0;
+	versionp = NULL;
+	needle = 0;
+
+	/*
+	 * Search from [current, end) for prefix, and return the
+	 * trailing four decimal number.
+	 */
+	for (current = 0; current < 0x600; current++) {
+		if (current % sizeof (buf) == 0) {
+			if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_FLASH,
+			    FALCON_GPXE_IMAGE_OFFSET + current, buf,
+			    sizeof (buf))) != 0)
+				break;
+		}
+
+		p = buf[current % sizeof (buf)];
+		if (versionp == NULL) {
+			if (prefix[needle] == p) {
+				++needle;
+				if (needle == sizeof (prefix) - 1)
+					versionp = version;
+			} else
+				needle = 0;
+		} else {
+			if (p == ')' && versionp == version + 3)
+				goto done;
+			else if (p >= '0' && p <= '9')
+				*versionp = (*versionp * 10) + (p - '0');
+			else if (p == '.' && versionp != version + 3)
+				++versionp;
+			else
+				/* Invalid format */
+				break;
+		}
+	}
+
+	version[0] = version[1] = version[2] = version[3] = 0;
+
+done:
+	*subtypep = 0;	/* Falcon bootrom is type 0 */
+
+	return (0);
+}
+
+static	__checkReturn		int
+falcon_nvram_bootrom_rw_start(
+	__in			efx_nic_t *enp,
+	__out			size_t *chunk_sizep)
+{
+	_NOTE(ARGUNUSED(enp))
+	if (chunk_sizep != NULL)
+		*chunk_sizep = sizeof (efx_oword_t);
+
+	return (0);
+}
+
+static	__checkReturn		int
+falcon_nvram_bootrom_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	int rc;
+
+	EFSYS_ASSERT3U(size + offset, <=, FALCON_GPXE_IMAGE_SIZE);
+
+	if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_FLASH,
+	    FALCON_GPXE_IMAGE_OFFSET + offset, data, size)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	 __checkReturn		int
+falcon_nvram_bootrom_erase(
+	__in			efx_nic_t *enp)
+{
+	int rc;
+
+	if ((rc = falcon_spi_dev_erase(enp, FALCON_SPI_FLASH,
+	    FALCON_GPXE_IMAGE_OFFSET, FALCON_GPXE_IMAGE_SIZE)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+falcon_nvram_bootrom_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t base,
+	__in			size_t size)
+{
+	int rc;
+
+	if ((rc = falcon_spi_dev_write(enp, FALCON_SPI_FLASH,
+	    FALCON_GPXE_IMAGE_OFFSET + offset, base, size)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static falcon_nvram_ops_t	__cs	__falcon_nvram_bootrom_ops = {
+	falcon_nvram_bootrom_size,		/* fnvo_size */
+	falcon_nvram_bootrom_get_version,	/* fnvo_get_version */
+	falcon_nvram_bootrom_rw_start,		/* fnvo_rw_start */
+	falcon_nvram_bootrom_read_chunk,	/* fnvo_read_chunk */
+	falcon_nvram_bootrom_erase,		/* fnvo_erase */
+	falcon_nvram_bootrom_write_chunk,	/* fnvo_write_chunk */
+	NULL,					/* fnvo_rw_finish */
+};
+
+#define	FALCON_GPXE_CFG_OFFSET		0x800
+
+static	__checkReturn		int
+falcon_nvram_bootrom_cfg_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep)
+{
+	falcon_spi_dev_t *fsdp =
+		&(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
+	int rc;
+
+	EFSYS_ASSERT(sizep != NULL);
+	EFSYS_ASSERT(fsdp != NULL);
+
+	if (fsdp->fsd_size < FALCON_GPXE_CFG_OFFSET) {
+		*sizep = 0;
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	*sizep = fsdp->fsd_size - FALCON_GPXE_CFG_OFFSET;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+falcon_nvram_bootrom_cfg_get_version(
+	__in			efx_nic_t *enp,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4])
+{
+	falcon_spi_dev_t *fsdp =
+		&(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
+	int rc;
+
+	EFSYS_ASSERT(fsdp != NULL);
+	if (fsdp->fsd_size < FALCON_GPXE_CFG_OFFSET) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	/* gpxecfg is not versioned */
+	*subtypep = 0;
+	version[0] = version[1] = version[2] = version[3];
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+falcon_nvram_bootrom_cfg_rw_start(
+	__in			efx_nic_t *enp,
+	__out			size_t *chunk_sizep)
+{
+	falcon_spi_dev_t *fsdp =
+		&(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
+	int rc;
+
+	EFSYS_ASSERT(fsdp != NULL);
+	if (fsdp->fsd_size < FALCON_GPXE_CFG_OFFSET) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (chunk_sizep != NULL)
+		*chunk_sizep = sizeof (efx_oword_t);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+static	__checkReturn		int
+falcon_nvram_bootrom_cfg_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	falcon_spi_dev_t *fsdp =
+		&(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
+	int rc;
+
+	EFSYS_ASSERT(fsdp != NULL);
+	EFSYS_ASSERT3U(fsdp->fsd_size, >=, FALCON_GPXE_CFG_OFFSET);
+	EFSYS_ASSERT3U(offset + size, <=,
+	    fsdp->fsd_size - FALCON_GPXE_CFG_OFFSET);
+
+	if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_EEPROM,
+	    FALCON_GPXE_CFG_OFFSET + offset, data, size)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+falcon_nvram_bootrom_cfg_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t base,
+	__in			size_t size)
+{
+	falcon_spi_dev_t *fsdp =
+		&(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
+	int rc;
+
+	EFSYS_ASSERT(fsdp != NULL);
+	EFSYS_ASSERT3U(fsdp->fsd_size, >=, FALCON_GPXE_CFG_OFFSET);
+	EFSYS_ASSERT3U(offset + size, <=,
+	    fsdp->fsd_size - FALCON_GPXE_CFG_OFFSET);
+
+	if ((rc = falcon_spi_dev_write(enp, FALCON_SPI_EEPROM,
+	    FALCON_GPXE_CFG_OFFSET + offset, base, size)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static falcon_nvram_ops_t	__cs	__falcon_nvram_bootrom_cfg_ops = {
+	falcon_nvram_bootrom_cfg_size,		/* fnvo_size */
+	falcon_nvram_bootrom_cfg_get_version,	/* fnvo_get_version */
+	falcon_nvram_bootrom_cfg_rw_start,	/* fnvo_rw_start */
+	falcon_nvram_bootrom_cfg_read_chunk,	/* fnvo_read_chunk */
+	NULL,					/* fnvo_erase */
+	falcon_nvram_bootrom_cfg_write_chunk,	/* fnvo_write_chunk */
+	NULL,					/* fnvo_rw_finish */
+};
+
+#endif	/* EFSYS_OPT_NVRAM_FALCON_BOOTROM */
+
+#if EFSYS_OPT_NVRAM_SFX7101
+
+static falcon_nvram_ops_t	__cs	__falcon_sfx7101_ops = {
+	sfx7101_nvram_size,		/* fnvo_size */
+	sfx7101_nvram_get_version,	/* fnvo_get_version */
+	sfx7101_nvram_rw_start,		/* fnvo_rw_start */
+	sfx7101_nvram_read_chunk,	/* fnvo_read_chunk */
+	sfx7101_nvram_erase,		/* fnvo_erase */
+	sfx7101_nvram_write_chunk,	/* fnvo_write_chunk */
+	sfx7101_nvram_rw_finish,	/* fnvo_rw_finish */
+};
+
+#endif	/* EFSYS_OPT_NVRAM_SFX7101 */
+
+#if EFSYS_OPT_NVRAM_SFT9001
+
+static falcon_nvram_ops_t	__cs	__falcon_sft9001_ops = {
+	sft9001_nvram_size,		/* fnvo_size */
+	sft9001_nvram_get_version,	/* fnvo_get_version */
+	sft9001_nvram_rw_start,		/* fnvo_rw_start */
+	sft9001_nvram_read_chunk,	/* fnvo_read_chunk */
+	sft9001_nvram_erase,		/* fnvo_erase */
+	sft9001_nvram_write_chunk,	/* fnvo_write_chunk */
+	sft9001_nvram_rw_finish,	/* fnvo_rw_finish */
+};
+
+#endif	/* EFSYS_OPT_NVRAM_SFT9001 */
+
+static	__checkReturn		int
+falcon_nvram_get_ops(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			falcon_nvram_ops_t **fnvopp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	falcon_nvram_ops_t *fnvop;
+	int rc;
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+
+	switch (type) {
+#if EFSYS_OPT_NVRAM_FALCON_BOOTROM
+	case EFX_NVRAM_BOOTROM_CFG:
+		fnvop = (falcon_nvram_ops_t *)&__falcon_nvram_bootrom_cfg_ops;
+		goto done;
+
+	case EFX_NVRAM_BOOTROM:
+		fnvop = (falcon_nvram_ops_t *)&__falcon_nvram_bootrom_ops;
+		goto done;
+#endif
+	case EFX_NVRAM_PHY:
+		switch (encp->enc_phy_type) {
+#if EFSYS_OPT_NVRAM_SFX7101
+		case EFX_PHY_SFX7101:
+			fnvop = (falcon_nvram_ops_t *)&__falcon_sfx7101_ops;
+			goto done;
+#endif	/* EFSYS_OPT_NVRAM_SFX7101 */
+
+#if EFSYS_OPT_NVRAM_SFT9001
+		case EFX_PHY_SFT9001B:
+			fnvop = (falcon_nvram_ops_t *)&__falcon_sft9001_ops;
+			goto done;
+#endif	/* EFSYS_OPT_NVRAM_SFT9001 */
+
+		default:
+			break;
+		}
+
+		break;
+
+	default:
+		break;
+	}
+
+	rc = ENOTSUP;
+	goto fail1;
+
+done:
+	*fnvopp = fnvop;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_DIAG
+
+	__checkReturn		int
+falcon_nvram_test(
+	__in			efx_nic_t *enp)
+{
+	efx_nic_cfg_t enc;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if ((rc = falcon_nic_cfg_build(enp, &enc)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_DIAG */
+
+	__checkReturn		int
+falcon_nvram_size(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *sizep)
+{
+	falcon_nvram_ops_t *fnvop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
+		goto fail1;
+
+	if ((rc = fnvop->fnvo_size(enp, sizep)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4])
+{
+	falcon_nvram_ops_t *fnvop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
+		goto fail1;
+
+	if ((rc = fnvop->fnvo_get_version(enp, subtypep, version)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *chunk_sizep)
+{
+	falcon_nvram_ops_t *fnvop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
+		goto fail1;
+
+	if ((rc = fnvop->fnvo_rw_start(enp, chunk_sizep)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	falcon_nvram_ops_t *fnvop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
+		goto fail1;
+
+	if ((rc = fnvop->fnvo_read_chunk(enp, offset, data, size)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_nvram_erase(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type)
+{
+	falcon_nvram_ops_t *fnvop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
+		goto fail1;
+
+	if (fnvop->fnvo_erase != NULL) {
+		if ((rc = fnvop->fnvo_erase(enp)) != 0)
+			goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_nvram_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	falcon_nvram_ops_t *fnvop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
+		goto fail1;
+
+	if ((rc = fnvop->fnvo_write_chunk(enp, offset, data, size)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+				void
+falcon_nvram_rw_finish(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type)
+{
+	falcon_nvram_ops_t *fnvop;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	rc = falcon_nvram_get_ops(enp, type, &fnvop);
+	EFSYS_ASSERT(rc == 0);
+	if (rc == 0) {
+		if (fnvop->fnvo_rw_finish != NULL)
+			fnvop->fnvo_rw_finish(enp);
+	}
+}
+
+	__checkReturn		int
+falcon_nvram_set_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint16_t version[4])
+{
+	falcon_nvram_ops_t *fnvop;
+	uint32_t subtype;
+	uint16_t old_version[4];
+	int rc;
+
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	/*
+	 * There is no room on Falcon to version anything, so it's
+	 * inferred where possible from the underlying entity.
+	 */
+	if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
+		goto fail1;
+
+	/*
+	 * The user *really should be setting the version correctly
+	 */
+	if ((rc = fnvop->fnvo_get_version(enp, &subtype, old_version)) != 0)
+		goto fail2;
+	EFSYS_ASSERT(memcmp(old_version, version, sizeof (old_version)) == 0);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_NVRAM */
+
+		void
+falcon_nvram_fini(
+	__in	efx_nic_t *enp)
+{
+	(void) memset(&enp->en_u.falcon.enu_fsd, 0,
+	    sizeof (enp->en_u.falcon.enu_fsd));
+}
+
+#endif	/* EFSYS_OPT_FALCON */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_nvram.h	2013-08-22 18:57:30.383373995 -0400
@@ -0,0 +1,143 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_FALCON_NVRAM_H
+#define	_SYS_FALCON_NVRAM_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* PCI subsystem vendor ID */
+#define	PC_SS_VEND_ID_REG_SF_OFST 0x12c
+
+/* PCI subsystem device ID */
+#define	PC_SS_ID_REG_SF_OFST 0x12e
+
+/* PCIe serial number */
+#define	PCI_SN_SF_OFST 0x1c4
+
+/* NVRAM and VPD configuration */
+#define	EE_VPD_CFG0_REG_SF_OFST 0x300
+
+/* MAC address */
+#define	MAC_ADDRESS_SF_OFST 0x310
+
+/* NIC stat */
+#define NIC_STAT_SF_OFST 0x360
+
+/* Sram config */
+#define SRAM_CFG_SF_OFST 0x380
+
+/* Magic number */
+#define	CFG_MAGIC_REG_SF_OFST 0x3a0
+
+#define	MAGIC_LBN 0
+#define	MAGIC_WIDTH 16
+#define	MAGIC_DECODE 0xfa1c
+
+/* Version */
+#define	CFG_VERSION_REG_SF_OFST 0x3a2
+
+#define	VERSION_LBN 0
+#define	VERSION_WIDTH 16
+
+/* Checksum */
+#define	CFG_CKSUM_REG_SF_OFST 0x3a4
+
+#define	CKSUM_LBN 0
+#define	CKSUM_WIDTH 16
+
+/* PHY address */
+#define	CFG_PHY_PORT_REG_SF_OFST 0x3a8
+
+#define	PHY_PORT_LBN 0
+#define	PHY_PORT_WIDTH 8
+#define	PHY_PORT_INVALID_DECODE 0xff
+
+/* PHY type */
+#define	CFG_PHY_TYPE_REG_SF_OFST 0x3a9
+
+#define	PHY_TYPE_LBN 0
+#define	PHY_TYPE_WIDTH 8
+#define	PHY_TYPE_NONE_DECODE 0x00
+#define	PHY_TYPE_TXC43128_DECODE 0x01
+#define	PHY_TYPE_88E1111_DECODE 0x02
+#define	PHY_TYPE_SFX7101_DECODE 0x03
+#define	PHY_TYPE_QT2022C2_DECODE 0x04
+#define	PHY_TYPE_SFT9001A_DECODE 0x08
+#define	PHY_TYPE_QT2025C_DECODE 0x09
+#define	PHY_TYPE_SFT9001B_DECODE 0x0a
+
+/* ASIC revision */
+#define	CFG_ASIC_REV_REG_SF_OFST 0x3ac
+
+#define	ASIC_REV_MINOR_LBN 0
+#define	ASIC_REV_MINOR_WIDTH 8
+#define	ASIC_REV_MAJOR_LBN 8
+#define	ASIC_REV_MAJOR_WIDTH 16
+
+/* Board revision */
+#define	CFG_BOARD_REV_REG_SF_OFST 0x3ae
+
+#define	BOARD_REV_MINOR_LBN 0
+#define	BOARD_REV_MINOR_WIDTH 4
+#define	BOARD_REV_MAJOR_LBN 4
+#define	BOARD_REV_MAJOR_WIDTH 4
+
+/* Board type */
+#define	CFG_BOARD_TYPE_REG_SF_OFST 0x3af
+
+#define	BOARD_TYPE_LBN 0
+#define	BOARD_TYPE_WIDTH 8
+#define	BOARD_TYPE_SFE4001_DECODE 0x01
+#define	BOARD_TYPE_SFE4002_DECODE 0x02
+#define	BOARD_TYPE_SFE4003_DECODE 0x03
+#define	BOARD_TYPE_SFE4005_DECODE 0x04
+#define	BOARD_TYPE_SFN4111T_DECODE 0x51
+#define	BOARD_TYPE_SFN4112F_DECODE 0x52
+
+/* EEPROM information */
+#define	CFG_EEPROM_DEV_REG_SF_OFST 0x3c0
+
+/* FLASH information */
+#define	CFG_FLASH_DEV_REG_SF_OFST 0x3c4
+
+#define	SPI_DEV_SIZE_LBN 0
+#define	SPI_DEV_SIZE_WIDTH 5
+#define	SPI_DEV_ADBCNT_LBN 6
+#define	SPI_DEV_ADBCNT_WIDTH 2
+#define	SPI_DEV_ERASE_CMD_LBN 8
+#define	SPI_DEV_ERASE_CMD_WIDTH 8
+#define	SPI_DEV_ERASE_SIZE_LBN 16
+#define	SPI_DEV_ERASE_SIZE_WIDTH 5
+#define	SPI_DEV_WRITE_SIZE_LBN 24
+#define	SPI_DEV_WRITE_SIZE_WIDTH 5
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_FALCON_NVRAM_H */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_spi.c	2013-08-22 18:57:30.469264727 -0400
@@ -0,0 +1,433 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_FALCON
+
+/* Commands common to all known devices */
+
+#define	SPI_CMD_WRSR 0x01	/* write status register */
+#define	SPI_CMD_WRITE 0x02	/* Write data to memory array */
+#define	SPI_CMD_READ 0x03	/* Read data from memory array */
+#define	SPI_CMD_WRDI 0x04	/* reset write enable latch */
+#define	SPI_CMD_RDSR 0x05	/* read status register */
+#define	SPI_CMD_WREN 0x06	/* set write enable latch */
+
+#define	SPI_CMD_SECE 0x52	/* erase one sector */
+
+#define	SPI_STATUS_WPEN_LBN 7
+#define	SPI_STATUS_WPEN_WIDTH 1
+#define	SPI_STATUS_BP2_LBN 4
+#define	SPI_STATUS_BP2_WIDTH 1
+#define	SPI_STATUS_BP1_LBN 3
+#define	SPI_STATUS_BP1_WIDTH 1
+#define	SPI_STATUS_BP0_LBN 2
+#define	SPI_STATUS_BP0_WIDTH 1
+#define	SPI_STATUS_WEN_LBN 1
+#define	SPI_STATUS_WEN_WIDTH 1
+#define	SPI_STATUS_NRDY_LBN 0
+#define	SPI_STATUS_NRDY_WIDTH 1
+
+static	__checkReturn	int
+falcon_spi_wait(
+	__in		efx_nic_t *enp)
+{
+	unsigned int count;
+	int rc;
+
+	count = 0;
+	do {
+		efx_oword_t oword;
+
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		EFX_BAR_READO(enp, FR_AB_EE_SPI_HCMD_REG, &oword);
+
+		if (EFX_OWORD_FIELD(oword, FRF_AB_EE_SPI_HCMD_CMD_EN) == 0)
+			goto done;
+
+		/* Spin for 10 us */
+		EFSYS_SPIN(10);
+	} while (++count < 10000);
+
+	rc = ETIMEDOUT;
+	goto fail1;
+
+done:
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#define	FALCON_SPI_COPY(_dst, _src, _size)				\
+	do {								\
+		unsigned int index;					\
+									\
+		for (index = 0; index < (unsigned int)(_size); index++)	\
+			*((uint8_t *)(_dst) + index) =			\
+			    *((uint8_t *)(_src) + index);		\
+									\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+static	__checkReturn			int
+falcon_spi_cmd(
+	__in				efx_nic_t *enp,
+	__in				uint32_t sf_sel,
+	__in				uint32_t adbcnt,
+	__in				uint32_t cmd,
+	__in				uint32_t addr,
+	__in				boolean_t munge,
+	__drv_when(cmd == SPI_CMD_WRSR || cmd == SPI_CMD_WRITE,
+	    __drv_in(__byte_readableTo(dabcnt)))
+	__drv_when(cmd == SPI_CMD_RDSR || cmd == SPI_CMD_READ,
+	    __drv_out(__byte_readableTo(dabcnt)))
+					caddr_t base,
+	__in				uint32_t dabcnt)
+{
+	uint32_t enc;
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(dabcnt, <=,  sizeof (efx_oword_t));
+
+	/* Wait for the SPI to become available */
+	if ((rc = falcon_spi_wait(enp)) != 0)
+		goto fail1;
+
+	/* Program the data register */
+	if (cmd == SPI_CMD_WRSR || cmd == SPI_CMD_WRITE) {
+		EFSYS_ASSERT(base != NULL);
+		EFSYS_ASSERT(dabcnt != 0);
+		EFX_ZERO_OWORD(oword);
+		FALCON_SPI_COPY(&oword, base, dabcnt);
+		EFX_BAR_WRITEO(enp, FR_AB_EE_SPI_HDATA_REG, &oword);
+	}
+
+	/* Program the address register */
+	if (cmd == SPI_CMD_READ || cmd == SPI_CMD_WRITE ||
+	    cmd == SPI_CMD_SECE) {
+		EFX_POPULATE_OWORD_1(oword, FRF_AB_EE_SPI_HADR_ADR, addr);
+		EFX_BAR_WRITEO(enp, FR_AB_EE_SPI_HADR_REG, &oword);
+
+		enc = (munge) ? (cmd | ((addr >> 8) << 3)) : cmd;
+	} else {
+		enc = cmd;
+	}
+
+	/* Issue command */
+	EFX_POPULATE_OWORD_6(oword, FRF_AB_EE_SPI_HCMD_CMD_EN, 1,
+	    FRF_AB_EE_SPI_HCMD_SF_SEL, sf_sel,
+	    FRF_AB_EE_SPI_HCMD_DABCNT, dabcnt,
+	    FRF_AB_EE_SPI_HCMD_DUBCNT, 0,
+	    FRF_AB_EE_SPI_HCMD_ADBCNT, adbcnt,
+	    FRF_AB_EE_SPI_HCMD_ENC, enc);
+
+	EFX_SET_OWORD_FIELD(oword,
+	    FRF_AB_EE_SPI_HCMD_READ,
+	    (cmd == SPI_CMD_RDSR || cmd == SPI_CMD_READ) ? 1 : 0);
+
+	EFX_BAR_WRITEO(enp, FR_AB_EE_SPI_HCMD_REG, &oword);
+
+	/* Wait for read to complete */
+	if ((rc = falcon_spi_wait(enp)) != 0)
+		goto fail2;
+
+	/* Read the data register */
+	if (cmd == SPI_CMD_RDSR || cmd == SPI_CMD_READ) {
+		EFX_BAR_READO(enp, FR_AB_EE_SPI_HDATA_REG, &oword);
+		EFSYS_ASSERT(base != NULL);
+		FALCON_SPI_COPY(base, &oword, dabcnt);
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+falcon_spi_dev_wait(
+	__in		efx_nic_t *enp,
+	__in		falcon_spi_dev_t *fsdp,
+	__in		unsigned int us,
+	__in		unsigned int n)
+{
+	unsigned int count;
+	int rc;
+
+	count = 0;
+	do {
+		efx_byte_t byte;
+
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		if ((rc = falcon_spi_cmd(enp, fsdp->fsd_sf_sel,
+		    fsdp->fsd_adbcnt, SPI_CMD_RDSR, 0, fsdp->fsd_munge,
+		    (caddr_t)&byte, sizeof (efx_byte_t))) != 0)
+			goto fail1;
+
+		if (EFX_BYTE_FIELD(byte, SPI_STATUS_NRDY) == 0)
+			goto done;
+
+		EFSYS_SPIN(us);
+	} while (++count < n);
+
+	rc = ETIMEDOUT;
+	goto fail2;
+
+done:
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_spi_dev_read(
+	__in			efx_nic_t *enp,
+	__in			falcon_spi_type_t type,
+	__in			uint32_t addr,
+	__out_bcount(size)	caddr_t base,
+	__in			size_t size)
+{
+	falcon_spi_dev_t *fsdp = &(enp->en_u.falcon.enu_fsd[type]);
+	uint32_t end = addr + size;
+	int state;
+	int rc;
+
+	EFSYS_ASSERT3U(type, <, FALCON_SPI_NTYPES);
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if (fsdp == NULL) {
+		rc = ENODEV;
+		goto fail1;
+	}
+
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	while (addr != end) {
+		uint32_t dabcnt = MIN(end - addr, sizeof (efx_oword_t));
+
+		if ((rc = falcon_spi_cmd(enp, fsdp->fsd_sf_sel,
+		    fsdp->fsd_adbcnt, SPI_CMD_READ, addr, fsdp->fsd_munge,
+		    base, dabcnt)) != 0)
+			goto fail2;
+
+		EFSYS_ASSERT3U(addr, <, end);
+		addr += dabcnt;
+		base += dabcnt;
+	}
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_spi_dev_write(
+	__in			efx_nic_t *enp,
+	__in			falcon_spi_type_t type,
+	__in			uint32_t addr,
+	__in_bcount(size)	caddr_t base,
+	__in			size_t size)
+{
+	falcon_spi_dev_t *fsdp = &(enp->en_u.falcon.enu_fsd[type]);
+	uint32_t end = addr + size;
+	int state;
+	int rc;
+
+	EFSYS_ASSERT3U(type, <, FALCON_SPI_NTYPES);
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if (fsdp == NULL) {
+		rc = ENODEV;
+		goto fail1;
+	}
+
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	while (addr != end) {
+		efx_oword_t oword;
+		uint32_t dabcnt;
+		unsigned int index;
+
+		if ((rc = falcon_spi_cmd(enp, fsdp->fsd_sf_sel,
+			    fsdp->fsd_adbcnt, SPI_CMD_WREN, 0, fsdp->fsd_munge,
+			    NULL, 0)) != 0)
+			goto fail2;
+
+		dabcnt = MIN(end - addr, fsdp->fsd_write_size -
+		    (addr & (fsdp->fsd_write_size - 1)));
+		dabcnt = MIN(dabcnt, sizeof (efx_oword_t));
+
+		if ((rc = falcon_spi_cmd(enp, fsdp->fsd_sf_sel,
+			    fsdp->fsd_adbcnt, SPI_CMD_WRITE, addr,
+			    fsdp->fsd_munge, base, dabcnt)) != 0)
+			goto fail3;
+
+		if ((rc = falcon_spi_dev_wait(enp, fsdp, 1000, 20)) != 0)
+			goto fail4;
+
+		if ((rc = falcon_spi_cmd(enp, fsdp->fsd_sf_sel,
+			    fsdp->fsd_adbcnt, SPI_CMD_READ, addr,
+			    fsdp->fsd_munge, (caddr_t)&oword, dabcnt)) != 0)
+			goto fail5;
+
+		for (index = 0; index < dabcnt; index++) {
+			if (oword.eo_u8[index] != *(uint8_t *)(base + index)) {
+				rc = EIO;
+				goto fail6;
+			}
+		}
+
+		EFSYS_ASSERT3U(addr, <, end);
+		addr += dabcnt;
+		base += dabcnt;
+	}
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+falcon_spi_dev_erase(
+	__in		efx_nic_t *enp,
+	__in		falcon_spi_type_t type,
+	__in		uint32_t addr,
+	__in		size_t size)
+{
+	falcon_spi_dev_t *fsdp = &(enp->en_u.falcon.enu_fsd[type]);
+	uint32_t end = addr + size;
+	int state;
+	int rc;
+
+	EFSYS_ASSERT3U(type, <, FALCON_SPI_NTYPES);
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if (fsdp == NULL) {
+		rc = ENODEV;
+		goto fail1;
+	}
+
+	if (fsdp->fsd_erase_cmd == 0) {
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if (!IS_P2ALIGNED(addr, fsdp->fsd_erase_size) ||
+	    !IS_P2ALIGNED(size, fsdp->fsd_erase_size)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	while (addr != end) {
+		if ((rc = falcon_spi_cmd(enp, fsdp->fsd_sf_sel,
+			    fsdp->fsd_adbcnt, SPI_CMD_WREN, 0, fsdp->fsd_munge,
+			    NULL, 0)) != 0)
+			goto fail4;
+
+		if ((rc = falcon_spi_cmd(enp, fsdp->fsd_sf_sel,
+			    fsdp->fsd_adbcnt, fsdp->fsd_erase_cmd, addr,
+			    fsdp->fsd_munge, NULL, 0)) != 0)
+			goto fail5;
+
+		if ((rc = falcon_spi_dev_wait(enp, fsdp, 40000, 100)) != 0)
+			goto fail6;
+
+		EFSYS_ASSERT3U(addr, <, end);
+		addr += fsdp->fsd_erase_size;
+	}
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_FALCON */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_sram.c	2013-08-22 18:57:30.557209023 -0400
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_FALCON
+
+static	__checkReturn	int
+falcon_sram_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	unsigned int count;
+	int rc;
+
+	/* Initiate SRAM reset */
+	EFX_POPULATE_OWORD_3(oword,
+			    FRF_AZ_SRM_NUM_BANK,
+			    enp->en_u.falcon.enu_sram_num_bank,
+			    FRF_AZ_SRM_BANK_SIZE,
+			    enp->en_u.falcon.enu_sram_bank_size,
+			    FRF_AZ_SRM_INIT_EN, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_SRM_CFG_REG, &oword);
+
+	/* Wait for SRAM reset to complete */
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 1 ms */
+		EFSYS_SPIN(1000);
+
+		/* Check for reset complete */
+		EFX_BAR_READO(enp, FR_AZ_SRM_CFG_REG, &oword);
+		if (EFX_OWORD_FIELD(oword, FRF_AZ_SRM_INIT_EN) == 0)
+			goto done;
+	} while (++count < 100);
+
+	rc = ETIMEDOUT;
+	goto fail1;
+
+done:
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+falcon_sram_init(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_oword_t oword;
+	uint32_t tx_base, rx_base;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	/* Position the descriptor caches */
+	if (enp->en_u.falcon.enu_internal_sram) {
+		tx_base = 0x130000;
+		rx_base = 0x100000;
+	} else {
+		rx_base = encp->enc_buftbl_limit * 8;
+		tx_base = rx_base + (encp->enc_rxq_limit * 64 * 8);
+	}
+
+	/* Select internal SRAM */
+	EFX_BAR_READO(enp, FR_AB_NIC_STAT_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_ONCHIP_SRAM,
+	    enp->en_u.falcon.enu_internal_sram ? 1 : 0);
+	EFX_BAR_WRITEO(enp, FR_AB_NIC_STAT_REG, &oword);
+
+	/* Sleep/Wake any external SRAM */
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO1_OEN, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO1_OUT,
+	    enp->en_u.falcon.enu_internal_sram ? 1 : 0);
+	EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
+
+	/* Clear the SRAM contents */
+	if ((rc = falcon_sram_reset(enp)) != 0)
+		goto fail1;
+
+	/* Initialize the buffer table */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);
+
+	/* Initialize the transmit descriptor cache */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_TX_DC_BASE_ADR, tx_base);
+	EFX_BAR_WRITEO(enp, FR_AZ_SRM_TX_DC_CFG_REG, &oword);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DC_SIZE, 1); /* 16 descriptors */
+	EFX_BAR_WRITEO(enp, FR_AZ_TX_DC_CFG_REG, &oword);
+
+	/* Initialize the receive descriptor cache */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_RX_DC_BASE_ADR, rx_base);
+	EFX_BAR_WRITEO(enp, FR_AZ_SRM_RX_DC_CFG_REG, &oword);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DC_SIZE, 3); /* 64 descriptors */
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_DC_CFG_REG, &oword);
+
+	/* Set receive descriptor pre-fetch low water mark */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DC_PF_LWM, 56);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_DC_PF_WM_REG, &oword);
+
+	/* Set the event queue to use for SRAM updates */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_UPD_EVQ_ID, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_SRM_UPD_EVQ_REG, &oword);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_DIAG
+
+	__checkReturn	int
+falcon_sram_test(
+	__in		efx_nic_t *enp,
+	__in		efx_sram_pattern_fn_t func)
+{
+	efx_qword_t qword;
+	efx_qword_t verify;
+	size_t rows = 0x1000;
+	unsigned int rptr;
+	unsigned int wptr;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	/*
+	 * Write the pattern through the SRAM debug aperture. Write
+	 * in 64 entry batches, waiting 1us in between each batch
+	 * to guarantee not to overflow the SRAM fifo
+	 */
+	for (wptr = 0, rptr = 0; wptr < rows; ++wptr) {
+		func(wptr, B_FALSE, &qword);
+		EFX_BAR_TBL_WRITEQ(enp, FR_AZ_SRM_DBG_REG, wptr, &qword);
+
+		if ((wptr - rptr) < 64 && wptr < rows - 1)
+			continue;
+
+		EFSYS_SPIN(1);
+
+		for (; rptr <= wptr; ++rptr) {
+			func(rptr, B_FALSE, &qword);
+			EFX_BAR_TBL_READQ(enp, FR_AZ_SRM_DBG_REG, rptr,
+			    &verify);
+
+			if (!EFX_QWORD_IS_EQUAL(verify, qword)) {
+				rc = EFAULT;
+				goto fail1;
+			}
+		}
+	}
+
+	/* And do the same negated */
+	for (wptr = 0, rptr = 0; wptr < rows; ++wptr) {
+		func(wptr, B_TRUE, &qword);
+		EFX_BAR_TBL_WRITEQ(enp, FR_AZ_SRM_DBG_REG, wptr, &qword);
+
+		if ((wptr - rptr) < 64 && wptr < rows - 1)
+			continue;
+
+		EFSYS_SPIN(1);
+
+		for (; rptr <= wptr; ++rptr) {
+			func(rptr, B_TRUE, &qword);
+			EFX_BAR_TBL_READQ(enp, FR_AZ_SRM_DBG_REG, rptr,
+			    &verify);
+
+			if (!EFX_QWORD_IS_EQUAL(verify, qword)) {
+				rc = EFAULT;
+				goto fail2;
+			}
+		}
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_DIAG */
+
+		void
+falcon_sram_fini(
+	__in	efx_nic_t *enp)
+{
+	efx_oword_t oword;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
+	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
+
+	/* Allow the GPIO1 pin to float */
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO1_OEN, 0);
+	EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
+}
+
+#endif	/* EFS_OPT_FALCON */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_stats.h	2013-08-22 18:57:30.643857238 -0400
@@ -0,0 +1,245 @@
+/*-
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_FALCON_STATS_H
+#define	_SYS_FALCON_STATS_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Falcon GMAC stats
+ */
+#define	G_RX_GOOD_OCT_OFFSET 0x0
+#define	G_RX_GOOD_OCT_WIDTH 6
+#define	G_RX_BAD_OCT_OFFSET 0x8
+#define	G_RX_BAD_OCT_WIDTH 6
+#define	G_RX_MISS_PKT_OFFSET 0x10
+#define	G_RX_MISS_PKT_WIDTH 4
+#define	G_RX_FALSE_CRS_OFFSET 0x14
+#define	G_RX_FALSE_CRS_WIDTH 4
+#define	G_RX_PAUSE_PKT_OFFSET 0x18
+#define	G_RX_PAUSE_PKT_WIDTH 4
+#define	G_RX_BAD_PKT_OFFSET 0x1C
+#define	G_RX_BAD_PKT_WIDTH 4
+#define	G_RX_UCAST_PKT_OFFSET 0x20
+#define	G_RX_UCAST_PKT_WIDTH 4
+#define	G_RX_MCAST_PKT_OFFSET 0x24
+#define	G_RX_MCAST_PKT_WIDTH 4
+#define	G_RX_BCAST_PKT_OFFSET 0x28
+#define	G_RX_BCAST_PKT_WIDTH 4
+#define	G_RX_GOOD_LT_64_PKT_OFFSET 0x2C
+#define	G_RX_GOOD_LT_64_PKT_WIDTH 4
+#define	G_RX_BAD_LT_64_PKT_OFFSET 0x30
+#define	G_RX_BAD_LT_64_PKT_WIDTH 4
+#define	G_RX_64_PKT_OFFSET 0x34
+#define	G_RX_64_PKT_WIDTH 4
+#define	G_RX_65_TO_127_PKT_OFFSET 0x38
+#define	G_RX_65_TO_127_PKT_WIDTH 4
+#define	G_RX_128_TO_255_PKT_OFFSET 0x3C
+#define	G_RX_128_TO_255_PKT_WIDTH 4
+#define	G_RX_256_TO_511_PKT_OFFSET 0x40
+#define	G_RX_256_TO_511_PKT_WIDTH 4
+#define	G_RX_512_TO_1023_PKT_OFFSET 0x44
+#define	G_RX_512_TO_1023_PKT_WIDTH 4
+#define	G_RX_1024_TO_15XX_PKT_OFFSET 0x48
+#define	G_RX_1024_TO_15XX_PKT_WIDTH 4
+#define	G_RX_15XX_TO_JUMBO_PKT_OFFSET 0x4C
+#define	G_RX_15XX_TO_JUMBO_PKT_WIDTH 4
+#define	G_RX_GT_JUMBO_PKT_OFFSET 0x50
+#define	G_RX_GT_JUMBO_PKT_WIDTH 4
+#define	G_RX_FCS_ERR_64_TO_15XX_PKT_OFFSET 0x54
+#define	G_RX_FCS_ERR_64_TO_15XX_PKT_WIDTH 4
+#define	G_RX_FCS_ERR_15XX_TO_JUMBO_PKT_OFFSET 0x58
+#define	G_RX_FCS_ERR_15XX_TO_JUMBO_PKT_WIDTH 4
+#define	G_RX_FCS_ERR_GT_JUMBO_PKT_OFFSET 0x5C
+#define	G_RX_FCS_ERR_GT_JUMBO_PKT_WIDTH 4
+
+#define	G_TX_GOOD_BAD_OCT_OFFSET 0x80
+#define	G_TX_GOOD_BAD_OCT_WIDTH 6
+#define	G_TX_GOOD_OCT_OFFSET 0x88
+#define	G_TX_GOOD_OCT_WIDTH 6
+#define	G_TX_SGL_COL_PKT_OFFSET 0x90
+#define	G_TX_SGL_COL_PKT_WIDTH 4
+#define	G_TX_MULT_COL_PKT_OFFSET 0x94
+#define	G_TX_MULT_COL_PKT_WIDTH 4
+#define	G_TX_EX_COL_PKT_OFFSET 0x98
+#define	G_TX_EX_COL_PKT_WIDTH 4
+#define	G_TX_DEF_PKT_OFFSET 0x9C
+#define	G_TX_DEF_PKT_WIDTH 4
+#define	G_TX_LATE_COL_OFFSET 0xA0
+#define	G_TX_LATE_COL_WIDTH 4
+#define	G_TX_EX_DEF_PKT_OFFSET 0xA4
+#define	G_TX_EX_DEF_PKT_WIDTH 4
+#define	G_TX_PAUSE_PKT_OFFSET 0xA8
+#define	G_TX_PAUSE_PKT_WIDTH 4
+#define	G_TX_BAD_PKT_OFFSET 0xAC
+#define	G_TX_BAD_PKT_WIDTH 4
+#define	G_TX_UCAST_PKT_OFFSET 0xB0
+#define	G_TX_UCAST_PKT_WIDTH 4
+#define	G_TX_MCAST_PKT_OFFSET 0xB4
+#define	G_TX_MCAST_PKT_WIDTH 4
+#define	G_TX_BCAST_PKT_OFFSET 0xB8
+#define	G_TX_BCAST_PKT_WIDTH 4
+#define	G_TX_LT_64_PKT_OFFSET 0xBC
+#define	G_TX_LT_64_PKT_WIDTH 4
+#define	G_TX_64_PKT_OFFSET 0xC0
+#define	G_TX_64_PKT_WIDTH 4
+#define	G_TX_65_TO_127_PKT_OFFSET 0xC4
+#define	G_TX_65_TO_127_PKT_WIDTH 4
+#define	G_TX_128_TO_255_PKT_OFFSET 0xC8
+#define	G_TX_128_TO_255_PKT_WIDTH 4
+#define	G_TX_256_TO_511_PKT_OFFSET 0xCC
+#define	G_TX_256_TO_511_PKT_WIDTH 4
+#define	G_TX_512_TO_1023_PKT_OFFSET 0xD0
+#define	G_TX_512_TO_1023_PKT_WIDTH 4
+#define	G_TX_1024_TO_15XX_PKT_OFFSET 0xD4
+#define	G_TX_1024_TO_15XX_PKT_WIDTH 4
+#define	G_TX_15XX_TO_JUMBO_PKT_OFFSET 0xD8
+#define	G_TX_15XX_TO_JUMBO_PKT_WIDTH 4
+#define	G_TX_GT_JUMBO_PKT_OFFSET 0xDC
+#define	G_TX_GT_JUMBO_PKT_WIDTH 4
+#define	G_TX_NON_TCP_UDP_PKT_OFFSET 0xE0
+#define	G_TX_NON_TCP_UDP_PKT_WIDTH 2
+#define	G_TX_MAC_SRC_ERR_PKT_OFFSET 0xE4
+#define	G_TX_MAC_SRC_ERR_PKT_WIDTH 2
+#define	G_TX_IP_SRC_ERR_PKT_OFFSET 0xE8
+#define	G_TX_IP_SRC_ERR_PKT_WIDTH 2
+
+#define	G_DMA_DONE_OFFSET 0xEC
+#define	G_DMA_DONE_WIDTH 4
+
+#define	G_STAT_OFFSET(_id) G_ ## _id ## _OFFSET
+#define	G_STAT_WIDTH(_id) G_ ## _id ## _WIDTH
+
+/*
+ * Falcon XMAC stats
+ */
+#define	XG_RX_OCTETS_OFFSET 0x0
+#define	XG_RX_OCTETS_WIDTH 6
+#define	XG_RX_OCTETS_OK_OFFSET 0x8
+#define	XG_RX_OCTETS_OK_WIDTH 6
+#define	XG_RX_PKTS_OFFSET 0x10
+#define	XG_RX_PKTS_WIDTH 4
+#define	XG_RX_PKTS_OK_OFFSET 0x14
+#define	XG_RX_PKTS_OK_WIDTH 4
+#define	XG_RX_BROADCAST_PKTS_OFFSET 0x18
+#define	XG_RX_BROADCAST_PKTS_WIDTH 4
+#define	XG_RX_MULTICAST_PKTS_OFFSET 0x1C
+#define	XG_RX_MULTICAST_PKTS_WIDTH 4
+#define	XG_RX_UNICAST_PKTS_OFFSET 0x20
+#define	XG_RX_UNICAST_PKTS_WIDTH 4
+#define	XG_RX_UNDERSIZE_PKTS_OFFSET 0x24
+#define	XG_RX_UNDERSIZE_PKTS_WIDTH 4
+#define	XG_RX_OVERSIZE_PKTS_OFFSET 0x28
+#define	XG_RX_OVERSIZE_PKTS_WIDTH 4
+#define	XG_RX_JABBER_PKTS_OFFSET 0x2C
+#define	XG_RX_JABBER_PKTS_WIDTH 4
+#define	XG_RX_UNDERSIZE_FCS_ERROR_PKTS_OFFSET 0x30
+#define	XG_RX_UNDERSIZE_FCS_ERROR_PKTS_WIDTH 4
+#define	XG_RX_DROP_EVENTS_OFFSET 0x34
+#define	XG_RX_DROP_EVENTS_WIDTH 4
+#define	XG_RX_FCS_ERROR_PKTS_OFFSET 0x38
+#define	XG_RX_FCS_ERROR_PKTS_WIDTH 4
+#define	XG_RX_ALIGN_ERROR_OFFSET 0x3C
+#define	XG_RX_ALIGN_ERROR_WIDTH 4
+#define	XG_RX_SYMBOL_ERROR_OFFSET 0x40
+#define	XG_RX_SYMBOL_ERROR_WIDTH 4
+#define	XG_RX_INTERNAL_MAC_ERROR_OFFSET 0x44
+#define	XG_RX_INTERNAL_MAC_ERROR_WIDTH 4
+#define	XG_RX_CONTROL_PKTS_OFFSET 0x48
+#define	XG_RX_CONTROL_PKTS_WIDTH 4
+#define	XG_RX_PAUSE_PKTS_OFFSET 0x4C
+#define	XG_RX_PAUSE_PKTS_WIDTH 4
+#define	XG_RX_PKTS_64_OCTETS_OFFSET 0x50
+#define	XG_RX_PKTS_64_OCTETS_WIDTH 4
+#define	XG_RX_PKTS_65_TO_127_OCTETS_OFFSET 0x54
+#define	XG_RX_PKTS_65_TO_127_OCTETS_WIDTH 4
+#define	XG_RX_PKTS_128_TO_255_OCTETS_OFFSET 0x58
+#define	XG_RX_PKTS_128_TO_255_OCTETS_WIDTH 4
+#define	XG_RX_PKTS_256_TO_511_OCTETS_OFFSET 0x5C
+#define	XG_RX_PKTS_256_TO_511_OCTETS_WIDTH 4
+#define	XG_RX_PKTS_512_TO_1023_OCTETS_OFFSET 0x60
+#define	XG_RX_PKTS_512_TO_1023_OCTETS_WIDTH 4
+#define	XG_RX_PKTS_1024_TO_15XX_OCTETS_OFFSET 0x64
+#define	XG_RX_PKTS_1024_TO_15XX_OCTETS_WIDTH 4
+#define	XG_RX_PKTS_15XX_TO_MAX_OCTETS_OFFSET 0x68
+#define	XG_RX_PKTS_15XX_TO_MAX_OCTETS_WIDTH 4
+#define	XG_RX_LENGTH_ERROR_OFFSET 0x6C
+#define	XG_RX_LENGTH_ERROR_WIDTH 4
+
+#define	XG_TX_PKTS_OFFSET 0x80
+#define	XG_TX_PKTS_WIDTH 4
+#define	XG_TX_OCTETS_OFFSET 0x88
+#define	XG_TX_OCTETS_WIDTH 6
+#define	XG_TX_MULTICAST_PKTS_OFFSET 0x90
+#define	XG_TX_MULTICAST_PKTS_WIDTH 4
+#define	XG_TX_BROADCAST_PKTS_OFFSET 0x94
+#define	XG_TX_BROADCAST_PKTS_WIDTH 4
+#define	XG_TX_UNICAST_PKTS_OFFSET 0x98
+#define	XG_TX_UNICAST_PKTS_WIDTH 4
+#define	XG_TX_CONTROL_PKTS_OFFSET 0x9C
+#define	XG_TX_CONTROL_PKTS_WIDTH 4
+#define	XG_TX_PAUSE_PKTS_OFFSET 0xA0
+#define	XG_TX_PAUSE_PKTS_WIDTH 4
+#define	XG_TX_PKTS_64_OCTETS_OFFSET 0xA4
+#define	XG_TX_PKTS_64_OCTETS_WIDTH 4
+#define	XG_TX_PKTS_65_TO_127_OCTETS_OFFSET 0xA8
+#define	XG_TX_PKTS_65_TO_127_OCTETS_WIDTH 4
+#define	XG_TX_PKTS_128_TO_255_OCTETS_OFFSET 0xAC
+#define	XG_TX_PKTS_128_TO_255_OCTETS_WIDTH 4
+#define	XG_TX_PKTS_256_TO_511_OCTETS_OFFSET 0xB0
+#define	XG_TX_PKTS_256_TO_511_OCTETS_WIDTH 4
+#define	XG_TX_PKTS_512_TO_1023_OCTETS_OFFSET 0xB4
+#define	XG_TX_PKTS_512_TO_1023_OCTETS_WIDTH 4
+#define	XG_TX_PKTS_1024_TO_15XX_OCTETS_OFFSET 0xB8
+#define	XG_TX_PKTS_1024_TO_15XX_OCTETS_WIDTH 4
+#define	XG_TX_PKTS_15XX_TO_MAX_OCTETS_OFFSET 0xBC
+#define	XG_TX_PKTS_15XX_TO_MAX_OCTETS_WIDTH 4
+#define	XG_TX_UNDERSIZE_PKTS_OFFSET 0xC0
+#define	XG_TX_UNDERSIZE_PKTS_WIDTH 4
+#define	XG_TX_OVERSIZE_PKTS_OFFSET 0xC4
+#define	XG_TX_OVERSIZE_PKTS_WIDTH 4
+#define	XG_TX_NON_TCP_UDP_PKTS_OFFSET 0xC8
+#define	XG_TX_NON_TCP_UDP_PKTS_WIDTH 2
+#define	XG_TX_MAC_SRC_ERR_PKTS_OFFSET 0xCC
+#define	XG_TX_MAC_SRC_ERR_PKTS_WIDTH 2
+#define	XG_TX_IP_SRC_ERR_PKTS_OFFSET 0xD0
+#define	XG_TX_IP_SRC_ERR_PKTS_WIDTH 2
+
+#define	XG_DMA_DONE_OFFSET 0xD4
+#define	XG_DMA_DONE_WIDTH 4
+
+#define	DMA_IS_DONE 0xffffffff
+
+#define	XG_STAT_OFFSET(_id) XG_ ## _id ## _OFFSET
+#define	XG_STAT_WIDTH(_id) XG_ ## _id ## _WIDTH
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_FALCON_STATS_H */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_vpd.c	2013-08-22 18:57:30.729122700 -0400
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Falcon conviniently uses an EEPROM to store it's VPD configuration,
+ * and it stores the VPD contents in native VPD format. This code does
+ * not cope with the presence of an RW block in VPD at all.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "falcon_nvram.h"
+#include "efx_types.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_FALCON
+
+#if EFSYS_OPT_VPD
+
+typedef struct {
+	size_t		fvpdd_base;
+	size_t		fvpdd_size;
+	boolean_t	fvpdd_writable;
+} falcon_vpd_dimension_t;
+
+static				void
+falcon_vpd_dimension(
+	__in			efx_nic_t *enp,
+	__out			falcon_vpd_dimension_t *dimp)
+{
+	efx_oword_t oword;
+
+#if EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE
+	if (enp->en_u.falcon.enu_forced_cfg != NULL) {
+		memcpy(&oword, (enp->en_u.falcon.enu_forced_cfg
+				+ EE_VPD_CFG0_REG_SF_OFST), sizeof (oword));
+	}
+	else
+#endif	/* EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE */
+	{
+		EFX_BAR_READO(enp, FR_AB_EE_VPD_CFG0_REG, &oword);
+	}
+
+	dimp->fvpdd_base = EFX_OWORD_FIELD(oword, FRF_AB_EE_VPD_BASE);
+	dimp->fvpdd_size = EFX_OWORD_FIELD(oword, FRF_AB_EE_VPD_LENGTH);
+	if (dimp->fvpdd_size != 0)
+		/* Non-zero "lengths" are actually maximum dword offsets */
+		dimp->fvpdd_size += 4;
+	dimp->fvpdd_writable =
+		EFX_OWORD_FIELD(oword, FRF_AB_EE_VPDW_LENGTH) != 0;
+}
+
+	__checkReturn		int
+falcon_vpd_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep)
+{
+	falcon_vpd_dimension_t dim;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	falcon_vpd_dimension(enp, &dim);
+	if (dim.fvpdd_size == 0 || dim.fvpdd_writable) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	*sizep = dim.fvpdd_size;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	*sizep = 0;
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_vpd_read(
+	__in			efx_nic_t *enp,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	falcon_vpd_dimension_t dim;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	falcon_vpd_dimension(enp, &dim);
+	if (size < dim.fvpdd_size || size == 0) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_EEPROM,
+		    dim.fvpdd_base, data, size)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_vpd_verify(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	falcon_vpd_dimension_t dim;
+	boolean_t cksummed;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	falcon_vpd_dimension(enp, &dim);
+	EFSYS_ASSERT3U(dim.fvpdd_size, <=, size);
+	EFSYS_ASSERT(!dim.fvpdd_writable);
+
+	if ((rc = efx_vpd_hunk_verify(data, size, &cksummed)) != 0)
+		goto fail1;
+
+	if (!cksummed) {
+		rc = EFAULT;
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_vpd_get(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__inout			efx_vpd_value_t *evvp)
+{
+	falcon_vpd_dimension_t dim;
+	unsigned int offset;
+	uint8_t length;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	if (evvp->evv_tag != EFX_VPD_ID && evvp->evv_tag != EFX_VPD_RO) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	falcon_vpd_dimension(enp, &dim);
+	EFSYS_ASSERT3U(dim.fvpdd_size, <=, size);
+	EFSYS_ASSERT(!dim.fvpdd_writable);
+
+	if ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag,
+	    evvp->evv_keyword, &offset, &length)) != 0)
+		goto fail2;
+
+	/* Copy out */
+	evvp->evv_length = length;
+	memcpy(evvp->evv_value, data + offset, length);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_vpd_set(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_value_t *evvp)
+{
+	falcon_vpd_dimension_t dim;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	falcon_vpd_dimension(enp, &dim);
+	EFSYS_ASSERT3U(dim.fvpdd_size, <=, size);
+
+	if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)
+		goto fail1;
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_vpd_next(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out			efx_vpd_value_t *evvp,
+	__inout			unsigned int *contp)
+{
+	falcon_vpd_dimension_t dim;
+	unsigned int offset;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	falcon_vpd_dimension(enp, &dim);
+	EFSYS_ASSERT3U(dim.fvpdd_size, <=, size);
+	EFSYS_ASSERT(!dim.fvpdd_writable);
+
+	/* Find the (tag, keyword) */
+	if ((rc = efx_vpd_hunk_next(data, size, &evvp->evv_tag,
+	    &evvp->evv_keyword, &offset, &evvp->evv_length, contp)) != 0)
+		goto fail1;
+
+	/* Copyout */
+	memcpy(evvp->evv_value, data + offset, evvp->evv_length);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+falcon_vpd_write(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	falcon_vpd_dimension_t dim;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
+
+	falcon_vpd_dimension(enp, &dim);
+	if (dim.fvpdd_size != size) {
+		/* User hasn't provided sufficient data */
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if ((rc = falcon_spi_dev_write(enp, FALCON_SPI_EEPROM,
+		    dim.fvpdd_base, data, dim.fvpdd_size)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_FALCON */
+
+#endif	/* EFSYS_OPT_VPD */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_xmac.c	2013-08-22 18:57:30.815617311 -0400
@@ -0,0 +1,537 @@
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "falcon_stats.h"
+#include "falcon_xmac.h"
+
+#if EFSYS_OPT_MAC_FALCON_XMAC
+
+static	__checkReturn	int
+falcon_xmac_xgxs_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+	unsigned int count;
+	int rc;
+
+	/* Reset the XGMAC via the Vendor Register */
+	EFX_POPULATE_OWORD_1(oword, FRF_AB_XX_RST_XX_EN, 1);
+	EFX_BAR_WRITEO(enp, FR_AB_XX_PWR_RST_REG, &oword);
+
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 10us */
+		EFSYS_SPIN(10);
+
+		/* Test for reset complete */
+		EFX_BAR_READO(enp, FR_AB_XX_PWR_RST_REG, &oword);
+		if (EFX_OWORD_FIELD(oword, FRF_AB_XX_RST_XX_EN) == 0 &&
+		    EFX_OWORD_FIELD(oword, FRF_AB_XX_SD_RST_ACT) == 0)
+			goto done;
+	} while (++count < 1000);
+
+	rc = ETIMEDOUT;
+	goto fail1;
+
+done:
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static			void
+falcon_xmac_xgxs_reconfigure(
+	__in		efx_nic_t *enp)
+{
+#if EFSYS_OPT_LOOPBACK
+	efx_port_t *epp = &(enp->en_port);
+#endif	/* EFSYS_OPT_LOOPBACK */
+	efx_oword_t oword;
+	uint32_t force_sig;
+	uint32_t force_sig_val;
+	uint32_t xgxs_lb_en;
+	uint32_t xgmii_lb_en;
+	uint32_t lpbk;
+	boolean_t need_reset;
+
+#if EFSYS_OPT_LOOPBACK
+	force_sig =
+	    (epp->ep_loopback_type == EFX_LOOPBACK_XGXS ||
+	    epp->ep_loopback_type == EFX_LOOPBACK_XAUI) ?
+	    1 : 0;
+	force_sig_val =
+	    (epp->ep_loopback_type == EFX_LOOPBACK_XGXS ||
+	    epp->ep_loopback_type == EFX_LOOPBACK_XAUI) ?
+	    1 : 0;
+	xgxs_lb_en = (epp->ep_loopback_type == EFX_LOOPBACK_XGXS) ?
+	    1 : 0;
+	xgmii_lb_en = (epp->ep_loopback_type == EFX_LOOPBACK_XGMII) ?
+	    1 : 0;
+	lpbk = (epp->ep_loopback_type == EFX_LOOPBACK_XAUI) ?
+	    1 : 0;
+#else	/* EFSYS_OPT_LOOPBACK */
+	force_sig = 0;
+	force_sig_val = 0;
+	xgxs_lb_en = 0;
+	xgmii_lb_en = 0;
+	lpbk = 0;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	EFX_BAR_READO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
+	need_reset =
+	    (EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG0) != force_sig ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG0_VAL) != force_sig_val ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG1) != force_sig ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG1_VAL) != force_sig_val ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG2) != force_sig ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG2_VAL) != force_sig_val ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG3) != force_sig ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG3_VAL) != force_sig_val ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_XGXS_LB_EN) != xgxs_lb_en ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_XGMII_LB_EN) != xgmii_lb_en);
+
+	EFX_BAR_READO(enp, FR_AB_XX_SD_CTL_REG, &oword);
+	need_reset |= (EFX_OWORD_FIELD(oword, FRF_AB_XX_LPBKA) != lpbk ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_LPBKB) != lpbk ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_LPBKC) != lpbk ||
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_LPBKD) != lpbk);
+
+	if (need_reset)
+		(void) falcon_xmac_xgxs_reset(enp);
+
+	EFX_BAR_READO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG0, force_sig);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG0_VAL, force_sig_val);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG1, force_sig);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG1_VAL, force_sig_val);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG2, force_sig);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG2_VAL, force_sig_val);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG3, force_sig);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG3_VAL, force_sig_val);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_XGXS_LB_EN, xgxs_lb_en);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_XGMII_LB_EN, xgmii_lb_en);
+	EFX_BAR_WRITEO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
+
+	EFX_BAR_READO(enp, FR_AB_XX_SD_CTL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_LPBKD, lpbk);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_LPBKB, lpbk);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_LPBKC, lpbk);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_LPBKA, lpbk);
+	EFX_BAR_WRITEO(enp, FR_AB_XX_SD_CTL_REG, &oword);
+}
+
+static			void
+falcon_xmac_core_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_oword_t oword;
+
+	EFX_POPULATE_OWORD_3(oword,
+	    FRF_AB_XM_RX_JUMBO_MODE, 1,
+	    FRF_AB_XM_TX_STAT_EN, 1,
+	    FRF_AB_XM_RX_STAT_EN, 1);
+
+	EFX_BAR_WRITEO(enp, FR_AB_XM_GLB_CFG_REG, &oword);
+
+	EFX_POPULATE_OWORD_6(oword,
+	    FRF_AB_XM_TXEN, 1,
+	    FRF_AB_XM_TX_PRMBL, 1,
+	    FRF_AB_XM_AUTO_PAD, 1,
+	    FRF_AB_XM_TXCRC, 1,
+	    FRF_AB_XM_FCNTL, 1,
+	    FRF_AB_XM_IPG, 3);
+
+	EFX_BAR_WRITEO(enp, FR_AB_XM_TX_CFG_REG, &oword);
+
+	EFX_POPULATE_OWORD_6(oword,
+	    FRF_AB_XM_RXEN, 1,
+	    FRF_AB_XM_AUTO_DEPAD, 0,
+	    FRF_AB_XM_REJ_BCAST, (epp->ep_brdcst) ? 0 : 1,
+	    FRF_AB_XM_ACPT_ALL_MCAST, 1,
+	    FRF_AB_XM_ACPT_ALL_UCAST, (epp->ep_unicst) ? 1 : 0,
+	    FRF_AB_XM_PASS_CRC_ERR, 1);
+
+	EFX_BAR_WRITEO(enp, FR_AB_XM_RX_CFG_REG, &oword);
+
+	EFX_POPULATE_OWORD_2(oword,
+	    FRF_AB_XM_PAUSE_TIME, 0xfffe,
+	    FRF_AB_XM_DIS_FCNTL, (epp->ep_fcntl != 0) ? 0 : 1);
+
+	EFX_BAR_WRITEO(enp, FR_AB_XM_FC_REG, &oword);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AB_XM_ADR_LO,
+	    ((uint32_t)epp->ep_mac_addr[0] << 0) |
+	    ((uint32_t)epp->ep_mac_addr[1] << 8) |
+	    ((uint32_t)epp->ep_mac_addr[2] << 16) |
+	    ((uint32_t)epp->ep_mac_addr[3] << 24));
+
+	EFX_BAR_WRITEO(enp, FR_AB_XM_ADR_LO_REG, &oword);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AB_XM_ADR_HI,
+	    ((uint32_t)epp->ep_mac_addr[4] << 0) |
+	    ((uint32_t)epp->ep_mac_addr[5] << 8));
+
+	EFX_BAR_WRITEO(enp, FR_AB_XM_ADR_HI_REG, &oword);
+
+	EFX_POPULATE_OWORD_1(oword,
+	    FRF_AB_XM_MAX_RX_FRM_SIZE_HI, epp->ep_mac_pdu >> 3);
+
+	EFX_BAR_WRITEO(enp, FR_AB_XM_RX_PARAM_REG, &oword);
+
+	EFX_POPULATE_OWORD_2(oword,
+	    FRF_AB_XM_MAX_TX_FRM_SIZE_HI, epp->ep_mac_pdu >> 3,
+	    FRF_AB_XM_TX_JUMBO_MODE, 1);
+
+	EFX_BAR_WRITEO(enp, FR_AB_XM_TX_PARAM_REG, &oword);
+}
+
+	__checkReturn	int
+falcon_xmac_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_oword_t oword;
+	int rc;
+
+	EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_XMAC);
+
+	EFSYS_PROBE(reset);
+
+	/* Ensure that the XMAC registers are accessible */
+	EFX_BAR_READO(enp, FR_AB_NIC_STAT_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_BB_EE_STRAP_EN, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_BB_EE_STRAP, 0x5);
+	EFX_BAR_WRITEO(enp, FR_AB_NIC_STAT_REG, &oword);
+
+	if ((rc = falcon_mac_wrapper_disable(enp)) != 0)
+	    goto fail1;
+
+	/*
+	 * Force the PHY XAUI state machine to restart after the EM block
+	 * reset. Don't do this if we're now in a MAC level loopback.
+	 */
+#if EFSYS_OPT_LOOPBACK
+	if ((1 << epp->ep_loopback_type) & ~EFX_LOOPBACK_MAC_MASK)
+#endif
+		if ((rc = falcon_xmac_xgxs_reset(enp)) != 0)
+			goto fail2;
+
+	epp->ep_mac_poll_needed = B_TRUE;
+
+	enp->en_reset_flags |= EFX_RESET_MAC;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+falcon_xmac_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+
+	EFSYS_PROBE(reconfigure);
+
+	EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_XMAC);
+	EFSYS_ASSERT(epp->ep_link_mode == EFX_LINK_UNKNOWN ||
+		    epp->ep_link_mode == EFX_LINK_DOWN ||
+		    epp->ep_link_mode == EFX_LINK_10000FDX);
+
+	falcon_xmac_xgxs_reconfigure(enp);
+	falcon_xmac_core_reconfigure(enp);
+
+	falcon_mac_wrapper_enable(enp);
+
+	return (0);
+}
+
+#if EFSYS_OPT_MAC_STATS
+static		uint32_t
+falcon_xmac_stat_read(
+	__in	efsys_mem_t *esmp,
+	__in	unsigned int offset,
+	__in	unsigned int width)
+{
+	uint32_t val;
+
+	switch (width) {
+	case 2: {
+		efx_dword_t dword;
+
+		EFSYS_MEM_READD(esmp, offset, &dword);
+
+		val = (uint16_t)EFX_DWORD_FIELD(dword, EFX_WORD_0);
+		break;
+	}
+	case 4: {
+		efx_dword_t dword;
+
+		EFSYS_MEM_READD(esmp, offset, &dword);
+
+		val = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+		break;
+	}
+	case 6: {
+		efx_qword_t qword;
+
+		EFSYS_MEM_READQ(esmp, offset, &qword);
+
+		val = EFX_QWORD_FIELD(qword, EFX_DWORD_0);
+		break;
+	}
+	default:
+		EFSYS_ASSERT(B_FALSE);
+
+		val = 0;
+		break;
+	}
+
+	return (val);
+}
+
+#define	XMAC_STAT_READ(_esmp, _id)					\
+	falcon_xmac_stat_read((_esmp), XG_STAT_OFFSET(_id),		\
+	    XG_STAT_WIDTH(_id))
+
+#define	XMAC_STAT_INCR(_esmp, _stat, _id)				\
+	do {								\
+		delta = XMAC_STAT_READ(_esmp, _id);			\
+		EFSYS_STAT_INCR(&(_stat), delta);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (0)
+
+#define	XMAC_STAT_DECR(_esmp, _stat, _id)				\
+	do {								\
+		delta = XMAC_STAT_READ(_esmp, _id);			\
+		EFSYS_STAT_DECR(&(_stat), delta);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (0)
+
+	__checkReturn			int
+falcon_xmac_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__in_ecount(EFX_MAC_NSTATS)	efsys_stat_t *stat,
+	__out_opt			uint32_t *generationp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_oword_t oword;
+	uint32_t delta;
+
+	_NOTE(ARGUNUSED(generationp));
+	EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_XMAC);
+
+	/* Check the DMA flag */
+	if (XMAC_STAT_READ(esmp, DMA_DONE) != DMA_IS_DONE)
+		return (EAGAIN);
+	EFSYS_MEM_READ_BARRIER();
+
+	/* RX */
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_OCTETS], RX_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_UNICST_PKTS], RX_UNICAST_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_MULTICST_PKTS],
+	    RX_MULTICAST_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_BRDCST_PKTS], RX_BROADCAST_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PAUSE_PKTS], RX_PAUSE_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_LE_64_PKTS], RX_UNDERSIZE_PKTS);
+
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_LE_64_PKTS], RX_PKTS_64_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_65_TO_127_PKTS],
+	    RX_PKTS_65_TO_127_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_128_TO_255_PKTS],
+	    RX_PKTS_128_TO_255_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_256_TO_511_PKTS],
+	    RX_PKTS_256_TO_511_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_512_TO_1023_PKTS],
+	    RX_PKTS_512_TO_1023_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_1024_TO_15XX_PKTS],
+	    RX_PKTS_1024_TO_15XX_OCTETS);
+
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_GE_15XX_PKTS],
+	    RX_PKTS_15XX_TO_MAX_OCTETS);
+	XMAC_STAT_DECR(esmp, stat[EFX_MAC_RX_GE_15XX_PKTS],
+	    RX_OVERSIZE_PKTS);
+
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_ERRORS], RX_PKTS);
+	XMAC_STAT_DECR(esmp, stat[EFX_MAC_RX_ERRORS], RX_PKTS_OK);
+
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_FCS_ERRORS],
+	    RX_UNDERSIZE_FCS_ERROR_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_FCS_ERRORS], RX_FCS_ERROR_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_DROP_EVENTS], RX_DROP_EVENTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_SYMBOL_ERRORS], RX_SYMBOL_ERROR);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_ALIGN_ERRORS], RX_ALIGN_ERROR);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_INTERNAL_ERRORS],
+	    RX_INTERNAL_MAC_ERROR);
+
+	EFX_BAR_READO(enp, FR_AZ_RX_NODESC_DROP_REG, &oword);
+	delta = (uint32_t)EFX_OWORD_FIELD(oword, FRF_AZ_RX_NODESC_DROP_CNT);
+	EFSYS_STAT_INCR(&(stat[EFX_MAC_RX_NODESC_DROP_CNT]), delta);
+
+	/* TX */
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_OCTETS], TX_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_UNICST_PKTS], TX_UNICAST_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_MULTICST_PKTS],
+	    TX_MULTICAST_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_BRDCST_PKTS], TX_BROADCAST_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PAUSE_PKTS], TX_PAUSE_PKTS);
+
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_LE_64_PKTS], TX_UNDERSIZE_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_LE_64_PKTS], TX_PKTS_64_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_65_TO_127_PKTS],
+	    TX_PKTS_65_TO_127_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_128_TO_255_PKTS],
+	    TX_PKTS_128_TO_255_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_256_TO_511_PKTS],
+	    TX_PKTS_256_TO_511_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_512_TO_1023_PKTS],
+	    TX_PKTS_512_TO_1023_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_1024_TO_15XX_PKTS],
+	    TX_PKTS_1024_TO_15XX_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_GE_15XX_PKTS],
+	    TX_PKTS_15XX_TO_MAX_OCTETS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_GE_15XX_PKTS],
+	    TX_OVERSIZE_PKTS);
+
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_ERRORS], TX_MAC_SRC_ERR_PKTS);
+	XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_ERRORS], TX_IP_SRC_ERR_PKTS);
+
+	return (0);
+}
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+static			void
+falcon_xmac_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_oword_t oword;
+	boolean_t align_done;
+	boolean_t sync_stat;
+
+	EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_XMAC);
+
+	/* XGXS state irrelevent in XGMII loopback */
+#if EFSYS_OPT_LOOPBACK
+	if (epp->ep_loopback_type == EFX_LOOPBACK_XGMII) {
+		*upp = B_TRUE;
+		return;
+	}
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	EFX_BAR_READO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
+
+	align_done = (EFX_OWORD_FIELD(oword, FRF_AB_XX_ALIGN_DONE) != 0);
+	sync_stat = (EFX_OWORD_FIELD(oword, FRF_AB_XX_SYNC_STAT0) != 0 &&
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_SYNC_STAT1) != 0 &&
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_SYNC_STAT2) != 0 &&
+	    EFX_OWORD_FIELD(oword, FRF_AB_XX_SYNC_STAT3) != 0);
+
+	*upp = (align_done && sync_stat);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_COMMA_DET_CH0, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_COMMA_DET_CH1, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_COMMA_DET_CH2, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_COMMA_DET_CH3, 1);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_CHAR_ERR_CH0, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_CHAR_ERR_CH1, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_CHAR_ERR_CH2, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_CHAR_ERR_CH3, 1);
+
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_DISPERR_CH0, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_DISPERR_CH1, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_DISPERR_CH2, 1);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_DISPERR_CH3, 1);
+
+	EFX_BAR_WRITEO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
+}
+
+			void
+falcon_xmac_poll(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *mac_upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+	boolean_t mac_up = B_TRUE;
+	boolean_t ok;
+
+	/* Poll the mac link state if required */
+	if (epp->ep_mac_poll_needed) {
+		falcon_xmac_downlink_check(enp, &mac_up);
+		if (!mac_up)
+			goto done;
+#if EFSYS_OPT_LOOPBACK
+		/* PHYXS link state irrelevent in MAC loopback */
+		if ((1 << epp->ep_loopback_type) & EFX_LOOPBACK_MAC_MASK)
+			goto done;
+#endif
+		if (epop->epo_uplink_check != NULL) {
+			if (epop->epo_uplink_check(enp, &ok) == 0)
+				mac_up = ok;
+		}
+	}
+
+done:
+	*mac_upp = mac_up;
+
+	/*
+	 * If the XAUI link (and therefore wireside link) are UP, then we
+	 * can use XGMT interrupts rather than polling the link state to spot
+	 * downwards transitions. To spot upwards transitions, we must poll
+	 */
+	epp->ep_mac_poll_needed = !mac_up;
+	if (mac_up) {
+		efx_oword_t oword;
+
+		/* ACK the interrupt */
+		EFX_BAR_READO(enp, FR_AB_XM_MGT_INT_REG, &oword);
+	} else {
+		(void) falcon_xmac_xgxs_reset(enp);
+	}
+}
+
+#endif	/* EFSYS_OPT_MAC_FALCON_XMAC */
--- /dev/null	2013-08-22 18:57:30.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/falcon_xmac.h	2013-08-22 18:57:30.904445763 -0400
@@ -0,0 +1,78 @@
+/*-
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_FALCON_XMAC_H
+#define	_SYS_FALCON_XMAC_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_MAC_FALCON_XMAC
+
+#if EFSYS_OPT_LOOPBACK
+
+#define	FALCON_XMAC_LOOPBACK_MASK					\
+	((1 << EFX_LOOPBACK_XGMII) |					\
+	(1 << EFX_LOOPBACK_XGXS) |					\
+	(1 << EFX_LOOPBACK_XAUI))
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+#define	XMAC_INTR_SUPPORTED	B_TRUE
+
+extern	__checkReturn	int
+falcon_xmac_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+falcon_xmac_reconfigure(
+	__in	efx_nic_t *enp);
+
+#if EFSYS_OPT_MAC_STATS
+
+extern	__checkReturn			int
+falcon_xmac_stats_update(
+	__in				efx_nic_t *enp,
+ 	__in				efsys_mem_t *esmp,
+	__in_ecount(EFX_MAC_NSTATS)	efsys_stat_t *essp,
+	__out_opt			uint32_t *generationp);
+
+#endif
+
+#endif	/* EFSYS_OPT_MAC_XMAC */
+
+extern			void
+falcon_xmac_poll(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *mac_upp);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_FALCON_XMAC_H */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/lm87.c	2013-08-22 18:57:30.989942616 -0400
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "lm87.h"
+#include "lm87_impl.h"
+
+#if EFSYS_OPT_MON_LM87
+
+	__checkReturn	int
+lm87_reset(
+	__in		efx_nic_t *enp)
+{
+	uint8_t devid = enp->en_u.falcon.enu_mon_devid;
+	efx_byte_t byte;
+	int rc;
+
+	/* Check we can communicate with the chip */
+	if ((rc = falcon_i2c_check(enp, devid)) != 0)
+		goto fail1;
+
+	/* Reset the chip */
+	EFX_POPULATE_BYTE_1(byte, INIT, 1);
+	if ((rc = falcon_i2c_write(enp, devid, CONFIG1_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail2;
+
+	/* Check the company identifier and revision */
+	if ((rc = falcon_i2c_read(enp, devid, ID_REG, (caddr_t)&byte, 1)) != 0)
+		goto fail3;
+
+	if (EFX_BYTE_FIELD(byte, EFX_BYTE_0) != ID_DECODE) {
+		rc = ENODEV;
+		goto fail4;
+	}
+
+	if ((rc = falcon_i2c_read(enp, devid, REV_REG, (caddr_t)&byte, 1)) != 0)
+		goto fail5;
+
+	if (EFX_BYTE_FIELD(byte, EFX_BYTE_0) != REV_DECODE) {
+		rc = ENODEV;
+		goto fail6;
+	}
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+lm87_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	uint8_t devid = enp->en_u.falcon.enu_mon_devid;
+	efx_byte_t byte;
+	int rc;
+
+	/* Configure the channel mode to select AIN1/2 rather than FAN1/2 */
+	EFX_POPULATE_BYTE_2(byte, FAN1_AIN1, 1, FAN2_AIN2, 1);
+	if ((rc = falcon_i2c_write(enp, devid, CHANNEL_MODE_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail1;
+
+	/* Mask out all interrupts */
+	EFX_SET_BYTE(byte);
+	if ((rc = falcon_i2c_write(enp, devid, INTERRUPT_MASK1_REG,
+	    (caddr_t)&byte, 1)) != 0)
+		goto fail2;
+	if ((rc = falcon_i2c_write(enp, devid, INTERRUPT_MASK2_REG,
+	    (caddr_t)&byte, 1)) != 0)
+		goto fail3;
+
+	/* Start monitoring */
+	EFX_POPULATE_BYTE_1(byte, START, 1);
+	if ((rc = falcon_i2c_write(enp, devid, CONFIG1_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail4;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_MON_STATS
+
+#define	LM87_STAT_SET(_enp, _mask, _value, _id, _rc)			\
+	do {								\
+		uint8_t devid = enp->en_u.falcon.enu_mon_devid;		\
+		efx_mon_stat_value_t *value =				\
+			(_value) + EFX_MON_STAT_ ## _id;		\
+		efx_byte_t byte;					\
+									\
+		if (((_rc) = falcon_i2c_read((_enp), devid, 		\
+		    VALUE_ ## _id ## _REG, (caddr_t)&byte, 1)) == 0) {	\
+			uint8_t val = EFX_BYTE_FIELD(byte, EFX_BYTE_0);	\
+			value->emsv_value = (uint16_t)val;		\
+			value->emsv_state = 0;				\
+		}							\
+									\
+		(_mask) |= (1 << (EFX_MON_STAT_ ## _id));		\
+		_NOTE(CONSTANTCONDITION)				\
+	} while (B_FALSE)
+
+	__checkReturn			int
+lm87_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values)
+{
+	uint32_t mask = 0;
+	int rc;
+
+	_NOTE(ARGUNUSED(esmp))
+
+	LM87_STAT_SET(enp, mask, values, 2_5V, rc);
+	if (rc != 0)
+		goto fail1;
+
+	LM87_STAT_SET(enp, mask, values, VCCP1, rc);
+	if (rc != 0)
+		goto fail2;
+
+	LM87_STAT_SET(enp, mask, values, VCC, rc);
+	if (rc != 0)
+		goto fail3;
+
+	LM87_STAT_SET(enp, mask, values, 5V, rc);
+	if (rc != 0)
+		goto fail4;
+
+	LM87_STAT_SET(enp, mask, values, 12V, rc);
+	if (rc != 0)
+		goto fail5;
+
+	LM87_STAT_SET(enp, mask, values, VCCP2, rc);
+	if (rc != 0)
+		goto fail6;
+
+	LM87_STAT_SET(enp, mask, values, EXT_TEMP, rc);
+	if (rc != 0)
+		goto fail7;
+
+	LM87_STAT_SET(enp, mask, values, INT_TEMP, rc);
+	if (rc != 0)
+		goto fail8;
+
+	LM87_STAT_SET(enp, mask, values, AIN1, rc);
+	if (rc != 0)
+		goto fail9;
+
+	LM87_STAT_SET(enp, mask, values, AIN2, rc);
+	if (rc != 0)
+		goto fail10;
+
+	EFSYS_ASSERT3U(mask, ==, LM87_STAT_MASK);
+
+	return (0);
+
+fail10:
+	EFSYS_PROBE(fail10);
+fail9:
+	EFSYS_PROBE(fail9);
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_MON_STATS */
+
+#endif	/* EFSYS_OPT_MON_LM87 */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/lm87.h	2013-08-22 18:57:31.078491415 -0400
@@ -0,0 +1,78 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_LM87_H
+#define	_SYS_LM87_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_MON_LM87
+
+#define	LM87_DEVID 0x2e
+
+extern	__checkReturn	int
+lm87_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+lm87_reconfigure(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_MON_STATS
+
+/* START MKCONFIG GENERATED Lm87MonitorHeaderStatsMask ebc33ca917ba24d7 */
+#define	LM87_STAT_MASK \
+	(1ULL << EFX_MON_STAT_2_5V) | \
+	(1ULL << EFX_MON_STAT_VCCP1) | \
+	(1ULL << EFX_MON_STAT_VCC) | \
+	(1ULL << EFX_MON_STAT_5V) | \
+	(1ULL << EFX_MON_STAT_12V) | \
+	(1ULL << EFX_MON_STAT_VCCP2) | \
+	(1ULL << EFX_MON_STAT_EXT_TEMP) | \
+	(1ULL << EFX_MON_STAT_INT_TEMP) | \
+	(1ULL << EFX_MON_STAT_AIN1) | \
+	(1ULL << EFX_MON_STAT_AIN2)
+
+/* END MKCONFIG GENERATED Lm87MonitorHeaderStatsMask */
+
+extern	__checkReturn			int
+lm87_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values);
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+#endif	/* EFSYS_OPT_MON_LM87 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_LM87_H */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/lm87_impl.h	2013-08-22 18:57:31.163015479 -0400
@@ -0,0 +1,79 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_LM87_IMPL_H
+#define	_SYS_LM87_IMPL_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_MON_LM87
+
+#define	TEST_REG 0x15
+#define	SHUTDOWN_LBN 0
+#define	SHUTDOWN_WIDTH 1
+
+#define	CHANNEL_MODE_REG 0x16
+#define	FAN1_AIN1_LBN 0
+#define	FAN1_AIN1_WIDTH 1
+#define	FAN2_AIN2_LBN 1
+#define	FAN2_AIN2_WIDTH 1
+
+#define	CONFIG1_REG 0x40
+#define	START_LBN 0
+#define	START_WIDTH 1
+#define	INT_EN_LBN 1
+#define	INT_EN_WIDTH 1
+#define	INIT_LBN 7
+#define	INIT_WIDTH 1
+
+#define	INTERRUPT_MASK1_REG 0x43
+#define	INTERRUPT_MASK2_REG 0x44
+
+#define	VALUE_2_5V_REG 0x20
+#define	VALUE_VCCP1_REG 0x21
+#define	VALUE_VCC_REG 0x22
+#define	VALUE_5V_REG 0x23
+#define	VALUE_12V_REG 0x24
+#define	VALUE_VCCP2_REG 0x25
+#define	VALUE_EXT_TEMP_REG 0x26
+#define	VALUE_INT_TEMP_REG 0x27
+#define	VALUE_AIN1_REG 0x28
+#define	VALUE_AIN2_REG 0x29
+
+#define	ID_REG 0x3e
+#define	ID_DECODE 0x02
+
+#define	REV_REG 0x3f
+#define	REV_DECODE 0x06
+
+#endif	/* EFSYS_OPT_MON_LM87 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_LM87_IMPL_H */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/max6647.c	2013-08-22 18:57:31.248142187 -0400
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "max6647.h"
+#include "max6647_impl.h"
+
+#if EFSYS_OPT_MON_MAX6647
+
+	__checkReturn	int
+max6647_reset(
+	__in		efx_nic_t *enp)
+{
+	uint8_t devid = enp->en_u.falcon.enu_mon_devid;
+	efx_byte_t byte;
+	int rc;
+
+	if ((rc = falcon_i2c_check(enp, devid)) != 0)
+		goto fail1;
+
+	/* Reset the chip */
+	EFX_POPULATE_BYTE_2(byte, MASK, 1, NRUN, 1);
+	if ((rc = falcon_i2c_write(enp, devid, WCA_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail2;
+
+	EFSYS_SPIN(10);
+
+	EFX_POPULATE_BYTE_2(byte, MASK, 1, NRUN, 0);
+	if ((rc = falcon_i2c_write(enp, devid, WCA_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail3;
+
+	/* Check the company identifier and revision */
+	if ((rc = falcon_i2c_read(enp, devid, MFID_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail2;
+
+	if (EFX_BYTE_FIELD(byte, EFX_BYTE_0) != MFID_DECODE) {
+		rc = ENODEV;
+		goto fail3;
+	}
+
+	if ((rc = falcon_i2c_read(enp, devid, REVID_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail4;
+
+	if (EFX_BYTE_FIELD(byte, EFX_BYTE_0) != REVID_DECODE) {
+		rc = ENODEV;
+		goto fail5;
+	}
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+max6647_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	uint8_t devid = enp->en_u.falcon.enu_mon_devid;
+	efx_byte_t byte;
+	int rc;
+
+	/* Clear any latched status */
+	if ((rc = falcon_i2c_read(enp, devid, RSL_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail1;
+
+	/* Override the default alert limit */
+	EFX_POPULATE_BYTE_1(byte, EFX_BYTE_0, 90);
+	if ((rc = falcon_i2c_write(enp, devid, WLHO_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail2;
+
+	/* Read it back and verify */
+	if ((rc = falcon_i2c_read(enp, devid, RLHN_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail3;
+
+	if (EFX_BYTE_FIELD(byte, EFX_BYTE_0) != 90) {
+		rc = EFAULT;
+		goto fail4;
+	}
+
+	/* Enable the alert signal */
+	EFX_POPULATE_BYTE_2(byte, MASK, 0, NRUN, 0);
+	if ((rc = falcon_i2c_write(enp, devid, WCA_REG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail5;
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_MON_STATS
+
+#define	MAX6647_STAT_SET(_enp, _value, _id, _rc)			\
+	do {								\
+		uint8_t devid = enp->en_u.falcon.enu_mon_devid;		\
+		efx_byte_t byte;					\
+									\
+		if (((_rc) = falcon_i2c_read((_enp), devid,		\
+		    _id ## _REG, (caddr_t)&byte, 1)) == 0) {		\
+			(_value)->emsv_value =				\
+				(uint16_t)EFX_BYTE_FIELD(byte, 		\
+							EFX_BYTE_0);	\
+			(_value)->emsv_state = 0;			\
+		}							\
+		_NOTE(CONSTANTCONDITION)				\
+	} while (B_FALSE)
+
+	__checkReturn			int
+max6647_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values)
+{
+	int rc;
+
+	_NOTE(ARGUNUSED(esmp))
+
+	MAX6647_STAT_SET(enp, values + EFX_MON_STAT_INT_TEMP, RLTS, rc);
+	if (rc != 0)
+		goto fail1;
+
+	MAX6647_STAT_SET(enp, values + EFX_MON_STAT_EXT_TEMP, RRTE, rc);
+	if (rc != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_MON_STATS */
+
+#endif	/* EFSYS_OPT_MON_MAX6647 */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/max6647.h	2013-08-22 18:57:31.333115733 -0400
@@ -0,0 +1,71 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_MAX6647_H
+#define	_SYS_MAX6647_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_MON_MAX6647
+
+#define	MAX6646_DEVID 0x4d
+#define	MAX6647_DEVID 0x4e
+
+extern	__checkReturn	int
+max6647_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+max6647_reconfigure(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_MON_STATS
+
+/* START MKCONFIG GENERATED Max6647MonitorHeaderStatsMask b4d91f25c4d293e1 */
+#define	MAX6647_STAT_MASK \
+	(1ULL << EFX_MON_STAT_INT_TEMP) | \
+	(1ULL << EFX_MON_STAT_EXT_TEMP)
+
+/* END MKCONFIG GENERATED Max6647MonitorHeaderStatsMask */
+
+extern	__checkReturn			int
+max6647_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values);
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+#endif	/* EFSYS_OPT_MON_MAX6647 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_MAX6647_H */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/max6647_impl.h	2013-08-22 18:57:31.418061347 -0400
@@ -0,0 +1,109 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_MAX6647_IMPL_H
+#define	_SYS_MAX6647_IMPL_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_MON_MAX6647 || EFSYS_OPT_PHY_SFX7101
+
+#define	RLTS_REG 0x00
+
+#define	RRTE_REG 0x01
+
+#define	RSL_REG 0x02
+#define	BUSY_LBN 7
+#define	BUSY_WIDTH 1
+#define	LHIGH_LBN 6
+#define	LHIGH_WIDTH 1
+#define	LLOW_LBN 5
+#define	LLOW_WIDTH 1
+#define	RHIGH_LBN 4
+#define	RHIGH_WIDTH 1
+#define	RLOW_LBN 3
+#define	RLOW_WIDTH 1
+#define	FAULT_LBN 2
+#define	FAULT_WIDTH 1
+#define	EOT_LBN 1
+#define	EOT_WIDTH 1
+#define	IOT_LBN 0
+#define	IOT_WIDTH 1
+
+#define	RCL_REG 0x03
+#define	MASK_LBN 7
+#define	MASK_WIDTH 1
+#define	NRUN_LBN 6
+#define	NRUN_WIDTH 1
+
+#define	RCRA_REG 0x04
+
+#define	RLHN_REG 0x05
+
+#define	RLLI_REG 0x06
+
+#define	RRHI_REG 0x07
+
+#define	RRLS_REG 0x08
+
+#define	WCA_REG 0x09
+
+#define	WCRW_REG 0x0a
+
+#define	WLHO_REG 0x0b
+
+#define	WRHA_REG 0x0c
+
+#define	WRLN_REG 0x0e
+
+#define	OSHT_REG 0x0f
+
+#define	REET_REG 0x10
+
+#define	RIET_REG 0x11
+
+#define	RWOE_REG 0x19
+
+#define	RWOI_REG 0x20
+
+#define	HYS_REG 0x21
+
+#define	QUEUE_REG 0x22
+
+#define	MFID_REG 0xfe
+#define	MFID_DECODE 0x4d
+
+#define	REVID_REG 0xff
+#define	REVID_DECODE 0x59
+
+#endif	/* EFSYS_OPT_MON_MAX6647 || EFSYS_OPT_PHY_SFX7101 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_MAX6647_IMPL_H */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/nullmon.c	2013-08-22 18:57:31.503028668 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "nullmon.h"
+
+#if EFSYS_OPT_MON_NULL
+
+	__checkReturn	int
+nullmon_reset(
+	__in		efx_nic_t *enp)
+{
+	_NOTE(ARGUNUSED(enp))
+
+	return (0);
+}
+
+	__checkReturn	int
+nullmon_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	_NOTE(ARGUNUSED(enp))
+
+	return (0);
+}
+
+#if EFSYS_OPT_MON_STATS
+
+	__checkReturn			int
+nullmon_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values)
+{
+	_NOTE(ARGUNUSED(enp, esmp, values))
+
+	return (ENOTSUP);
+}
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+#endif	/* EFSYS_OPT_MON_NULL */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/nullmon.h	2013-08-22 18:57:31.587246871 -0400
@@ -0,0 +1,65 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_NULLMON_H
+#define	_SYS_NULLMON_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_MON_NULL
+
+#if EFSYS_OPT_MON_STATS
+#define	NULLMON_NSTATS	0
+#endif
+
+extern	__checkReturn	int
+nullmon_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+nullmon_reconfigure(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_MON_STATS
+
+extern	__checkReturn			int
+nullmon_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values);
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+#endif	/* EFSYS_OPT_MON_NULL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_NULLMON_H */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/nullphy.c	2013-08-22 18:57:31.672165739 -0400
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "nullphy.h"
+#include "nullphy_impl.h"
+
+#if EFSYS_OPT_PHY_NULL
+
+	__checkReturn	int
+nullphy_reset(
+	__in		efx_nic_t *enp)
+{
+	_NOTE(ARGUNUSED(enp))
+
+	enp->en_reset_flags |= EFX_RESET_PHY;
+
+	return (0);
+}
+
+	__checkReturn	int
+nullphy_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	efx_word_t check;
+	int rc;
+
+	_NOTE(ARGUNUSED(enp))
+
+	EFX_POPULATE_WORD_3(word, HOSTPORT_EQ, 1, PORTSEL, 0, CX4uC_RESET, 1);
+
+	if ((rc = falcon_i2c_send(enp, PCF8575, (caddr_t)&word.ew_byte[0],
+	    sizeof (word.ew_byte) / sizeof (efx_byte_t))) != 0)
+		goto fail1;
+
+	if ((rc = falcon_i2c_recv(enp, PCF8575, (caddr_t)&check.ew_byte[0],
+	    sizeof (check.ew_byte) / sizeof (efx_byte_t))) != 0)
+		goto fail2;
+
+	if (EFX_WORD_FIELD(check, EFX_WORD_0) !=
+	    EFX_WORD_FIELD(word, EFX_WORD_0)) {
+		rc = EFAULT;
+		goto fail3;
+	}
+
+	EFSYS_ASSERT3U(epp->ep_adv_cap_mask, ==, NULLPHY_ADV_CAP_MASK);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+nullphy_verify(
+	__in		efx_nic_t *enp)
+{
+	_NOTE(ARGUNUSED(enp))
+
+	return (ENOTSUP);
+}
+
+	__checkReturn	int
+nullphy_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+
+	*modep = EFX_LINK_10000FDX;
+	*fcntlp = epp->ep_fcntl;
+	*lp_cap_maskp = NULLPHY_ADV_CAP_MASK;
+
+	return (0);
+}
+
+	__checkReturn	int
+nullphy_lp_cap_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *maskp)
+{
+	_NOTE(ARGUNUSED(enp, maskp))
+
+	return (ENOTSUP);
+}
+
+	__checkReturn	int
+nullphy_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip)
+{
+	_NOTE(ARGUNUSED(enp, ouip))
+
+	return (ENOTSUP);
+}
+
+#if EFSYS_OPT_PHY_STATS
+
+	__checkReturn			int
+nullphy_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	_NOTE(ARGUNUSED(enp, esmp, stat))
+
+	return (ENOTSUP);
+}
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+		const char __cs *
+nullphy_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	_NOTE(ARGUNUSED(enp, id))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (NULL);
+}
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn	int
+nullphy_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp)
+{
+	_NOTE(ARGUNUSED(enp, id, flags, valp))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+
+	__checkReturn	int
+nullphy_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val)
+{
+	_NOTE(ARGUNUSED(enp, id, val))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#endif	/* EFSYS_OPT_PHY_NULL */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/nullphy.h	2013-08-22 18:57:31.759281226 -0400
@@ -0,0 +1,122 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_NULLPHY_H
+#define	_SYS_NULLPHY_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_NULL
+
+#define	NULLPHY_LOOPBACK_MASK						\
+	    FALCON_XMAC_LOOPBACK_MASK
+
+#define	NULLPHY_LED_MASK	0
+
+#define	NULLPHY_NSTATS		0
+
+#define	NULLPHY_NPROPS		0
+
+#define	NULLPHY_ADV_CAP_MASK						\
+	    ((1 << EFX_PHY_CAP_10000FDX) |				\
+	    (1 << EFX_PHY_CAP_PAUSE))
+
+#define	NULLPHY_ADV_CAP_PERM	0
+
+#define	NULLPHY_BIST_MASK	0
+
+extern	__checkReturn	int
+nullphy_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+nullphy_reconfigure(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+nullphy_verify(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+nullphy_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp);
+
+extern	__checkReturn	int
+nullphy_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip);
+
+#if EFSYS_OPT_PHY_STATS
+
+#define	NULLPHY_STAT_MASK	0
+
+extern	__checkReturn			int
+nullphy_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat);
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+nullphy_prop_name(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id);
+
+#endif
+
+extern	__checkReturn	int
+nullphy_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp);
+
+extern	__checkReturn	int
+nullphy_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val);
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#endif	/* EFSYS_OPT_PHY_NULL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_NULLPHY_H */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/nullphy_impl.h	2013-08-22 18:57:31.843259149 -0400
@@ -0,0 +1,69 @@
+/*-
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_NULLPHY_IMPL_H
+#define	_SYS_NULLPHY_IMPL_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_NULL
+
+/* IO expender */
+#define	PCF8575	0x20
+
+#define	PORT0_EXTLOOP_LBN 0
+#define	PORT0_EXTLOOP_WIDTH 1
+#define	PORT1_EXTLOOP_LBN 1
+#define	PORT1_EXTLOOP_WIDTH 1
+#define	HOSTPORT_LOOP_LBN 2
+#define	HOSTPORT_LOOP_WIDTH 1
+#define	BCAST_LBN 3
+#define	BCAST_WIDTH 1
+#define	PORT0_EQ_LBN 4
+#define	PORT0_EQ_WIDTH 1
+#define	PORT1_EQ_LBN 5
+#define	PORT1_EQ_WIDTH 1
+#define	HOSTPORT_EQ_LBN 6
+#define	HOSTPORT_EQ_WIDTH 1
+#define	PORTSEL_LBN 7
+#define	PORTSEL_WIDTH 1
+#define	PORT0_PRE_LBN 8
+#define	PORT0_PRE_WIDTH 2
+#define	PORT1_PRE_LBN 10
+#define	PORT1_PRE_WIDTH 2
+#define	HOSTPORT_PRE_LBN 12
+#define	HOSTPORT_PRE_WIDTH 2
+#define	CX4uC_RESET_LBN 15
+#define	CX4uC_RESET_WIDTH 1
+
+#endif	/* EFSYS_OPT_PHY_NULL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_NULLPHY_IMPL_H */
--- /dev/null	2013-08-22 18:57:31.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/qt2022c2.c	2013-08-22 18:57:31.928555410 -0400
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "xphy.h"
+#include "qt2022c2.h"
+#include "qt2022c2_impl.h"
+
+#if EFSYS_OPT_PHY_QT2022C2
+
+static	__checkReturn	int
+qt2022c2_led_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t led1;
+	efx_word_t led2;
+	efx_word_t led3;
+	int rc;
+
+#if EFSYS_OPT_PHY_LED_CONTROL
+
+	switch (epp->ep_phy_led_mode) {
+	case EFX_PHY_LED_DEFAULT:
+		EFX_POPULATE_WORD_2(led1, PMA_PMD_LED_CFG, LED_CFG_LSA_DECODE,
+		    PMA_PMD_LED_PATH, LED_PATH_RX_DECODE);
+		EFX_POPULATE_WORD_2(led2, PMA_PMD_LED_CFG, LED_CFG_LSA_DECODE,
+		    PMA_PMD_LED_PATH, LED_PATH_TX_DECODE);
+		EFX_POPULATE_WORD_1(led3, PMA_PMD_LED_CFG, LED_CFG_OFF_DECODE);
+		break;
+
+	case EFX_PHY_LED_OFF:
+		EFX_POPULATE_WORD_1(led1, PMA_PMD_LED_CFG, LED_CFG_OFF_DECODE);
+		EFX_POPULATE_WORD_1(led2, PMA_PMD_LED_CFG, LED_CFG_OFF_DECODE);
+		EFX_POPULATE_WORD_1(led3, PMA_PMD_LED_CFG, LED_CFG_OFF_DECODE);
+		break;
+
+	case EFX_PHY_LED_ON:
+		EFX_POPULATE_WORD_1(led1, PMA_PMD_LED_CFG, LED_CFG_ON_DECODE);
+		EFX_POPULATE_WORD_1(led2, PMA_PMD_LED_CFG, LED_CFG_ON_DECODE);
+		EFX_POPULATE_WORD_1(led3, PMA_PMD_LED_CFG, LED_CFG_ON_DECODE);
+		break;
+
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		break;
+	}
+
+#else	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	EFX_POPULATE_WORD_2(led1, PMA_PMD_LED_CFG, LED_CFG_LSA_DECODE,
+	    PMA_PMD_LED_PATH, LED_PATH_RX_DECODE);
+	EFX_POPULATE_WORD_2(led2, PMA_PMD_LED_CFG, LED_CFG_LSA_DECODE,
+	    PMA_PMD_LED_PATH, LED_PATH_TX_DECODE);
+	EFX_POPULATE_WORD_1(led3, PMA_PMD_LED_CFG, LED_CFG_OFF_DECODE);
+
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_LED1_REG, &led1)) != 0)
+		goto fail1;
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_LED2_REG, &led2)) != 0)
+		goto fail2;
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_LED3_REG, &led3)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail2);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_LOOPBACK
+static	__checkReturn	int
+qt2022c2_loopback_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS: {
+		efx_word_t word;
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+		    PHY_XS_VENDOR0_REG, &word)) != 0)
+			goto fail1;
+
+		EFX_SET_WORD_FIELD(word, XAUI_SYSTEM_LOOPBACK, 1);
+
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+		    PHY_XS_VENDOR0_REG, &word)) != 0)
+			goto fail2;
+
+		break;
+	}
+	case EFX_LOOPBACK_PCS:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PCS_MMD,
+		    B_TRUE)) != 0)
+			goto fail1;
+
+		break;
+
+	case EFX_LOOPBACK_PMA_PMD:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PMA_PMD_MMD,
+		    B_TRUE)) != 0)
+			goto fail1;
+
+		break;
+
+	default:
+		break;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	__checkReturn	int
+qt2022c2_reset(
+	__in		efx_nic_t *enp)
+{
+	/* Pull the external reset line */
+	falcon_nic_phy_reset(enp);
+
+	return (0);
+}
+
+	__checkReturn	int
+qt2022c2_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_pkg_wait(enp, epp->ep_port, QT2022C2_MMD_MASK)) != 0)
+		goto fail1;
+
+	if ((rc = qt2022c2_led_cfg(enp)) != 0)
+		goto fail2;
+
+	EFSYS_ASSERT3U(epp->ep_adv_cap_mask, ==, QT2022C2_ADV_CAP_MASK);
+
+#if EFSYS_OPT_LOOPBACK
+	if ((rc = qt2022c2_loopback_cfg(enp)) != 0)
+		goto fail3;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	return (0);
+
+#if EFSYS_OPT_LOOPBACK
+fail3:
+	EFSYS_PROBE(fail3);
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2022c2_verify(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_pkg_verify(enp, epp->ep_port, QT2022C2_MMD_MASK)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2022c2_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if (epp->ep_mac_type != EFX_MAC_FALCON_XMAC) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail2;
+
+	*upp = ((EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0));
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2022c2_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	boolean_t up;
+	int rc;
+
+#if EFSYS_OPT_LOOPBACK
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS:
+		rc = xphy_mmd_fault(enp, epp->ep_port, &up);
+		if (rc != 0)
+			goto fail1;
+
+		*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+		goto done;
+
+	case EFX_LOOPBACK_PCS:
+		rc = xphy_mmd_check(enp, epp->ep_port, PHY_XS_MMD, &up);
+		if (rc != 0)
+			goto fail1;
+
+		*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+		goto done;
+
+	default:
+		break;
+	}
+#endif /* EFSYS_OPT_LOOPBACK */
+
+	if ((rc = xphy_mmd_check(enp, epp->ep_port, PCS_MMD, &up)) != 0)
+		goto fail1;
+
+	*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+
+#if EFSYS_OPT_LOOPBACK
+done:
+#endif
+	*fcntlp = epp->ep_fcntl;
+	*lp_cap_maskp = epp->ep_lp_cap_mask;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2022c2_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, ouip)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_PHY_STATS
+
+#define	QT2022C2_STAT_SET(_stat, _mask, _id, _val)			\
+	do {								\
+		(_mask) |= (1 << (_id));				\
+		(_stat)[_id] = (uint32_t)(_val);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+static	__checkReturn			int
+qt2022c2_pma_pmd_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_LINK_UP,
+	    (EFX_WORD_FIELD(word, PMA_PMD_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_RX_FAULT) != 0) ? 1 : 0);
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_TX_FAULT) != 0) ? 1 : 0);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+qt2022c2_pcs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PCS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_RX_FAULT) != 0) ? 1 : 0);
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_10GBASE_R_STATUS2_REG, &word)) != 0)
+		goto fail3;
+
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BER,
+	    EFX_WORD_FIELD(word, PCS_BER));
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BLOCK_ERRORS,
+	    EFX_WORD_FIELD(word, PCS_ERR));
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+qt2022c2_phy_xs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PHY_XS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_RX_FAULT) != 0) ? 1 : 0);
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail3;
+
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_ALIGN,
+	    (EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) ? 1 : 0);
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_A,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) ? 1 : 0);
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_B,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) ? 1 : 0);
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_C,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) ? 1 : 0);
+	QT2022C2_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_D,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0) ? 1 : 0);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+qt2022c2_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint32_t oui;
+	uint64_t mask = 0;
+	int rc;
+
+	_NOTE(ARGUNUSED(esmp))
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, &oui)) != 0)
+		goto fail1;
+
+	QT2022C2_STAT_SET(stat, mask, EFX_PHY_STAT_OUI, oui);
+
+	if ((rc = qt2022c2_pma_pmd_stats_update(enp, &mask, stat)) != 0)
+		goto fail2;
+
+	if ((rc = qt2022c2_pcs_stats_update(enp, &mask, stat)) != 0)
+		goto fail3;
+
+	if ((rc = qt2022c2_phy_xs_stats_update(enp, &mask, stat)) != 0)
+		goto fail4;
+
+	/* Ensure all the supported statistics are up to date */
+	EFSYS_ASSERT(mask == encp->enc_phy_stat_mask);
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+		const char __cs *
+qt2022c2_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	_NOTE(ARGUNUSED(enp, id))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (NULL);
+}
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn	int
+qt2022c2_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp)
+{
+	_NOTE(ARGUNUSED(enp, id, flags, valp))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+
+	__checkReturn	int
+qt2022c2_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val)
+{
+	_NOTE(ARGUNUSED(enp, id, val))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#endif	/* EFSYS_OPT_PHY_QT2022C2 */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/qt2022c2.h	2013-08-22 18:57:32.018324887 -0400
@@ -0,0 +1,150 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_QT2022C2_H
+#define	_SYS_QT2022C2_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_QT2022C2
+
+#define	QT2022C2_LOOPBACK_MASK						\
+	    ((1 << EFX_LOOPBACK_PHY_XS) |				\
+	    (1 << EFX_LOOPBACK_PCS) |					\
+	    (1 << EFX_LOOPBACK_PMA_PMD) |				\
+	    FALCON_XMAC_LOOPBACK_MASK)
+
+#define	QT2022C2_LED_MASK						\
+	    ((1 << EFX_PHY_LED_OFF) |					\
+	    (1 << EFX_PHY_LED_ON))
+
+#define	QT2022C2_NPROPS		0
+
+#define	QT2022C2_ADV_CAP_MASK						\
+	    ((1 << EFX_PHY_CAP_10000FDX) |				\
+	    (1 << EFX_PHY_CAP_PAUSE))
+
+#define	QT2022C2_ADV_CAP_PERM	0
+
+#define	QT2022C2_BIST_MASK	0
+
+extern	__checkReturn	int
+qt2022c2_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+qt2022c2_reconfigure(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+qt2022c2_verify(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+qt2022c2_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp);
+
+extern	__checkReturn	int
+qt2022c2_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp);
+
+extern	__checkReturn	int
+qt2022c2_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip);
+
+#if EFSYS_OPT_PHY_STATS
+
+/* START MKCONFIG GENERATED Qt2022c2PhyHeaderStatsMask 5655dc14f9b46071 */
+#define	QT2022C2_STAT_MASK \
+	(1ULL << EFX_PHY_STAT_OUI) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PCS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_BER) | \
+	(1ULL << EFX_PHY_STAT_PCS_BLOCK_ERRORS) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_ALIGN) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_A) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_B) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_C) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_D)
+
+/* END MKCONFIG GENERATED Qt2022c2PhyHeaderStatsMask */
+
+extern	__checkReturn			int
+qt2022c2_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat);
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+qt2022c2_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id);
+
+#endif
+
+extern	__checkReturn	int
+qt2022c2_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp);
+
+extern	__checkReturn	int
+qt2022c2_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val);
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#endif	/* EFSYS_OPT_PHY_QT2022C2 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_QT2022C2_H */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/qt2022c2_impl.h	2013-08-22 18:57:32.105364881 -0400
@@ -0,0 +1,66 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_QT2022C2_IMPL_H
+#define	_SYS_QT2022C2_IMPL_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_QT2022C2
+
+#define	QT2022C2_MMD_MASK						\
+	    ((1 << PMA_PMD_MMD) |					\
+	    (1 << PCS_MMD) |						\
+	    (1 << PHY_XS_MMD))
+
+#define	PMA_PMD_LED1_REG 0xd006	/* Green */
+#define	PMA_PMD_LED2_REG 0xd007	/* Amber */
+#define	PMA_PMD_LED3_REG 0xd008 /* Red */
+
+#define	PMA_PMD_LED_CFG_LBN 0
+#define	PMA_PMD_LED_CFG_WIDTH 3
+#define	LED_CFG_LS_DECODE 0x1
+#define	LED_CFG_LA_DECODE 0x2
+#define	LED_CFG_LSA_DECODE 0x3
+#define	LED_CFG_OFF_DECODE 0x4
+#define	LED_CFG_ON_DECODE 0x5
+#define	PMA_PMD_LED_PATH_LBN 3
+#define	PMA_PMD_LED_PATH_WIDTH 1
+#define	LED_PATH_TX_DECODE 0x0
+#define	LED_PATH_RX_DECODE 0x1
+
+#define	PHY_XS_VENDOR0_REG 0xc000
+#define	XAUI_SYSTEM_LOOPBACK_LBN 14
+#define	XAUI_SYSTEM_LOOPBACK_WIDTH 1
+
+#endif	/* EFSYS_OPT_PHY_QT2022C2 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_QT2022C2_IMPL_H */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/qt2025c.c	2013-08-22 18:57:32.190022358 -0400
@@ -0,0 +1,1117 @@
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "xphy.h"
+#include "qt2025c.h"
+#include "qt2025c_impl.h"
+#include "falcon_impl.h"
+
+#if EFSYS_OPT_PHY_QT2025C
+
+static	__checkReturn	int
+qt2025c_led_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t led1;
+	efx_word_t led2;
+	int rc;
+
+#if EFSYS_OPT_PHY_LED_CONTROL
+
+	switch (epp->ep_phy_led_mode) {
+	case EFX_PHY_LED_DEFAULT:
+		EFX_POPULATE_WORD_2(led1, PMA_PMD_LED_CFG, LED_CFG_LA_DECODE,
+		    PMA_PMD_LED_PATH, LED_PATH_RX_DECODE);
+		EFX_POPULATE_WORD_2(led2, PMA_PMD_LED_CFG, LED_CFG_LS_DECODE,
+		    PMA_PMD_LED_PATH, LED_PATH_RX_DECODE);
+		break;
+
+	case EFX_PHY_LED_OFF:
+		EFX_POPULATE_WORD_1(led1, PMA_PMD_LED_CFG, LED_CFG_OFF_DECODE);
+		EFX_POPULATE_WORD_1(led2, PMA_PMD_LED_CFG, LED_CFG_OFF_DECODE);
+		break;
+
+	case EFX_PHY_LED_ON:
+		EFX_POPULATE_WORD_1(led1, PMA_PMD_LED_CFG, LED_CFG_ON_DECODE);
+		EFX_POPULATE_WORD_1(led2, PMA_PMD_LED_CFG, LED_CFG_ON_DECODE);
+		break;
+
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		break;
+	}
+
+#else	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	EFX_POPULATE_WORD_2(led1, PMA_PMD_LED_CFG, LED_CFG_LA_DECODE,
+	    PMA_PMD_LED_PATH, LED_PATH_RX_DECODE);
+	EFX_POPULATE_WORD_2(led2, PMA_PMD_LED_CFG, LED_CFG_LS_DECODE,
+	    PMA_PMD_LED_PATH, LED_PATH_RX_DECODE);
+
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_LED1_REG, &led1)) != 0)
+		goto fail1;
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_LED2_REG, &led2)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_LOOPBACK
+static	__checkReturn	int
+qt2025c_loopback_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* Set static mode appropriately */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_FTX_CTRL2_REG, &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, FTX_STATIC,
+	    (epp->ep_loopback_type == EFX_LOOPBACK_PCS ||
+	    epp->ep_loopback_type == EFX_LOOPBACK_PMA_PMD) ? 1 : 0);
+
+	/* Set static mode appropriately */
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_FTX_CTRL2_REG, &word)) != 0)
+		goto fail2;
+
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS: {
+		efx_word_t xsword;
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+		    XGXS_VENDOR_SPECIFIC_1_REG, &xsword)) != 0)
+			goto fail3;
+
+		EFX_SET_WORD_FIELD(xsword, XGXS_SYSLPBK, 1);
+
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+		    XGXS_VENDOR_SPECIFIC_1_REG, &xsword)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case EFX_LOOPBACK_PCS:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PCS_MMD,
+		    B_TRUE)) != 0)
+			goto fail3;
+
+		break;
+
+	case EFX_LOOPBACK_PMA_PMD:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PMA_PMD_MMD,
+		    B_TRUE)) != 0)
+			goto fail3;
+
+		break;
+
+	default:
+		break;
+	}
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+static	__checkReturn	int
+qt2025c_version_get(
+	__in		efx_nic_t *enp,
+	__out_ecount(4)	uint8_t version[])
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    FW_VERSION1_REG, &word)) != 0)
+		goto fail1;
+
+	version[0] = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0) >> 4;
+	version[1] = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0) & 0x0f;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    FW_VERSION2_REG, &word)) != 0)
+		goto fail2;
+
+	version[2] = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    FW_VERSION3_REG, &word)) != 0)
+		goto fail3;
+
+	version[3] = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+/*
+ * Convinience function so that the large number of MDIO writes
+ * in qt2025c_select_phy_mode are condensed, and easier to compare
+ * directly with the data sheet.
+ */
+static	__checkReturn	int
+qt2025c_mdio_write(
+	__in		efx_nic_t *enp,
+	__in		uint8_t mmd,
+	__in		uint16_t addr,
+	__in		uint16_t value)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	EFX_POPULATE_WORD_1(word, EFX_WORD_0, value);
+	rc = falcon_mdio_write(enp, epp->ep_port, mmd, addr, &word);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+qt2025c_restart_firmware(
+	__in		efx_nic_t *enp)
+{
+	int rc;
+
+	/* Restart microcontroller execution of firmware from RAM */
+	if ((rc = qt2025c_mdio_write(enp, 3, 0xe854, 0x00c0)) != 0)
+		goto fail1;
+
+	if ((rc = qt2025c_mdio_write(enp, 3, 0xe854, 0x0040)) != 0)
+		goto fail2;
+
+	EFSYS_SLEEP(50000);	/* 50ms */
+
+	return (0);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+qt2025c_wait_heartbeat(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int count;
+	uint8_t heartb;
+	int rc;
+
+	/* Read the initial heartbeat */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    FW_HEARTBEAT_REG, &word)) != 0)
+		goto fail1;
+
+	heartb = EFX_WORD_FIELD(word, FW_HEARTB);
+
+	/* Wait for the heartbeat to start updating */
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		EFSYS_SLEEP(100000);	/* 100ms */
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    FW_HEARTBEAT_REG, &word)) != 0)
+			goto fail2;
+
+		if (EFX_WORD_FIELD(word, FW_HEARTB) != heartb)
+			return (0);
+
+	} while (++count < 50);		/* For up to 5s */
+
+	rc = ENOTACTIVE;
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+qt2025c_wait_firmware(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int count;
+	uint16_t status;
+	int rc;
+
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		EFSYS_SLEEP(100000);	/* 100ms */
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    UC8051_STATUS_REG, &word)) != 0)
+			goto fail1;
+
+		status = EFX_WORD_FIELD(word, UC_STATUS);
+		if (status >= UC_STATUS_FW_SAVE_DECODE)
+			return (0);
+
+	} while (++count < 25);		/* For up to 2.5s */
+
+	rc = ENOTACTIVE;
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+qt2025c_wait_reset(
+	__in		efx_nic_t *enp)
+{
+	boolean_t retry = B_TRUE;
+	int rc;
+
+	/*
+	 * Bug17689: occasionally heartbeat starts but firmware status
+	 * code never progresses beyond 0x00.  Try again, once, after
+	 * restarting execution of the firmware image.
+	 */
+again:
+	if ((rc = qt2025c_wait_heartbeat(enp)) != 0)
+		goto fail1;
+
+	rc = qt2025c_wait_firmware(enp);
+	if (rc == ENOTACTIVE && retry) {
+		if ((rc = qt2025c_restart_firmware(enp)) != 0)
+			goto fail2;
+
+		retry = B_FALSE;
+		goto again;
+	}
+	if (rc != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2025c_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	uint8_t version[4];
+	int rc;
+
+	/* Pull the external reset line */
+	falcon_nic_phy_reset(enp);
+
+	/* Wait for the reset to complete */
+	if ((rc = qt2025c_wait_reset(enp)) != 0)
+		goto fail1;
+
+	/* Read the firmware version again post-reset */
+	if ((rc = qt2025c_version_get(enp, version)) != 0)
+		goto fail2;
+	epp->ep_fwver = \
+	    ((uint32_t)version[0] << 24 | (uint32_t)version[1] << 16 | \
+	    (uint32_t)version[2] << 8 | (uint32_t)version[3]);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+qt2025c_select_phy_mode(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	uint16_t phy_op_mode;
+	int i;
+	int rc;
+
+	/*
+	 * Only 2.0.1.0+ PHY firmware supports the more optimal SFP+
+	 * Self-Configure mode.  Don't attempt any switching if we encounter
+	 * older firmware.
+	 *
+	 * NOTE: This code uses explicit integers for MMD's and register
+	 * addresses so that it is trivially comparable to the firmware
+	 * release notes.
+	 */
+	if (epp->ep_fwver < 0x02000100)
+		return (0);
+
+	/*
+	 * In general we will get optimal behaviour in "SFP+ Self-Configure"
+	 * mode; however, that powers down most of the PHY when no module is
+	 * present, so we must use a different mode (any fixed mode will do)
+	 * to be sure that loopbacks will work.
+	 */
+	phy_op_mode = 0x0038;
+#if EFSYS_OPT_LOOPBACK
+	if (epp->ep_loopback_type != EFX_LOOPBACK_OFF)
+		phy_op_mode = 0x0020;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	/* Only change mode if really necessary */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, 1, 0xc319, &word)) != 0)
+		goto fail1;
+	if ((EFX_WORD_FIELD(word, EFX_WORD_0) & 0x0038) == phy_op_mode)
+		return (0);
+
+	/* Do a full reset and wait for it to complete */
+	if ((rc = qt2025c_mdio_write(enp, 1, 0x0000, 0x8000)) != 0)
+		goto fail2;
+	EFSYS_SLEEP(50000);		/* 50ms */
+
+	if ((rc = qt2025c_wait_reset(enp)) != 0)
+		goto fail3;
+
+	/*
+	 * This sequence replicates the register writes configured in the boot
+	 * EEPROM (including the differences between board revisions), except
+	 * that the operating mode is changed, and the PHY is prevented from
+	 * unnecessarily reloading the main firmware image again.
+	 */
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xc300, 0)) != 0)
+		goto fail4;
+
+	/*
+	 * (Note: this portion of the boot EEPROM sequence, which bit-bashes 9
+	 * STOPs onto the firmware/module I2C bus to reset it, varies across
+	 * board revisions, as the bus is connected to different GPIO/LED
+	 * outputs on the PHY.)
+	 */
+	if (enp->en_u.falcon.enu_board_rev < 2) {
+		if ((rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4498)) != 0)
+			goto fail5;
+		for (i = 0; i < 9; i++) {
+			rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4488);
+			if (rc != 0)
+				goto fail5;
+			rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4480);
+			if (rc != 0)
+				goto fail5;
+			rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4490);
+			if (rc != 0)
+				goto fail5;
+			rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4498);
+			if (rc != 0)
+				goto fail5;
+		}
+	} else {
+		if ((rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x0920)) != 0)
+			goto fail5;
+		if ((rc = qt2025c_mdio_write(enp, 1, 0xd008, 0x0004)) != 0)
+			goto fail5;
+		for (i = 0; i < 9; i++) {
+			rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x0900);
+			if (rc != 0)
+				goto fail5;
+			rc = qt2025c_mdio_write(enp, 1, 0xd008, 0x0005);
+			if (rc != 0)
+				goto fail5;
+			rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x0920);
+			if (rc != 0)
+				goto fail5;
+			rc = qt2025c_mdio_write(enp, 1, 0xd008, 0x0004);
+			if (rc != 0)
+				goto fail5;
+		}
+		if ((rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4900)) != 0)
+			goto fail5;
+	}
+
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4900)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xc302, 0x0004)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xc316, 0x0013)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xc318, 0x0054)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xc319, phy_op_mode)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xc31a, 0x0098)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 3, 0x0026, 0x0e00)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 3, 0x0027, 0x0013)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 3, 0x0028, 0xa528)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xd006, 0x000a)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xd007, 0x0009)) != 0)
+		goto fail6;
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xd008, 0x0004)) != 0)
+		goto fail6;
+	/*
+	 * This additional write prevents the PHY boot ROM doing another
+	 * pointless reload of the firmware image (the microcontroller's
+	 * code memory is not affected by the microcontroller reset).
+	 */
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xc317, 0x00ff)) != 0)
+		goto fail7;
+	if ((rc = qt2025c_mdio_write(enp, 1, 0xc300, 0x0002)) != 0)
+		goto fail7;
+	EFSYS_SLEEP(20000);		/* 20ms */
+
+	/* Restart microcontroller execution from RAM */
+	if ((rc = qt2025c_restart_firmware(enp)) != 0)
+		goto fail8;
+
+	/* Wait for the microcontroller to be ready again */
+	if ((rc = qt2025c_wait_reset(enp)) != 0)
+		goto fail9;
+
+	return (0);
+
+fail9:
+	EFSYS_PROBE(fail9);
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2025c_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = qt2025c_select_phy_mode(enp)) != 0)
+		goto fail1;
+
+	if ((rc = xphy_pkg_wait(enp, epp->ep_port, QT2025C_MMD_MASK)) != 0)
+		goto fail2;
+
+	if ((rc = qt2025c_led_cfg(enp)) != 0)
+		goto fail3;
+
+	EFSYS_ASSERT3U(epp->ep_adv_cap_mask, ==, QT2025C_ADV_CAP_MASK);
+
+#if EFSYS_OPT_LOOPBACK
+	if ((rc = qt2025c_loopback_cfg(enp)) != 0)
+		goto fail4;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	return (0);
+
+#if EFSYS_OPT_LOOPBACK
+fail4:
+	EFSYS_PROBE(fail4);
+#endif	/* EFSYS_OPT_LOOPBACK */
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2025c_verify(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_pkg_verify(enp, epp->ep_port, QT2025C_MMD_MASK)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2025c_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if (epp->ep_mac_type != EFX_MAC_FALCON_XMAC) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail2;
+
+	*upp = ((EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0));
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+/* Recover from bug17190 by moving into and out of PMA loopback */
+static	__checkReturn	int
+qt2025c_bug17190_workaround(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port,
+	    PMA_PMD_MMD, MMD_CONTROL1_REG, &word)) != 0)
+		goto fail1;
+	EFX_SET_WORD_FIELD(word, MMD_PMA_LOOPBACK, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port,
+	    PMA_PMD_MMD, MMD_CONTROL1_REG, &word)) != 0)
+		goto fail2;
+
+	EFSYS_SLEEP(100000);	/* 100ms */
+
+	EFX_SET_WORD_FIELD(word, MMD_PMA_LOOPBACK, 0);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port,
+	    PMA_PMD_MMD, MMD_CONTROL1_REG, &word)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2025c_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	uint8_t mmd;
+	uint8_t mmds;
+	boolean_t broken;
+	boolean_t ok;
+	boolean_t up;
+	int rc;
+
+	mmds = (1 << PMA_PMD_MMD) | (1 << PCS_MMD) | (1 << PHY_XS_MMD);
+#if EFSYS_OPT_LOOPBACK
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS:
+		mmds = 0;
+		break;
+	case EFX_LOOPBACK_PCS:
+		mmds = (1 << PHY_XS_MMD);
+		break;
+	case EFX_LOOPBACK_PMA_PMD:
+		mmds = (1 << PHY_XS_MMD) | (1 << PCS_MMD);
+		break;
+	default:
+		break;
+	}
+#endif /* EFSYS_OPT_LOOPBACK */
+
+	/*
+	 * bug17190 is a persistent failure of PCS block lock when PMA
+	 * and PHYXS are up. Only check for this when not in phy loopback.
+	 */
+	broken = !!(mmds & (1 << PMA_PMD_MMD));
+
+	if (!mmds) {
+		/* Use the fault state instead */
+		if ((rc = xphy_mmd_fault(enp, epp->ep_port, &up)) != 0)
+			goto fail1;
+
+	} else {
+		up = B_TRUE;
+		for (mmd = 0; mmd < MAXMMD; mmd++) {
+			if (~mmds & (1 << mmd))
+				continue;
+
+			rc = xphy_mmd_check(enp, epp->ep_port, mmd, &ok);
+			if (rc != 0)
+				goto fail2;
+			up &= ok;
+			broken &= (ok == (mmd != PCS_MMD));
+		}
+	}
+
+	/* Recover from bug17190 if we've been stuck there for 3 polls. */
+	if (!broken)
+		epp->ep_qt2025c.bug17190_count = 0;
+	else if (++(epp->ep_qt2025c.bug17190_count) >= 3) {
+		epp->ep_qt2025c.bug17190_count = 0;
+		EFSYS_PROBE(bug17190_recovery);
+
+		if ((rc = qt2025c_bug17190_workaround(enp)) != 0)
+			goto fail3;
+	}
+
+	*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+	*fcntlp = epp->ep_fcntl;
+	*lp_cap_maskp = epp->ep_lp_cap_mask;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+qt2025c_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, ouip)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_PHY_STATS
+
+#define	QT2025C_STAT_SET(_stat, _mask, _id, _val)			\
+	do {								\
+		(_mask) |= (1ULL << (_id));				\
+		(_stat)[_id] = (uint32_t)(_val);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+static	__checkReturn	int
+qt2025c_build_get(
+	__in		efx_nic_t *enp,
+	__out		uint8_t *yp,
+	__out		uint8_t *mp,
+	__out		uint8_t *dp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    FW_BUILD1_REG, &word)) != 0)
+		goto fail1;
+
+	*yp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    FW_BUILD2_REG, &word)) != 0)
+		goto fail2;
+
+	*mp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    FW_BUILD3_REG, &word)) != 0)
+		goto fail3;
+
+	*dp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+qt2025c_pma_pmd_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_LINK_UP,
+	    (EFX_WORD_FIELD(word, PMA_PMD_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_RX_FAULT) != 0) ? 1 : 0);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_TX_FAULT) != 0) ? 1 : 0);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+qt2025c_pcs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	uint8_t version[4];
+	uint8_t yy;
+	uint8_t mm;
+	uint8_t dd;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PCS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_RX_FAULT) != 0) ? 1 : 0);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_10GBASE_R_STATUS2_REG, &word)) != 0)
+		goto fail3;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BER,
+	    EFX_WORD_FIELD(word, PCS_BER));
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BLOCK_ERRORS,
+	    EFX_WORD_FIELD(word, PCS_ERR));
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    OP_MODE_REG, &word)) != 0)
+		goto fail4;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_OP_MODE,
+	    EFX_WORD_FIELD(word, OP_MODE_CURRENT));
+
+	if ((rc = qt2025c_version_get(enp, version)) != 0)
+		goto fail5;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_VERSION_0,
+	    version[0]);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_VERSION_1,
+	    version[1]);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_VERSION_2,
+	    version[2]);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_VERSION_3,
+	    version[3]);
+
+	if ((rc = qt2025c_build_get(enp, &yy, &mm, &dd)) != 0)
+		goto fail6;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_BUILD_YY, yy);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_BUILD_MM, mm);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_BUILD_DD, dd);
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+qt2025c_phy_xs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PHY_XS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_RX_FAULT) != 0) ? 1 : 0);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail3;
+
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_ALIGN,
+	    (EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) ? 1 : 0);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_A,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) ? 1 : 0);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_B,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) ? 1 : 0);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_C,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) ? 1 : 0);
+	QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_D,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0) ? 1 : 0);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+qt2025c_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint64_t mask = 0;
+	uint32_t oui;
+	int rc;
+
+	_NOTE(ARGUNUSED(esmp))
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, &oui)) != 0)
+		goto fail1;
+
+	QT2025C_STAT_SET(stat, mask, EFX_PHY_STAT_OUI, oui);
+
+	if ((rc = qt2025c_pma_pmd_stats_update(enp, &mask, stat)) != 0)
+		goto fail2;
+
+	if ((rc = qt2025c_pcs_stats_update(enp, &mask, stat)) != 0)
+		goto fail3;
+
+	if ((rc = qt2025c_phy_xs_stats_update(enp, &mask, stat)) != 0)
+		goto fail4;
+
+	/* Ensure all the supported statistics are up to date */
+	EFSYS_ASSERT(mask == encp->enc_phy_stat_mask);
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+		const char __cs *
+qt2025c_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	_NOTE(ARGUNUSED(enp, id))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (NULL);
+}
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn	int
+qt2025c_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp)
+{
+	_NOTE(ARGUNUSED(enp, id, flags, valp))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+
+	__checkReturn	int
+qt2025c_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val)
+{
+	_NOTE(ARGUNUSED(enp, id, val))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#endif	/* EFSYS_OPT_PHY_QT2025C */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/qt2025c.h	2013-08-22 18:57:32.284627446 -0400
@@ -0,0 +1,162 @@
+/*-
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_QT2025C_H
+#define	_SYS_QT2025C_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_QT2025C
+
+#define	QT2025C_LOOPBACK_MASK						\
+	    ((1 << EFX_LOOPBACK_PHY_XS) |				\
+	    (1 << EFX_LOOPBACK_PCS) |					\
+	    (1 << EFX_LOOPBACK_PMA_PMD) |				\
+	    FALCON_XMAC_LOOPBACK_MASK)
+
+#define	QT2025C_LED_MASK						\
+	    ((1 << EFX_PHY_LED_OFF) |					\
+	    (1 << EFX_PHY_LED_ON))
+
+#define	QT2025C_NPROPS		0
+
+#define	QT2025C_ADV_CAP_MASK						\
+	    ((1 << EFX_PHY_CAP_10000FDX) |				\
+	    (1 << EFX_PHY_CAP_PAUSE))
+
+#define	QT2025C_ADV_CAP_PERM	0
+
+#define	QT2025C_BIST_MASK	0
+
+extern	__checkReturn	int
+qt2025c_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+qt2025c_reconfigure(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+qt2025c_verify(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+qt2025c_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp);
+
+extern	__checkReturn	int
+qt2025c_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp);
+
+extern			void
+qt2025c_downlink_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+qt2025c_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip);
+
+#if EFSYS_OPT_PHY_STATS
+
+/* START MKCONFIG GENERATED Qt2025cPhyHeaderStatsMask 2eb4a092d85bd5ac */
+#define	QT2025C_STAT_MASK \
+	(1ULL << EFX_PHY_STAT_OUI) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PCS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_BER) | \
+	(1ULL << EFX_PHY_STAT_PCS_BLOCK_ERRORS) | \
+	(1ULL << EFX_PHY_STAT_PCS_FW_VERSION_0) | \
+	(1ULL << EFX_PHY_STAT_PCS_FW_VERSION_1) | \
+	(1ULL << EFX_PHY_STAT_PCS_FW_VERSION_2) | \
+	(1ULL << EFX_PHY_STAT_PCS_FW_VERSION_3) | \
+	(1ULL << EFX_PHY_STAT_PCS_FW_BUILD_YY) | \
+	(1ULL << EFX_PHY_STAT_PCS_FW_BUILD_MM) | \
+	(1ULL << EFX_PHY_STAT_PCS_FW_BUILD_DD) | \
+	(1ULL << EFX_PHY_STAT_PCS_OP_MODE) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_ALIGN) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_A) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_B) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_C) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_D)
+
+/* END MKCONFIG GENERATED Qt2025cPhyHeaderStatsMask */
+
+extern	__checkReturn			int
+qt2025c_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat);
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+qt2025c_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id);
+
+#endif
+
+extern	__checkReturn	int
+qt2025c_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp);
+
+extern	__checkReturn	int
+qt2025c_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val);
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#endif	/* EFSYS_OPT_PHY_QT2025C */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_QT2025C_H */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/qt2025c_impl.h	2013-08-22 18:57:32.370272480 -0400
@@ -0,0 +1,248 @@
+/*-
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_QT2025C_IMPL_H
+#define	_SYS_QT2025C_IMPL_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_QT2025C
+
+#define	QT2025C_MMD_MASK						\
+	    ((1 << PMA_PMD_MMD) |					\
+	    (1 << PCS_MMD) |						\
+	    (1 << PHY_XS_MMD))
+
+/* PMA/PMD */
+
+#define	MDIO_RESETS_REG 0xc300
+#define	KRDLL_RESETN_LBN 0
+#define	KRDLL_RESETN_WIDTH 1
+#define	MICRO_RESETN_LBN 1
+#define	MICRO_RESETN_WIDTH 1
+#define	EDC_RESETN_LBN 2
+#define	EDC_RESETN_WIDTH 1
+#define	PSDLL_RESETN_LBN 3
+#define	PSDLL_RESETN_WIDTH 1
+#define	PRDLL_RESETN_LBN 4
+#define	PRDLL_RESETN_WIDTH 1
+#define	RESLRN_RESETN_LBN 5
+#define	RESLRN_RESETN_WIDTH 1
+#define	IB_TX_RESETN_LBN 6
+#define	IB_TX_RESETN_WIDTH 1
+#define	IB_RX_RESETN_LBN 7
+#define	IB_RX_RESETN_WIDTH 1
+#define	SINUS_RESETN_LBN 8
+#define	SINUS_RESETN_WIDTH 1
+
+#define	PMA_UC8051_CFG_REG 0xc302
+#define	EREFCLK_FREQ_LBN 0
+#define	EREFCLK_FREQ_WIDTH 1
+#define	EREFCLK_FREQ_156_25_DECODE 0
+#define	EREFCLK_FREQ_52_08_DECODE 1
+#define	SREFCLK_FREQ_LBN 1
+#define	SREFCLK_FREQ_WIDTH 1
+#define	SREFCLK_FREQ_155_52_DECODE 0
+#define	SREFCLK_FREQ_51_84_DECODE 1
+#define	UC_CLK_SEL_LBN 2
+#define	UC_CLK_SEL_WIDTH 3
+#define	UC_CLK_156_25_DECODE 1
+#define	EEPROM_BOOT_MODE_LBN 5
+#define	EEPROM_BOOT_MODE_WIDTH 1
+#define	EEPROM_BOOT_0_DECODE 0
+#define	EEPROM_BOOT_1K_DECODE 1
+#define	UC_JTAG_CTRL_LBN 6
+#define	UC_JTAG_CTRL_WIDTH 1
+
+#define	PMA_FTX_CTRL2_REG 0xc309
+#define	FTX_STATIC_LBN 13
+#define	FTX_STATIC_WIDTH 1
+
+#define	PMA_UC8051_I2C_FREQ_REG 0xc316
+#define	UC_I2C_DIV_LBN 0
+#define	UC_I2C_DIV_WIDTH 8
+
+#define	PMA_UC8051_I2C_SLV_ADDR_REG 0xc318
+#define	UC_I2C_SLV_ADDR_LBN 0
+#define	UC_I2C_SLV_ADDR_WIDTH 7
+
+#define	PMA_UC8051_SPARE2_REG 0xc319
+#define	DISABLE_PORT_LBN 1
+#define	DISABLE_PORT_WIDTH 1
+#define	OP_MODE_CONFIG_LBN 3
+#define	OP_MODE_CONFIG_WIDTH 3
+#define	OP_MODE_LINEAR_DECODE 0
+#define	OP_MODE_LIMITING_DECODE 1
+#define	OP_MODE_KR_DECODE 2
+#define	OP_MODE_DIRECT_DECODE 4
+#define	OP_MODE_LOW_POWER_DECODE 5
+#define	OP_MODE_AUTO_DECODE 7
+#define	DATA_RATE_LBN 7
+#define	DATA_RATE_WIDTH 1
+#define	DATA_RATE_10G_DECODE 0
+#define	DATA_RATE_1_25G_DECODE 1
+
+#define	PMA_UC8051_SPARE3_REG 0xc31a
+#define	XDRV_OVRD_LBN 1
+#define	XDRV_OVRD_WIDTH 1
+#define	FTX_OVRD_LBN 2
+#define	FTX_OVRD_WIDTH 1
+#define	MODULE_TYPE_LBN 3
+#define	MODULE_TYPE_WIDTH 3
+#define	MODULE_TYPE_X2_DECODE 1
+#define	MODULE_TYPE_XFP_DECODE 2
+#define	MODULE_TYPE_SFP_DECODE 3
+
+#define	PRD_CODE1_REG 0xd000
+#define	PRODUCT_CODE_LBN 0
+#define	PRODUCT_CODE_WIDTH 16
+
+#define	PMA_PMD_LED1_REG 0xd006	/* Green */
+#define	PMA_PMD_LED2_REG 0xd007	/* Amber */
+#define	PMA_PMD_LED3_REG 0xd008 /* Red */
+
+#define	PMA_PMD_LED_CFG_LBN 0
+#define	PMA_PMD_LED_CFG_WIDTH 3
+#define	LED_CFG_LS_DECODE 0x1
+#define	LED_CFG_LA_DECODE 0x2
+#define	LED_CFG_LSA_DECODE 0x3
+#define	LED_CFG_OFF_DECODE 0x4
+#define	LED_CFG_ON_DECODE 0x5
+#define	PMA_PMD_LED_PATH_LBN 3
+#define	PMA_PMD_LED_PATH_WIDTH 1
+#define	LED_PATH_TX_DECODE 0x0
+#define	LED_PATH_RX_DECODE 0x1
+
+/* PCS */
+
+#define	KR_BYPASS_CTRL_REG 0x0026
+#define	FREEZE_DIS_LBN 8
+#define	FREEZE_DIS_WIDTH 8
+#define	FREEZE_DIS_DECODE 0x0e
+
+#define	BOOT_CTRL_REG 0x0027
+#define	LED1_CTRL_LBN 0
+#define	LED1_CTRL_WIDTH 1
+#define	LED1_CTRL_FW_DECODE 0
+#define	LED1_CTRL_HW_DECODE 1
+#define	FTX_FR4_LOSS_LBN 1
+#define	FTX_FR4_LOSS_WIDTH 3
+#define	FRX_FR4_LOSS_LBN 4
+#define	FRX_FR4_LOSS_WIDTH 3
+#define	GE_PRBS_MODE_LBN 15
+#define	GE_PRBS_MODE_WIDTH 1
+
+#define	FW_CFG_REG 0x0028
+#define	FW_CFG_KEY_LBN 0
+#define	FW_CFG_KEY_WIDTH 16
+#define	FW_CFG_KEY_DECODE 0xa528
+
+#define	MICRO_RAM1_BASE	0x8000
+#define	MICRO_RAM1_SIZE	0x4000
+
+#define	OP_MODE_REG 0xd70c
+#define	OP_MODE_CURRENT_LBN 0
+#define	OP_MODE_CURRENT_WIDTH 4
+
+#define	LED_CFG_REG 0xd70d
+#define	LED3_CFG_LBN 0
+#define	LED3_CFG_WIDTH 2
+#define	LED2_CFG_LBN 2
+#define	LED2_CFG_WIDTH 2
+#define	LED1_CFG_LBN 4
+#define	LED1_CFG_WIDTH 2
+#define	LED_RXTX_DECODE 3
+#define	LED_RX_DECODE 2
+#define	LED_TX_DECODE 1
+#define	LED_ON_DECODE 0
+
+#define	CKSUM_STATUS1_REG 0xd716
+#define	CKSUM_STATUS1_BYTE_LBN 0
+#define	CKSUM_STATUS1_BYTE_WIDTH 1
+#define	CKSUM_STATUS1_BYTE_BAD_DECODE 0xde
+
+#define	CKSUM_STATUS2_REG 0xd717
+#define	CKSUM_STATUS2_BYTE_LBN 0
+#define	CKSUM_STATUS2_BYTE_WIDTH 1
+#define	CKSUM_STATUS2_BYTE_BAD_DECODE 0xad
+
+#define	FW_HEARTBEAT_REG 0xd7ee
+#define	FW_HEARTB_LBN 0
+#define	FW_HEARTB_WIDTH 8
+
+#define	FW_VERSION1_REG 0xd7f3
+#define	FW_VERSION2_REG 0xd7f4
+#define	FW_VERSION3_REG 0xd7f5
+
+#define	FW_BUILD1_REG 0xd7f6
+#define	FW_BUILD2_REG 0xd7f7
+#define	FW_BUILD3_REG 0xd7f8
+
+#define	UC8051_STATUS_REG 0xd7fd
+#define	UC_STATUS_LBN 0
+#define	UC_STATUS_WIDTH 8
+#define	UC_STATUS_INVALID_DECODE 0x00
+#define	UC_STATUS_FW_START_DECODE 0x10
+#define	UC_STATUS_FW_SAVE_DECODE 0x20
+#define	UC_STATUS_INIT_DECODE 0x40
+#define	UC_STATUS_AQ_IN_PROG_DECODE 0x50
+#define	UC_STATUS_AQ_COMPLETE_DECODE 0x60
+#define	UC_STATUS_TRACK_IN_PROG_DECODE 0x70
+#define	UC_STATUS_IN_AN_DECODE 0xa0
+
+#define	MICRO_GEN_CTL_REG 0xe854
+#define	UC_INT0_CNT_LBN 0
+#define	UC_INT0_CNT_WIDTH 1
+#define	UC_INT1_CNT_LBN 1
+#define	UC_INT1_CNT_WIDTH 1
+#define	UC_MDIO_SW_LBN 3
+#define	UC_MDIO_SW_WIDTH 1
+#define	UC_DIS_ROM_LBN 4
+#define	UC_DIS_ROM_WIDTH 1
+#define	UC_UPDATE_LBN 5
+#define	UC_UPDATE_WIDTH 1
+#define	UC_RUN_RAM_LBN 6
+#define	UC_RUN_RAM_WIDTH 1
+#define	UC_RST_LBN 7
+#define	UC_RST_WIDTH 1
+
+/* PHY_XS */
+
+#define	XGXS_VENDOR_SPECIFIC_1_REG 0xc000
+#define	XGXS_SYSLPBK_LBN 14
+#define	XGXS_SYSLPBK_WIDTH 1
+
+#define	MICRO_RAM2_BASE	0x8000
+#define	MICRO_RAM2_SIZE	0x2000
+
+#endif	/* EFSYS_OPT_PHY_QT2025C */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_QT2025C_IMPL_H */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sft9001.c	2013-08-22 18:57:32.457049566 -0400
@@ -0,0 +1,2083 @@
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "falcon_nvram.h"
+#include "sft9001.h"
+#include "sft9001_impl.h"
+#include "xphy.h"
+#include "falcon_impl.h"
+
+#if EFSYS_OPT_PHY_SFT9001
+
+static	__checkReturn	int
+sft9001_short_reach_set(
+	__in		efx_nic_t *enp,
+	__in		boolean_t on)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port,
+	    PMA_PMD_MMD, PMA_PMD_PWR_BACKOFF_REG, &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, SHORT_REACH, (on) ? 1 : 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port,
+	    PMA_PMD_MMD, PMA_PMD_PWR_BACKOFF_REG, &word)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sft9001_short_reach_get(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *onp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port,
+	    PMA_PMD_MMD, PMA_PMD_PWR_BACKOFF_REG, &word)) != 0)
+		goto fail1;
+
+	*onp = (EFX_WORD_FIELD(word, SHORT_REACH) != 0);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sft9001_robust_set(
+	__in		efx_nic_t *enp,
+	__in		boolean_t on)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, ROBUST, (on) ? 1 : 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sft9001_robust_get(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *onp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail1;
+
+	*onp = (EFX_WORD_FIELD(word, ROBUST) != 0);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sft9001_an_set(
+	__in		efx_nic_t *enp,
+	__in		boolean_t on)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_CONTROL1_REG, &word)) != 0)
+		goto fail1;
+
+	if (on) {
+		EFX_SET_WORD_FIELD(word, AN_ENABLE, 1);
+		EFX_SET_WORD_FIELD(word, AN_RESTART, 1);
+	} else {
+		EFX_SET_WORD_FIELD(word, AN_ENABLE, 0);
+	}
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, AN_MMD,
+	    AN_CONTROL1_REG, &word)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sft9001_gmii_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, GMII_EN, 1);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sft9001_clock_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail1;
+
+	/* Select 312MHz clock on CLK312_OUT_{P,N} */
+	EFX_SET_WORD_FIELD(word, CLK312_OUT_SEL, SEL_312MHZ_DECODE);
+	EFX_SET_WORD_FIELD(word, CLK312_OUT_EN, 1);
+
+	/* Select 125MHz clock on TEST_CLKOUT_{P,N} */
+	EFX_SET_WORD_FIELD(word, TEST_CLKOUT_SEL, SEL_125MHZ_DECODE);
+	EFX_SET_WORD_FIELD(word, TEST_CLKOUT_EN, 1);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sft9001_adv_cap_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* Check base page */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_ADV_BP_CAP_REG, &word)) != 0)
+		goto fail1;
+
+	EFSYS_ASSERT(!(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_10HDX)));
+	if (EFX_WORD_FIELD(word, AN_ADV_TA_10BASE_T) != 0)
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_10BASE_T, 0);
+
+	EFSYS_ASSERT(!(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_10FDX)));
+	if (EFX_WORD_FIELD(word, AN_ADV_TA_10BASE_T_FDX) != 0)
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_10BASE_T_FDX, 0);
+
+	if (EFX_WORD_FIELD(word, AN_ADV_TA_100BASE_TX) == 0 &&
+	    epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_100HDX))
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_100BASE_TX, 1);
+	else if (EFX_WORD_FIELD(word, AN_ADV_TA_100BASE_TX) != 0 &&
+	    !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_100HDX)))
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_100BASE_TX, 0);
+
+	if (EFX_WORD_FIELD(word, AN_ADV_TA_100BASE_TX_FDX) == 0 &&
+	    epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_100FDX))
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_100BASE_TX_FDX, 1);
+	else if (EFX_WORD_FIELD(word, AN_ADV_TA_100BASE_TX_FDX) != 0 &&
+	    !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_100FDX)))
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_100BASE_TX_FDX, 0);
+
+	if (EFX_WORD_FIELD(word, AN_ADV_TA_PAUSE) == 0 &&
+	    epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_PAUSE, 1);
+	else if (EFX_WORD_FIELD(word, AN_ADV_TA_PAUSE) != 0 &&
+	    !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)))
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_PAUSE, 0);
+
+	if (EFX_WORD_FIELD(word, AN_ADV_TA_ASM_DIR) == 0 &&
+	    epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_ASM_DIR, 1);
+	else if (EFX_WORD_FIELD(word, AN_ADV_TA_ASM_DIR) != 0 &&
+	    !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)))
+		EFX_SET_WORD_FIELD(word, AN_ADV_TA_ASM_DIR, 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, AN_MMD,
+	    AN_ADV_BP_CAP_REG, &word)) != 0)
+		goto fail2;
+
+	/* Check 1G operation */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, CL22EXT_MMD,
+	    CL22EXT_MS_CONTROL_REG, &word)) != 0)
+		goto fail3;
+
+	EFSYS_ASSERT(!(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_1000HDX)));
+	if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_ADV) != 0)
+		EFX_SET_WORD_FIELD(word, CL22EXT_1000BASE_T_ADV, 0);
+
+	if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_ADV) == 0 &&
+	    epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_1000FDX))
+		EFX_SET_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_ADV, 1);
+	else if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_ADV) != 0 &&
+	    !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_1000FDX)))
+		EFX_SET_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_ADV, 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, CL22EXT_MMD,
+	    CL22EXT_MS_CONTROL_REG, &word)) != 0)
+		goto fail4;
+
+	/* Check 10G operation */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_10G_BASE_T_CONTROL_REG, &word)) != 0)
+		goto fail5;
+
+	if (EFX_WORD_FIELD(word, AN_10G_BASE_T_ADV) == 0 &&
+	    epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_10000FDX))
+		EFX_SET_WORD_FIELD(word, AN_10G_BASE_T_ADV, 1);
+	else if (EFX_WORD_FIELD(word, AN_10G_BASE_T_ADV) != 0 &&
+	    !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_10000FDX)))
+		EFX_SET_WORD_FIELD(word, AN_10G_BASE_T_ADV, 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, AN_MMD,
+	    AN_10G_BASE_T_CONTROL_REG, &word)) != 0)
+		goto fail6;
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_LOOPBACK
+static	__checkReturn	int
+sft9001_loopback_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS:
+		if ((rc = falcon_mdio_read(enp, epp->ep_port,
+		    PHY_XS_MMD, PHY_XS_TEST1_REG, &word)) != 0)
+			goto fail1;
+
+		EFX_SET_WORD_FIELD(word, PHY_XS_NE_LOOPBACK, 1);
+
+		if ((rc = falcon_mdio_write(enp, epp->ep_port,
+		    PHY_XS_MMD, PHY_XS_TEST1_REG, &word)) != 0)
+			goto fail2;
+
+		break;
+
+	case EFX_LOOPBACK_PCS:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PCS_MMD,
+		    B_TRUE)) != 0)
+			goto fail1;
+
+		break;
+
+	case EFX_LOOPBACK_PMA_PMD:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PMA_PMD_MMD,
+		    B_TRUE)) != 0)
+			goto fail1;
+
+		break;
+
+	case EFX_LOOPBACK_GPHY:
+		if ((rc = falcon_mdio_read(enp, epp->ep_port,
+		    CL22EXT_MMD, CL22EXT_CONTROL_REG, &word)) != 0)
+			goto fail1;
+
+		EFX_SET_WORD_FIELD(word, CL22EXT_NE_LOOPBACK, 1);
+
+		if ((rc = falcon_mdio_write(enp, epp->ep_port,
+		    CL22EXT_MMD, CL22EXT_CONTROL_REG, &word)) != 0)
+			goto fail2;
+
+		break;
+
+	default:
+		break;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+static	__checkReturn	int
+sft9001_led_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+#if EFSYS_OPT_PHY_LED_CONTROL
+
+	switch (epp->ep_phy_led_mode) {
+	case EFX_PHY_LED_DEFAULT:
+		EFX_POPULATE_WORD_8(word,
+		    LED_TMODE, LED_NORMAL_DECODE,
+		    LED_SPARE, LED_NORMAL_DECODE,
+		    LED_MS, LED_NORMAL_DECODE,
+		    LED_RX, LED_NORMAL_DECODE,
+		    LED_TX, LED_NORMAL_DECODE,
+		    LED_SPEED0, LED_NORMAL_DECODE,
+		    LED_SPEED1, LED_NORMAL_DECODE,
+		    LED_LINK, LED_NORMAL_DECODE);
+		break;
+
+	case EFX_PHY_LED_OFF:
+		EFX_POPULATE_WORD_8(word,
+		    LED_TMODE, LED_OFF_DECODE,
+		    LED_SPARE, LED_OFF_DECODE,
+		    LED_MS, LED_OFF_DECODE,
+		    LED_RX, LED_OFF_DECODE,
+		    LED_TX, LED_OFF_DECODE,
+		    LED_SPEED0, LED_OFF_DECODE,
+		    LED_SPEED1, LED_OFF_DECODE,
+		    LED_LINK, LED_OFF_DECODE);
+		break;
+
+	case EFX_PHY_LED_ON:
+		EFX_POPULATE_WORD_8(word,
+		    LED_TMODE, LED_ON_DECODE,
+		    LED_SPARE, LED_ON_DECODE,
+		    LED_MS, LED_ON_DECODE,
+		    LED_RX, LED_ON_DECODE,
+		    LED_TX, LED_ON_DECODE,
+		    LED_SPEED0, LED_ON_DECODE,
+		    LED_SPEED1, LED_ON_DECODE,
+		    LED_LINK, LED_ON_DECODE);
+		break;
+
+	case EFX_PHY_LED_FLASH:
+		EFX_POPULATE_WORD_8(word,
+		    LED_TMODE, LED_FLASH_DECODE,
+		    LED_SPARE, LED_FLASH_DECODE,
+		    LED_MS, LED_FLASH_DECODE,
+		    LED_RX, LED_FLASH_DECODE,
+		    LED_TX, LED_FLASH_DECODE,
+		    LED_SPEED0, LED_FLASH_DECODE,
+		    LED_SPEED1, LED_FLASH_DECODE,
+		    LED_LINK, LED_FLASH_DECODE);
+		break;
+
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		break;
+	}
+
+#else	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	EFX_POPULATE_WORD_8(word,
+	    LED_TMODE, LED_NORMAL_DECODE,
+	    LED_SPARE, LED_NORMAL_DECODE,
+	    LED_MS, LED_NORMAL_DECODE,
+	    LED_RX, LED_NORMAL_DECODE,
+	    LED_TX, LED_NORMAL_DECODE,
+	    LED_SPEED0, LED_NORMAL_DECODE,
+	    LED_SPEED1, LED_NORMAL_DECODE,
+	    LED_LINK, LED_NORMAL_DECODE);
+
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_LED_OVERRIDE_REG, &word)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sft9001_reset(
+	__in		efx_nic_t *enp)
+{
+	int state;
+
+	/* Lock I2C bus because sft9001 is sensitive to GPIO3 */
+	EFSYS_LOCK(enp->en_eslp, state);
+	EFSYS_ASSERT(!enp->en_u.falcon.enu_i2c_locked);
+	enp->en_u.falcon.enu_i2c_locked = B_TRUE;
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	/* Pull the external reset line */
+	falcon_nic_phy_reset(enp);
+
+	/* Unlock I2C */
+	EFSYS_LOCK(enp->en_eslp, state);
+	enp->en_u.falcon.enu_i2c_locked = B_FALSE;
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	return (0);
+}
+
+	__checkReturn	int
+sft9001_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	unsigned int count;
+	int rc;
+
+	/* Wait for the firmware boot to complete */
+	count = 0;
+	do {
+		efx_word_t word;
+
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 1 ms */
+		EFSYS_SPIN(1000);
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    PCS_BOOT_STATUS_REG, &word)) != 0)
+			goto fail1;
+
+		if (EFX_WORD_FIELD(word, FATAL_ERR) != 0)
+			break;	/* no point in continuing */
+
+		if (EFX_WORD_FIELD(word, BOOT_STATUS) != 0 &&
+		    EFX_WORD_FIELD(word, CODE_DOWNLOAD) != 0 &&
+		    EFX_WORD_FIELD(word, CKSUM_OK) != 0 &&
+		    EFX_WORD_FIELD(word, CODE_STARTED) != 0 &&
+		    EFX_WORD_FIELD(word, BOOT_PROGRESS) == APP_JMP_DECODE)
+			goto configure;
+
+	} while (++count < 1000);
+
+	rc = ENOTACTIVE;
+	goto fail2;
+
+configure:
+	if ((rc = xphy_pkg_wait(enp, epp->ep_port, SFT9001_MMD_MASK)) != 0)
+		goto fail3;
+
+	/* Make sure auto-negotiation is off whilst we configure the PHY */
+	if ((rc = sft9001_an_set(enp, B_FALSE)) != 0)
+		goto fail4;
+
+	if ((rc = sft9001_gmii_cfg(enp)) != 0)
+		goto fail5;
+
+	if ((rc = sft9001_clock_cfg(enp)) != 0)
+		goto fail6;
+
+	if ((rc = sft9001_adv_cap_cfg(enp)) != 0)
+		goto fail7;
+
+#if EFSYS_OPT_LOOPBACK
+	if ((rc = sft9001_loopback_cfg(enp)) != 0)
+		goto fail8;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	if ((rc = sft9001_led_cfg(enp)) != 0)
+		goto fail9;
+
+	if ((rc = sft9001_robust_set(enp, B_TRUE)) != 0)
+		goto fail10;
+
+#if EFSYS_OPT_LOOPBACK
+	if (epp->ep_loopback_type == EFX_LOOPBACK_OFF) {
+		if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
+			goto fail11;
+	}
+#else	/* EFSYS_OPT_LOOPBACK */
+	if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
+		goto fail11;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	return (0);
+
+fail11:
+	EFSYS_PROBE(fail11);
+fail10:
+	EFSYS_PROBE(fail10);
+fail9:
+	EFSYS_PROBE(fail9);
+
+#if EFSYS_OPT_LOOPBACK
+fail8:
+	EFSYS_PROBE(fail8);
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sft9001_verify(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_pkg_verify(enp, epp->ep_port, SFT9001_MMD_MASK)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sft9001_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if (epp->ep_mac_type != EFX_MAC_FALCON_XMAC) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail2;
+
+	*upp = ((EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0));
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sft9001_lp_cap_get(
+	__in		efx_nic_t *enp,
+	__out		unsigned int *maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	*maskp = 0;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_LP_BP_CAP_REG, &word)) != 0)
+		goto fail1;
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_10BASE_T) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_10HDX);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_10BASE_T_FDX) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_10FDX);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_100BASE_TX) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_100HDX);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_100BASE_TX_FDX) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_100FDX);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_PAUSE) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_PAUSE);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_ASM_DIR) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_ASYM);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, CL22EXT_MMD,
+	    CL22EXT_MS_STATUS_REG, &word)) != 0)
+		goto fail2;
+
+	if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_LP) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_1000HDX);
+
+	if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_LP) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_1000FDX);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_10G_BASE_T_STATUS_REG, &word)) != 0)
+		goto fail3;
+
+	if (EFX_WORD_FIELD(word, AN_10G_BASE_T_LP) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_10000FDX);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sft9001_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	unsigned int fcntl = epp->ep_fcntl;
+	unsigned int lp_cap_mask = epp->ep_lp_cap_mask;
+	boolean_t up;
+	uint32_t common;
+	int rc;
+
+#if EFSYS_OPT_LOOPBACK
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS:
+		rc = xphy_mmd_fault(enp, epp->ep_port, &up);
+		if (rc != 0)
+			goto fail1;
+
+		*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+		goto done;
+
+	case EFX_LOOPBACK_PCS:
+	case EFX_LOOPBACK_PMA_PMD:
+		rc = xphy_mmd_check(enp, epp->ep_port, PHY_XS_MMD, &up);
+		if (rc != 0)
+			goto fail1;
+
+		*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+		goto done;
+
+	case EFX_LOOPBACK_GPHY:
+		*modep = EFX_LINK_1000FDX;
+		goto done;
+
+	default:
+		break;
+	}
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	if ((rc = xphy_mmd_check(enp, epp->ep_port, AN_MMD, &up)) != 0)
+		goto fail1;
+
+	if (!up) {
+		*modep = EFX_LINK_DOWN;
+		goto done;
+	}
+
+	/* Check the link partner capabilities */
+	if ((rc = sft9001_lp_cap_get(enp, &lp_cap_mask)) != 0)
+		goto fail2;
+
+	/* Resolve the common capabilities */
+	common = epp->ep_adv_cap_mask & lp_cap_mask;
+
+	/* The 'best' common link mode should be the one in operation */
+	if (common & (1 << EFX_PHY_CAP_10000FDX)) {
+		*modep = EFX_LINK_10000FDX;
+	} else if (common & (1 << EFX_PHY_CAP_1000FDX)) {
+		*modep = EFX_LINK_1000FDX;
+	} else if (common & (1 << EFX_PHY_CAP_100FDX)) {
+		*modep = EFX_LINK_100FDX;
+	} else if (common & (1 << EFX_PHY_CAP_100HDX)) {
+		*modep = EFX_LINK_100HDX;
+	} else {
+		*modep = EFX_LINK_UNKNOWN;
+	}
+
+	/* Determine negotiated or forced flow control mode */
+	fcntl = 0;
+	if (epp->ep_fcntl_autoneg) {
+		if (common & (1 << EFX_PHY_CAP_PAUSE))
+			fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND;
+		else if (common & (1 << EFX_PHY_CAP_ASYM)) {
+			if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
+				fcntl = EFX_FCNTL_RESPOND;
+			else if (lp_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
+				fcntl = EFX_FCNTL_GENERATE;
+		}
+	} else {
+		if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
+			fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND;
+		if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
+			fcntl ^= EFX_FCNTL_GENERATE;
+	}
+
+done:
+	*fcntlp = fcntl;
+	*lp_cap_maskp = lp_cap_mask;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sft9001_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, ouip)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#define	SFT9001_STAT_SET(_stat, _mode, _id, _val)			\
+	do {								\
+		(_mode) |= (1 << (_id));				\
+		(_stat)[_id] = (uint32_t)(_val);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+static	__checkReturn	int
+sft9001_rev_get(
+	__in		efx_nic_t *enp,
+	__out		uint8_t *ap,
+	__out		uint8_t *bp,
+	__out		uint8_t *cp,
+	__out		uint8_t *dp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_FW_REV0_REG, &word)) != 0)
+		goto fail1;
+
+	*ap = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_1);
+	*bp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_FW_REV1_REG, &word)) != 0)
+		goto fail2;
+
+	*cp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_1);
+	*dp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_PHY_STATS
+
+static	__checkReturn			int
+sft9001_pma_pmd_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	uint8_t a;
+	uint8_t b;
+	uint8_t c;
+	uint8_t d;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_LINK_UP,
+	    (EFX_WORD_FIELD(word, PMA_PMD_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_RX_FAULT) != 0) ? 1 : 0);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = sft9001_rev_get(enp, &a, &b, &c, &d)) != 0)
+		goto fail3;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_A, a);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_B, b);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_C, c);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_D, d);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_CHANNELA_SNR_REG, &word)) != 0)
+		goto fail4;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_A,
+	    EFX_WORD_FIELD(word, PMA_PMD_SNR));
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_CHANNELB_SNR_REG, &word)) != 0)
+		goto fail5;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_B,
+	    EFX_WORD_FIELD(word, PMA_PMD_SNR));
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_CHANNELC_SNR_REG, &word)) != 0)
+		goto fail6;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_C,
+	    EFX_WORD_FIELD(word, PMA_PMD_SNR));
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_CHANNELD_SNR_REG, &word)) != 0)
+		goto fail7;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_D,
+	    EFX_WORD_FIELD(word, PMA_PMD_SNR));
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+sft9001_pcs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PCS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_RX_FAULT) != 0) ? 1 : 0);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_10GBASE_T_STATUS2_REG, &word)) != 0)
+		goto fail3;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BER,
+	    EFX_WORD_FIELD(word, PCS_BER));
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BLOCK_ERRORS,
+	    EFX_WORD_FIELD(word, PCS_ERR));
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+sft9001_phy_xs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PHY_XS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_RX_FAULT) != 0) ? 1 : 0);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail3;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_ALIGN,
+	    (EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) ? 1 : 0);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_A,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) ? 1 : 0);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_B,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) ? 1 : 0);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_C,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) ? 1 : 0);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_D,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0) ? 1 : 0);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+sft9001_an_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_LINK_UP,
+	    (EFX_WORD_FIELD(word, AN_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_10G_BASE_T_STATUS_REG, &word)) != 0)
+		goto fail2;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_MASTER,
+	    (EFX_WORD_FIELD(word, AN_MASTER) != 0) ? 1 : 0);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_LOCAL_RX_OK,
+	    (EFX_WORD_FIELD(word, AN_LOCAL_RX_OK) != 0) ? 1 : 0);
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_REMOTE_RX_OK,
+	    (EFX_WORD_FIELD(word, AN_REMOTE_RX_OK) != 0) ? 1 : 0);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+sft9001_cl22ext_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, CL22EXT_MMD,
+	    CL22EXT_STATUS_REG, &word)) != 0)
+		goto fail1;
+
+	SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_CL22EXT_LINK_UP,
+	    (EFX_WORD_FIELD(word, CL22EXT_LINK_UP) != 0) ? 1 : 0);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+	__checkReturn			int
+sft9001_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint64_t mask = 0;
+	uint32_t oui;
+	int rc;
+
+	_NOTE(ARGUNUSED(esmp))
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, &oui)) != 0)
+		goto fail1;
+
+	SFT9001_STAT_SET(stat, mask, EFX_PHY_STAT_OUI, oui);
+
+	if ((rc = sft9001_pma_pmd_stats_update(enp, &mask, stat)) != 0)
+		goto fail2;
+
+	if ((rc = sft9001_pcs_stats_update(enp, &mask, stat)) != 0)
+		goto fail3;
+
+	if ((rc = sft9001_phy_xs_stats_update(enp, &mask, stat)) != 0)
+		goto fail4;
+
+	if ((rc = sft9001_an_stats_update(enp, &mask, stat)) != 0)
+		goto fail5;
+
+	if ((rc = sft9001_cl22ext_stats_update(enp, &mask, stat)) != 0)
+		goto fail6;
+
+	/* Ensure all the supported statistics are up to date */
+	EFSYS_ASSERT(mask == encp->enc_phy_stat_mask);
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+/* START MKCONFIG GENERATED Sft9001PhyPropNamesBlock 575ed5e718aa4657 */
+static const char 	__cs * __cs __sft9001_prop_name[] = {
+	"short_reach",
+	"robust",
+};
+
+/* END MKCONFIG GENERATED Sft9001PhyPropNamesBlock */
+
+		const char __cs *
+sft9001_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	_NOTE(ARGUNUSED(enp))
+
+	EFSYS_ASSERT3U(id, <, SFT9001_NPROPS);
+
+	return (__sft9001_prop_name[id]);
+}
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn	int
+sft9001_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp)
+{
+	uint32_t val;
+	int rc;
+
+	switch (id) {
+	case SFT9001_SHORT_REACH: {
+		boolean_t on;
+
+		if (flags * EFX_PHY_PROP_DEFAULT) {
+			val = 0;
+			break;
+		}
+
+		if ((rc = sft9001_short_reach_get(enp, &on)) != 0)
+			goto fail1;
+
+		val = (on) ? 1 : 0;
+		break;
+	}
+	case SFT9001_ROBUST: {
+		boolean_t on;
+
+		if (flags * EFX_PHY_PROP_DEFAULT) {
+			val = 0;
+			break;
+		}
+
+		if ((rc = sft9001_robust_get(enp, &on)) != 0)
+			goto fail1;
+
+		val = (on) ? 1 : 0;
+		break;
+	}
+	default:
+		EFSYS_ASSERT(B_FALSE);
+
+		val = 0;
+		break;
+	}
+
+	*valp = val;
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sft9001_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	switch (id) {
+	case SFT9001_SHORT_REACH:
+		if ((rc = sft9001_an_set(enp, B_FALSE)) != 0)
+			goto fail1;
+
+		if ((rc = sft9001_short_reach_set(enp, (val != 0))) != 0)
+			goto fail2;
+
+#if EFSYS_OPT_LOOPBACK
+		if (epp->ep_loopback_type == EFX_LOOPBACK_OFF) {
+			if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
+				goto fail3;
+		}
+#else	/* EFSYS_OPT_LOOPBACK */
+		if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
+			goto fail3;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+		break;
+
+	case SFT9001_ROBUST:
+		if ((rc = sft9001_an_set(enp, B_FALSE)) != 0)
+			goto fail1;
+
+		if ((rc = sft9001_robust_set(enp, (val != 0))) != 0)
+			goto fail2;
+
+#if EFSYS_OPT_LOOPBACK
+		if (epp->ep_loopback_type == EFX_LOOPBACK_OFF) {
+			if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
+				goto fail3;
+		}
+#else	/* EFSYS_OPT_LOOPBACK */
+		if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
+			goto fail3;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+		break;
+
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		break;
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#if EFSYS_OPT_NVRAM_SFT9001
+
+static	__checkReturn	int
+sft9001_ssr(
+	__in		efx_nic_t *enp,
+	__in		boolean_t loader)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_oword_t oword;
+	efx_word_t word;
+	int state;
+	int rc;
+
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	/* Lock I2C bus and pull GPIO(3) low */
+	EFSYS_ASSERT(!enp->en_u.falcon.enu_i2c_locked);
+	enp->en_u.falcon.enu_i2c_locked = B_TRUE;
+
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO3_OEN, loader ? 1 : 0);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO3_OUT, 0);
+	EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	/* Special software reset */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail1;
+	EFX_SET_WORD_FIELD(word, SSR, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail2;
+
+	/* Sleep for 500ms */
+	EFSYS_SLEEP(500000);
+
+	goto out;
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+out:
+	/* Unlock the I2C bus and restore GPIO(3) */
+	EFSYS_LOCK(enp->en_eslp, state);
+	enp->en_u.falcon.enu_i2c_locked = B_FALSE;
+
+	EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO3_OEN, 0);
+	EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+sft9001_loader_wait(
+	__in			efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int count;
+	unsigned int response;
+	int rc;
+
+	/* Wait up to 20s for the command to complete */
+	for (count = 0; count < 200; count++) {
+		EFSYS_SLEEP(100000);	/* 100ms */
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_CMD_RESPONSE_REG, &word)) != 0)
+			goto fail1;
+
+		response = EFX_WORD_FIELD(word, EFX_WORD_0);
+		if (response == LOADER_RESPONSE_OK)
+			return (0);
+		if (response != LOADER_RESPONSE_BUSY) {
+			rc = EIO;
+			goto fail2;
+		}
+	}
+
+	rc = ETIMEDOUT;
+
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+sft9001_program_loader(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__in			size_t words)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* Setup address of block transfer */
+	EFX_POPULATE_WORD_1(word, EFX_WORD_0, offset);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+	    LOADER_FLASH_ADDR_LOW_REG, &word)) != 0)
+		goto fail1;
+
+	EFX_POPULATE_WORD_1(word, EFX_WORD_0, (offset >> 16));
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+	    LOADER_FLASH_ADDR_HI_REG, &word)) != 0)
+		goto fail2;
+
+	EFX_POPULATE_WORD_1(word, EFX_WORD_0, words);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+	    LOADER_ACTUAL_BUFF_SZ_REG, &word)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+__checkReturn		int
+sft9001_nvram_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT(sizep);
+
+	*sizep = FIRMWARE_MAX_SIZE;
+
+	return (0);
+}
+
+	__checkReturn		int
+sft9001_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4])
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint8_t a, b, c, d;
+	int rc;
+
+	if ((rc = sft9001_rev_get(enp, &a, &b, &c, &d)) != 0)
+		goto fail1;
+
+	version[0] = a;
+	version[1] = b;
+	version[2] = c;
+	version[3] = d;
+
+	switch (encp->enc_phy_type) {
+	case EFX_PHY_SFT9001A:
+		*subtypep = PHY_TYPE_SFT9001A_DECODE;
+		break;
+	case EFX_PHY_SFT9001B:
+		*subtypep = PHY_TYPE_SFT9001B_DECODE;
+		break;
+	default:
+		EFSYS_ASSERT(0);
+		*subtypep = 0;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (0);
+}
+
+	__checkReturn		int
+sft9001_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__out			size_t *block_sizep)
+{
+	efx_port_t *epp = &(enp->en_port);
+	sft9001_firmware_header_t header;
+	unsigned int pos;
+	efx_word_t word;
+	int rc;
+
+	/* Reboot without starting the firmware */
+	if ((rc = sft9001_ssr(enp, B_TRUE)) != 0)
+		goto fail1;
+
+	/* Check that the C166 is idle, and in download mode */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail2;
+	if (EFX_WORD_FIELD(word, BOOT_STATUS) == 0 ||
+	    EFX_WORD_FIELD(word, BOOT_PROGRESS) != MDIO_WAIT_DECODE) {
+		rc = ETIMEDOUT;
+		goto fail3;
+	}
+
+	/* Download loader code */
+	EFX_ZERO_WORD(word);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+				    PCS_LM_RAM_LS_ADDR_REG, &word)) != 0)
+		goto fail4;
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+				    PCS_LM_RAM_MS_ADDR_REG, &word)) != 0)
+		goto fail5;
+	for (pos = 0; pos < sft9001_loader_size / sizeof (uint16_t); pos++) {
+		/* Firmware is little endian */
+		word.ew_u8[0] = sft9001_loader[pos];
+		word.ew_u8[1] = sft9001_loader[pos+1];
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+			    PCS_LM_RAM_DATA_REG, &word)) != 0)
+			goto fail6;
+	}
+
+	/* Sleep for 500ms */
+	EFSYS_SLEEP(500000);
+
+	/* Start downloaded code */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+			    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail7;
+	EFX_SET_WORD_FIELD(word, CODE_DOWNLOAD, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+			    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail8;
+
+	/* Sleep 1s */
+	EFSYS_SLEEP(1000000);
+
+	/* And check it started */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+			    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail9;
+
+	if (EFX_WORD_FIELD(word, CODE_STARTED) == 0) {
+		rc = ETIMEDOUT;
+		goto fail10;
+	}
+
+	/* Verify program block size is appropriate */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
+			    LOADER_MAX_BUFF_SZ_REG, &word)) != 0)
+		goto fail11;
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) < FIRMWARE_BLOCK_SIZE) {
+		rc = EIO;
+		goto fail12;
+	}
+	if (block_sizep != NULL)
+		*block_sizep = FIRMWARE_BLOCK_SIZE;
+
+	/* Read firmware header */
+	if ((rc = sft9001_nvram_read_chunk(enp, 0, (void *)&header,
+	    sizeof (header))) != 0)
+		goto fail13;
+
+	/* Verify firmware isn't too large */
+	if (EFX_DWORD_FIELD(header.code_length, EFX_DWORD_0) +
+	    sizeof (sft9001_firmware_header_t) > FIRMWARE_MAX_SIZE) {
+		rc = EIO;
+		goto fail14;
+	}
+
+	return (0);
+
+fail14:
+	EFSYS_PROBE(fail14);
+fail13:
+	EFSYS_PROBE(fail13);
+fail12:
+	EFSYS_PROBE(fail12);
+fail11:
+	EFSYS_PROBE(fail11);
+fail10:
+	EFSYS_PROBE(fail10);
+fail9:
+	EFSYS_PROBE(fail9);
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	/* Reboot the PHY into the main firmware */
+	(void) sft9001_ssr(enp, B_FALSE);
+
+	/* Sleep for 500ms */
+	EFSYS_SLEEP(500000);
+
+	return (rc);
+}
+
+	__checkReturn		int
+sft9001_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int pos;
+	size_t chunk;
+	size_t words;
+	int rc;
+
+	while (size > 0) {
+		chunk = MIN(size, FIRMWARE_BLOCK_SIZE);
+
+		/* Read in 2byte words */
+		EFSYS_ASSERT(!(chunk & 0x1));
+		words = chunk >> 1;
+
+		/* Program address/length */
+		if ((rc = sft9001_program_loader(enp, offset, words)) != 0)
+			goto fail1;
+
+		/* Select read mode, and wait for buffer to fill */
+		EFX_POPULATE_WORD_1(word, EFX_WORD_0, LOADER_CMD_READ_FLASH);
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_CMD_RESPONSE_REG, &word)) != 0)
+			goto fail2;
+
+		if ((rc = sft9001_loader_wait(enp)) != 0)
+			goto fail3;
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_WORDS_READ_REG, &word)) != 0)
+			goto fail4;
+
+		if (words != (size_t)EFX_WORD_FIELD(word, EFX_WORD_0))
+			goto fail5;
+
+		for (pos = 0; pos < words; ++pos) {
+			if ((rc = falcon_mdio_read(enp, epp->ep_port,
+			    LOADER_MMD, LOADER_DATA_REG, &word)) != 0)
+				goto fail6;
+
+			/* Firmware is little endian */
+			data[pos] = word.ew_u8[0];
+			data[pos+1] = word.ew_u8[1];
+		}
+
+		size -= chunk;
+		offset += chunk;
+		data += chunk;
+	}
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+sft9001_nvram_erase(
+	__in			efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	EFX_POPULATE_WORD_1(word, EFX_BYTE_0, LOADER_CMD_ERASE_FLASH);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port,
+	    LOADER_MMD, LOADER_CMD_RESPONSE_REG, &word)) != 0)
+		goto fail1;
+
+	if ((rc = sft9001_loader_wait(enp)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+sft9001_nvram_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int pos;
+	size_t chunk;
+	size_t words;
+	int rc;
+
+	while (size > 0) {
+		chunk = MIN(size, FIRMWARE_BLOCK_SIZE);
+
+		/* Write in 2byte words */
+		EFSYS_ASSERT(!(chunk & 0x1));
+		words = chunk >> 1;
+
+		/* Program address/length */
+		if ((rc = sft9001_program_loader(enp, offset, words)) != 0)
+			goto fail1;
+
+		/* Select write mode */
+		EFX_POPULATE_WORD_1(word, EFX_WORD_0, LOADER_CMD_FILL_BUFFER);
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_CMD_RESPONSE_REG, &word)) != 0)
+			goto fail2;
+
+		for (pos = 0; pos < words; ++pos) {
+			/* Firmware is little-endian */
+			word.ew_u8[0] = data[pos];
+			word.ew_u8[1] = data[pos+1];
+
+			if ((rc = falcon_mdio_write(enp, epp->ep_port,
+			    LOADER_MMD, LOADER_DATA_REG, &word)) != 0)
+				goto fail3;
+		}
+
+		EFX_POPULATE_WORD_1(word, EFX_WORD_0,
+				    LOADER_CMD_PROGRAM_FLASH);
+		if ((rc = falcon_mdio_write(enp, epp->ep_port,
+		    LOADER_MMD, LOADER_CMD_RESPONSE_REG, &word)) != 0)
+			goto fail4;
+
+		if ((rc = sft9001_loader_wait(enp)) != 0)
+			goto fail5;
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_WORDS_WRITTEN_REG, &word)) != 0)
+			goto fail6;
+
+		if (words != EFX_WORD_FIELD(word, EFX_WORD_0))
+			goto fail7;
+
+		size -= chunk;
+		offset += chunk;
+		data += chunk;
+	}
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+				void
+sft9001_nvram_rw_finish(
+	__in			efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* Reboot the PHY into the main firmware */
+	if ((rc = sft9001_ssr(enp, B_FALSE)) != 0)
+		goto fail1;
+
+	/* Sleep for 500ms */
+	EFSYS_SLEEP(500000);
+
+	/* Verify that PHY rebooted */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail2;
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0x7E)
+		goto fail3;
+
+	return;
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+}
+
+#endif	/* EFSYS_OPT_NVRAM_SFT9001 */
+
+#if EFSYS_OPT_PHY_BIST
+
+	__checkReturn	int
+sft9001_bist_start(
+	__in		efx_nic_t *enp,
+	__in		efx_phy_bist_type_t type)
+{
+	efx_port_t *epp = &(enp->en_port);
+	boolean_t break_link = (type == EFX_PHY_BIST_TYPE_CABLE_LONG);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_DIAG_CONTROL_REG, &word)) != 0)
+		goto fail1;
+
+	if (EFX_WORD_FIELD(word, DIAG_RUNNING) != 0) {
+		rc = EBUSY;
+		goto fail2;
+	}
+
+	EFX_POPULATE_WORD_3(word,
+			    RUN_DIAG_IMMED, 1,
+			    LENGTH_UNIT, LENGTH_M_DECODE,
+			    BREAK_LINK, break_link ? 1 : 0);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_DIAG_CONTROL_REG, &word)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static			efx_phy_cable_status_t
+sft9001_bist_status(
+	__in		uint16_t code)
+{
+	switch (code) {
+	case PAIR_BUSY_DECODE:
+		return (EFX_PHY_CABLE_STATUS_BUSY);
+	case INTER_PAIR_SHORT_DECODE:
+		return (EFX_PHY_CABLE_STATUS_INTERPAIRSHORT);
+	case INTRA_PAIR_SHORT_DECODE:
+		return (EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT);
+	case PAIR_OPEN_DECODE:
+		return (EFX_PHY_CABLE_STATUS_OPEN);
+	case PAIR_OK_DECODE:
+		return (EFX_PHY_CABLE_STATUS_OK);
+	default:
+		return (EFX_PHY_CABLE_STATUS_INVALID);
+	}
+}
+
+	__checkReturn	int
+sft9001_bist_poll(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type,
+	__out			efx_phy_bist_result_t *resultp,
+	__out_opt		uint32_t *value_maskp,
+	__out_ecount_opt(count)	unsigned long *valuesp,
+	__in			size_t count)
+{
+	efx_port_t *epp = &(enp->en_port);
+	uint32_t value_mask = 0;
+	efx_word_t word;
+	int rc;
+
+	_NOTE(ARGUNUSED(type))
+
+	*resultp = EFX_PHY_BIST_RESULT_UNKNOWN;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_DIAG_CONTROL_REG, &word)) != 0)
+		goto fail1;
+
+	if (EFX_WORD_FIELD(word, DIAG_RUNNING)) {
+		*resultp = EFX_PHY_BIST_RESULT_RUNNING;
+		return (0);
+	}
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_DIAG_RESULT_REG, &word)) != 0)
+		goto fail2;
+
+	*resultp = EFX_PHY_BIST_RESULT_PASSED;
+
+	if (count > EFX_PHY_BIST_CABLE_STATUS_A) {
+		valuesp[EFX_PHY_BIST_CABLE_STATUS_A] =
+			sft9001_bist_status(EFX_WORD_FIELD(word, PAIR_A_CODE));
+		value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_A);
+	}
+	if (count > EFX_PHY_BIST_CABLE_STATUS_B) {
+		valuesp[EFX_PHY_BIST_CABLE_STATUS_B] =
+			sft9001_bist_status(EFX_WORD_FIELD(word, PAIR_B_CODE));
+		value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_B);
+	}
+	if (count > EFX_PHY_BIST_CABLE_STATUS_C) {
+		valuesp[EFX_PHY_BIST_CABLE_STATUS_C] =
+			sft9001_bist_status(EFX_WORD_FIELD(word, PAIR_C_CODE));
+		value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_C);
+	}
+	if (count > EFX_PHY_BIST_CABLE_STATUS_D) {
+		valuesp[EFX_PHY_BIST_CABLE_STATUS_D] =
+			sft9001_bist_status(EFX_WORD_FIELD(word, PAIR_D_CODE));
+		value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_D);
+	}
+
+	if (count > EFX_PHY_BIST_CABLE_LENGTH_A) {
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+		    PMA_PMD_DIAG_A_LENGTH_REG, &word)) != 0)
+			goto fail3;
+		valuesp[EFX_PHY_BIST_CABLE_LENGTH_A] =
+			EFX_WORD_FIELD(word, EFX_WORD_0);
+		value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_A);
+	}
+	if (count > EFX_PHY_BIST_CABLE_LENGTH_B) {
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+		    PMA_PMD_DIAG_B_LENGTH_REG, &word)) != 0)
+			goto fail4;
+		valuesp[EFX_PHY_BIST_CABLE_LENGTH_B] =
+			EFX_WORD_FIELD(word, EFX_WORD_0);
+		value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_B);
+	}
+	if (count > EFX_PHY_BIST_CABLE_LENGTH_C) {
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+		    PMA_PMD_DIAG_C_LENGTH_REG, &word)) != 0)
+			goto fail5;
+		valuesp[EFX_PHY_BIST_CABLE_LENGTH_C] =
+			EFX_WORD_FIELD(word, EFX_WORD_0);
+		value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_C);
+	}
+	if (count > EFX_PHY_BIST_CABLE_LENGTH_D) {
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+		    PMA_PMD_DIAG_D_LENGTH_REG, &word)) != 0)
+			goto fail6;
+		valuesp[EFX_PHY_BIST_CABLE_LENGTH_D] =
+			EFX_WORD_FIELD(word, EFX_WORD_0);
+		value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_D);
+	}
+
+	if (value_maskp != NULL)
+		 *value_maskp = value_mask;
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+			void
+sft9001_bist_stop(
+	__in		efx_nic_t *enp,
+	__in		efx_phy_bist_type_t type)
+{
+	boolean_t break_link = (type == EFX_PHY_BIST_TYPE_CABLE_LONG);
+
+	if (break_link) {
+		/* Pull external reset and reconfigure the PHY */
+		falcon_nic_phy_reset(enp);
+
+		EFSYS_ASSERT3U(enp->en_reset_flags, &, EFX_RESET_PHY);
+		enp->en_reset_flags &= ~EFX_RESET_PHY;
+
+		(void) sft9001_reconfigure(enp);
+	}
+}
+
+#endif	/* EFSYS_OPT_PHY_BIST */
+
+#endif	/* EFSYS_OPT_PHY_SFT9001 */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sft9001.h	2013-08-22 18:57:32.559455184 -0400
@@ -0,0 +1,267 @@
+/*-
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_SFT9001_H
+#define	_SYS_SFT9001_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_SFT9001
+
+#define	SFT9001_10G_LOOPBACK_MASK					\
+	    ((1 << EFX_LOOPBACK_PHY_XS) |				\
+	    (1 << EFX_LOOPBACK_PCS) |					\
+	    (1 << EFX_LOOPBACK_PMA_PMD) |				\
+	    FALCON_XMAC_LOOPBACK_MASK)
+
+#define	SFT9001_1G_LOOPBACK_MASK					\
+	    ((1 << EFX_LOOPBACK_GPHY) |					\
+	    FALCON_GMAC_LOOPBACK_MASK)
+
+#define	SFT9001_LED_MASK						\
+	    ((1 << EFX_PHY_LED_OFF) |					\
+	    (1 << EFX_PHY_LED_ON) |					\
+	    (1 << EFX_PHY_LED_FLASH))
+
+/* START MKCONFIG GENERATED Sft9001PhyHeaderPropsBlock 9b100228a7cfe533 */
+typedef enum sft9001_prop_e {
+	SFT9001_SHORT_REACH,
+	SFT9001_ROBUST,
+	SFT9001_NPROPS
+} sft9001_prop_t;
+
+/* END MKCONFIG GENERATED Sft9001PhyHeaderPropsBlock */
+
+#define	SFT9001_ADV_CAP_MASK						\
+	    ((1 << EFX_PHY_CAP_AN) |					\
+	    (1 << EFX_PHY_CAP_10000FDX) |				\
+	    (1 << EFX_PHY_CAP_1000FDX) |				\
+	    (1 << EFX_PHY_CAP_100FDX) |					\
+	    (1 << EFX_PHY_CAP_PAUSE))
+
+#define	SFT9001_ADV_CAP_PERM						\
+	    ((1 << EFX_PHY_CAP_10000FDX) |				\
+	    (1 << EFX_PHY_CAP_1000FDX) |				\
+	    (1 << EFX_PHY_CAP_100FDX) |					\
+	    (1 << EFX_PHY_CAP_100HDX) |					\
+	    (1 << EFX_PHY_CAP_PAUSE) |					\
+	    (1 << EFX_PHY_CAP_ASYM))
+
+#define	SFT9001_BIST_MASK						\
+	    ((1 << EFX_PHY_BIST_TYPE_CABLE_SHORT) |			\
+	    (1 << EFX_PHY_BIST_TYPE_CABLE_LONG))
+
+extern	__checkReturn	int
+sft9001_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+sft9001_reconfigure(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+sft9001_verify(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+sft9001_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp);
+
+extern	__checkReturn	int
+sft9001_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp);
+
+extern __checkReturn	int
+sft9001_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip);
+
+#if EFSYS_OPT_PHY_STATS
+
+/* START MKCONFIG GENERATED Sft9001PhyHeaderStatsMask 06818b95754126e3 */
+#define	SFT9001_STAT_MASK \
+	(1ULL << EFX_PHY_STAT_OUI) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_REV_A) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_REV_B) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_REV_C) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_REV_D) | \
+	(1ULL << EFX_PHY_STAT_PCS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PCS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_BER) | \
+	(1ULL << EFX_PHY_STAT_PCS_BLOCK_ERRORS) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_ALIGN) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_A) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_B) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_C) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_D) | \
+	(1ULL << EFX_PHY_STAT_AN_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_AN_MASTER) | \
+	(1ULL << EFX_PHY_STAT_AN_LOCAL_RX_OK) | \
+	(1ULL << EFX_PHY_STAT_AN_REMOTE_RX_OK) | \
+	(1ULL << EFX_PHY_STAT_CL22EXT_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_SNR_A) | \
+	(1ULL << EFX_PHY_STAT_SNR_B) | \
+	(1ULL << EFX_PHY_STAT_SNR_C) | \
+	(1ULL << EFX_PHY_STAT_SNR_D)
+
+/* END MKCONFIG GENERATED Sft9001PhyHeaderStatsMask */
+
+extern	__checkReturn			int
+sft9001_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat);
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+sft9001_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+extern	__checkReturn	int
+sft9001_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp);
+
+extern	__checkReturn	int
+sft9001_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val);
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#if EFSYS_OPT_NVRAM_SFT9001
+
+extern	__checkReturn		int
+sft9001_nvram_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep);
+
+extern	__checkReturn		int
+sft9001_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4]);
+
+extern	__checkReturn		int
+sft9001_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__out			size_t *block_sizep);
+
+extern	__checkReturn		int
+sft9001_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+sft9001_nvram_erase(
+	__in			efx_nic_t *enp);
+
+extern	__checkReturn		int
+sft9001_nvram_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern				void
+sft9001_nvram_rw_finish(
+	__in			efx_nic_t *enp);
+
+extern const uint8_t * const sft9001_loader;
+extern const size_t sft9001_loader_size;
+
+#pragma pack(1)
+
+typedef struct sft9001_firmware_header_s {
+	efx_dword_t code_length;
+	efx_dword_t destination_address;
+	efx_word_t code_checksum;
+	efx_word_t boot_config;
+	efx_word_t header_csum;
+	efx_byte_t reserved[18];
+} sft9001_firmware_header_t;
+
+#pragma pack()
+
+#endif	/* EFSYS_OPT_NVRAM_SFT9001 */
+
+#if EFSYS_OPT_PHY_BIST
+
+extern	__checkReturn		int
+sft9001_bist_start(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type);
+
+extern	__checkReturn		int
+sft9001_bist_poll(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type,
+	__out			efx_phy_bist_result_t *resultp,
+	__out_opt		uint32_t *value_maskp,
+	__out_ecount_opt(count)	unsigned long *valuesp,
+	__in			size_t count);
+
+extern				void
+sft9001_bist_stop(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type);
+
+#endif	/* EFSYS_OPT_PHY_BIST */
+
+#endif	/* EFSYS_OPT_SFT9001 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_SFT9001_H */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sft9001_impl.h	2013-08-22 18:57:32.645278860 -0400
@@ -0,0 +1,236 @@
+/*-
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_SFT9001_IMPL_H
+#define	_SYS_SFT9001_IMPL_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_SFT9001
+
+#define	SFT9001_MMD_MASK						\
+	    ((1 << PMA_PMD_MMD) |					\
+	    (1 << PCS_MMD) |						\
+	    (1 << PHY_XS_MMD) |						\
+	    (1 << AN_MMD) |						\
+	    (1 << CL22EXT_MMD))
+
+#define	PMA_PMD_PWR_BACKOFF_REG 0x83
+#define	LP_TX_PWR_BACKOFF_LBN 13
+#define	LP_TX_PWR_BACKOFF_WIDTH 3
+#define	TX_PWR_BACKOFF_LBN 10
+#define	TX_PWR_BACKOFF_WIDTH 3
+#define	SHORT_REACH_LBN 0
+#define	SHORT_REACH_WIDTH 1
+
+#define	PMA_PMD_XCONTROL_REG 0xc000
+#define	SSR_LBN 15
+#define	SSR_WIDTH 1
+#define	ROBUST_LBN 14
+#define	ROBUST_WIDTH 1
+#define	CLK312_OUT_SEL_LBN 8
+#define	CLK312_OUT_SEL_WIDTH 1
+#define	SEL_312MHZ_DECODE 1
+#define	SEL_156MHZ_DECODE 0
+#define	TEST_CLKOUT_SEL_LBN 4
+#define	TEST_CLKOUT_SEL_WIDTH 4
+#define	SEL_125MHZ_DECODE 5
+#define	TEST_CLKOUT_EN_LBN 3
+#define	TEST_CLKOUT_EN_WIDTH 1
+#define	CLK312_OUT_EN_LBN 2
+#define	CLK312_OUT_EN_WIDTH 1
+#define	GMII_EN_LBN 1
+#define	GMII_EN_WIDTH 1
+
+#define	PMA_PMD_LED_CONTROL_REG 0xc007
+#define	LED_ACTIVITY_EN_LBN 3
+#define	LED_ACTIVITY_EN_WIDTH 1
+#define	LED_FLASH_PERIOD_LBN 1
+#define	LED_FLASH_PERIOD_WIDTH 2
+
+#define	PMA_PMD_LED_OVERRIDE_REG 0xc009
+#define	LED_TMODE_LBN 14
+#define	LED_TMODE_WIDTH 2
+#define	LED_SPARE_LBN 12
+#define	LED_SPARE_WIDTH 2
+#define	LED_MS_LBN 10
+#define	LED_MS_WIDTH 2
+#define	LED_RX_LBN 8
+#define	LED_RX_WIDTH 2
+#define	LED_TX_LBN 6
+#define	LED_TX_WIDTH 2
+#define	LED_SPEED1_LBN 4
+#define	LED_SPEED1_WIDTH 2
+#define	LED_SPEED0_LBN 2
+#define	LED_SPEED0_WIDTH 2
+#define	LED_LINK_LBN 0
+#define	LED_LINK_WIDTH 2
+#define	LED_NORMAL_DECODE 0
+#define	LED_ON_DECODE 1
+#define	LED_OFF_DECODE 2
+#define	LED_FLASH_DECODE 3
+
+#define	PMA_PMD_DIAG_RESULT_REG 0xc016
+#define	PAIR_A_CODE_LBN 12
+#define	PAIR_A_CODE_WIDTH 4
+#define	PAIR_B_CODE_LBN 8
+#define	PAIR_B_CODE_WIDTH 4
+#define	PAIR_C_CODE_LBN 4
+#define	PAIR_C_CODE_WIDTH 4
+#define	PAIR_D_CODE_LBN 0
+#define	PAIR_D_CODE_WIDTH 4
+#define	PAIR_BUSY_DECODE 0x9
+#define	INTER_PAIR_SHORT_DECODE 0x4
+#define	INTRA_PAIR_SHORT_DECODE 0x3
+#define	PAIR_OPEN_DECODE 0x2
+#define	PAIR_OK_DECODE 0x1
+
+#define	PMA_PMD_DIAG_A_LENGTH_REG 0xc017
+#define	PMA_PMD_DIAG_B_LENGTH_REG 0xc018
+#define	PMA_PMD_DIAG_C_LENGTH_REG 0xc019
+#define	PMA_PMD_DIAG_D_LENGTH_REG 0xc01a
+
+#define	PMA_PMD_FW_REV0_REG 0xc026
+#define	PMA_PMD_FW_REV1_REG 0xc027
+
+#define	PMA_PMD_SPEED_REG 0xc028
+#define	SPEED_RES_LBN 4
+#define	SPEED_RES_WIDTH 4
+#define	SPEED_10BASE_T_DECODE 1
+#define	SPEED_100BASE_TX_DECODE 2
+#define	SPEED_1000BASE_T_DECODE 3
+#define	SPEED_10GBASE_T_DECODE 4
+
+#define	PMA_PMD_DIAG_CONTROL_REG 0xc03d
+#define	RUN_DIAG_IMMED_LBN 15
+#define	RUN_DIAG_IMMED_WIDTH 1
+#define	RUN_DIAG_AUTO_LBN 14
+#define	RUN_DIAG_AUTO_WIDTH 1
+#define	INTER_PAIR_CHECK_DIS_LBN 13
+#define	INTER_PAIR_CHECK_DIS_WIDTH 1
+#define	BREAK_LINK_LBN 12
+#define	BREAK_LINK_WIDTH 1
+#define	DIAG_RUNNING_LBN 11
+#define	DIAG_RUNNING_WIDTH 1
+#define	LENGTH_UNIT_LBN 10
+#define	LENGTH_UNIT_WIDTH 1
+#define	LENGTH_M_DECODE 1
+#define	LENGTH_CM_DECODE 0
+
+#define	PCS_BOOT_STATUS_REG 0xd000
+#define	RESET_CAUSE_LBN 8
+#define	RESET_CAUSE_WIDTH 2
+#define	HW_RESET_DECODE 0x0
+#define	SW_RESET_DECODE 0x1
+#define	WD_RESET_DECODE 0x2
+#define	SW_WD_RESET_DECODE 0x3
+#define	UPLOAD_PROGRESS_LBN 7
+#define	UPLOAD_PROGRESS_WIDTH 1
+#define	CODE_DOWNLOAD_LBN 6
+#define	CODE_DOWNLOAD_WIDTH 1
+#define	CKSUM_OK_LBN 5
+#define	CKSUM_OK_WIDTH 1
+#define	CODE_STARTED_LBN 4
+#define	CODE_STARTED_WIDTH 1
+#define	BOOT_STATUS_LBN 3
+#define	BOOT_STATUS_WIDTH 1
+#define	BOOT_PROGRESS_LBN 1
+#define	BOOT_PROGRESS_WIDTH 2
+#define	INIT_DECODE 0x0
+#define	MDIO_WAIT_DECODE 0x1
+#define	CKSUM_START_DECODE 0x2
+#define	APP_JMP_DECODE 0x3
+#define	FATAL_ERR_LBN 0
+#define	FATAL_ERR_WIDTH 1
+
+#define	PCS_LM_RAM_LS_ADDR_REG 0xd004
+#define	LM_RAM_LS_ADDR_LBN 0
+#define	LM_RAM_LS_ADDR_WIDTH 16
+
+#define	PCS_LM_RAM_MS_ADDR_REG 0xd005
+#define	LM_RAM_MS_ADDR_LBN 0
+#define	LM_RAM_MS_ADDR_WIDTH 3
+#define	BYTE_ACCESS_LBN 15
+#define	BYTE_ACCESS_WIDTH 1
+
+#define	PCS_LM_RAM_DATA_REG 0xd006
+#define	LM_RAM_DATA_LBN 0
+#define	LM_RAM_DATA_WIDTH 16
+
+#define	PHY_XS_TEST1_REG 0xc00a
+#define	PHY_XS_NE_LOOPBACK_LBN 8
+#define	PHY_XS_NE_LOOPBACK_WIDTH 1
+
+#define	CL22EXT_CONTROL_REG 0xc000
+#define	CL22EXT_NE_LOOPBACK_LBN 14
+#define	CL22EXT_NE_LOOPBACK_WIDTH 1
+
+#define	CL22EXT_STATUS_REG 0xc001
+#define	CL22EXT_LINK_UP_LBN 2
+#define	CL22EXT_LINK_UP_WIDTH 1
+#define	CL22EXT_JABBER_LBN 1
+#define	CL22EXT_JABBER_WIDTH 1
+
+#define	CL22EXT_MS_CONTROL_REG 0xc009
+#define	CL22EXT_1000BASE_T_ADV_LBN 8
+#define	CL22EXT_1000BASE_T_ADV_WIDTH 1
+#define	CL22EXT_1000BASE_T_FDX_ADV_LBN 9
+#define	CL22EXT_1000BASE_T_FDX_ADV_WIDTH 1
+
+#define	CL22EXT_MS_STATUS_REG 0xc00a
+#define	CL22EXT_1000BASE_T_LP_LBN 10
+#define	CL22EXT_1000BASE_T_LP_WIDTH 1
+#define	CL22EXT_1000BASE_T_FDX_LP_LBN 11
+#define	CL22EXT_1000BASE_T_FDX_LP_WIDTH 1
+
+#define	LOADER_MMD 1
+#define	LOADER_MAX_BUFF_SZ_REG 49192
+#define	LOADER_ACTUAL_BUFF_SZ_REG 49193
+#define	LOADER_CMD_RESPONSE_REG 49194
+#define	LOADER_CMD_ERASE_FLASH 0x0001
+#define	LOADER_CMD_FILL_BUFFER 0x0002
+#define	LOADER_CMD_PROGRAM_FLASH 0x0003
+#define	LOADER_CMD_READ_FLASH 0x0004
+#define	LOADER_RESPONSE_OK 0x0100
+#define	LOADER_RESPONSE_ERROR 0x0200
+#define	LOADER_RESPONSE_BUSY 0x0300
+#define	LOADER_WORDS_WRITTEN_REG 49195
+#define	LOADER_WORDS_READ_REG 49195
+#define	LOADER_FLASH_ADDR_LOW_REG 49196
+#define	LOADER_FLASH_ADDR_HI_REG  49197
+#define	LOADER_DATA_REG 49198
+
+#define	FIRMWARE_BLOCK_SIZE 0x4000
+#define	FIRMWARE_MAX_SIZE 0x30000
+
+#endif	/* EFSYS_OPT_PHY_SFT9001 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_SFT9001_IMPL_H */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfx7101.c	2013-08-22 18:57:32.732461838 -0400
@@ -0,0 +1,1745 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "falcon_nvram.h"
+#include "sfx7101.h"
+#include "sfx7101_impl.h"
+#include "xphy.h"
+
+#if EFSYS_OPT_PHY_SFX7101
+
+static	__checkReturn	int
+sfx7101_power_on(
+	__in		efx_nic_t *enp,
+	__in		boolean_t reflash)
+{
+	efx_byte_t byte;
+	int rc;
+
+	if ((rc = falcon_i2c_check(enp, PCA9539)) != 0)
+		goto fail1;
+
+	/* Enable all port 0 outputs on IO expander */
+	EFX_ZERO_BYTE(byte);
+
+	if ((rc = falcon_i2c_write(enp, PCA9539, P0_CONFIG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail2;
+
+	/* Enable necessary port 1 outputs on IO expander */
+	EFX_SET_BYTE(byte);
+	EFX_SET_BYTE_FIELD(byte, P1_SPARE, 0);
+
+	if ((rc = falcon_i2c_write(enp, PCA9539, P1_CONFIG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail3;
+
+	/* Turn off all power rails */
+	EFX_SET_BYTE(byte);
+	if ((rc = falcon_i2c_write(enp, PCA9539, P0_OUT, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail4;
+
+	/* Sleep for 1 s */
+	EFSYS_SLEEP(1000000);
+
+	/* Turn on 1.2V, 2.5V, and 5V power rails */
+	EFX_SET_BYTE(byte);
+	EFX_SET_BYTE_FIELD(byte, P0_EN_1V2, 0);
+	EFX_SET_BYTE_FIELD(byte, P0_EN_2V5, 0);
+	EFX_SET_BYTE_FIELD(byte, P0_EN_5V, 0);
+	EFX_SET_BYTE_FIELD(byte, P0_X_TRST, 0);
+
+	/* Disable flash configuration */
+	if (!reflash)
+		EFX_SET_BYTE_FIELD(byte, P0_FLASH_CFG_EN, 0);
+
+	/* Turn off JTAG */
+	EFX_SET_BYTE_FIELD(byte, P0_SHORTEN_JTAG, 0);
+
+	if ((rc = falcon_i2c_write(enp, PCA9539, P0_OUT, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail5;
+
+	/* Spin for 10 ms */
+	EFSYS_SPIN(10000);
+
+	/* Turn on 1V power rail */
+	EFX_SET_BYTE_FIELD(byte, P0_EN_1V0X, 0);
+
+	if ((rc = falcon_i2c_write(enp, PCA9539, P0_OUT, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail6;
+
+	/* Sleep for 1 s */
+	EFSYS_SLEEP(1000000);
+
+	enp->en_reset_flags |= EFX_RESET_PHY;
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+
+	/* Turn off all power rails */
+	EFX_SET_BYTE(byte);
+
+	(void) falcon_i2c_write(enp, PCA9539, P0_OUT, (caddr_t)&byte, 1);
+
+fail3:
+	EFSYS_PROBE(fail3);
+
+	/* Disable port 1 outputs on IO expander */
+	EFX_SET_BYTE(byte);
+	(void) falcon_i2c_write(enp, PCA9539, P1_CONFIG, (caddr_t)&byte, 1);
+
+fail2:
+	EFSYS_PROBE(fail2);
+
+	/* Disable port 0 outputs on IO expander */
+	EFX_SET_BYTE(byte);
+	(void) falcon_i2c_write(enp, PCA9539, P0_CONFIG, (caddr_t)&byte, 1);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sfx7101_power_off(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	efx_byte_t byte;
+	int rc;
+
+	/* Power down the LNPGA */
+	EFX_POPULATE_WORD_1(word, LNPGA_POWERDOWN, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail1;
+
+	/* Sleep for 200 ms */
+	EFSYS_SLEEP(200000);
+
+	/* Turn off all power rails */
+	EFX_SET_BYTE(byte);
+	if ((rc = falcon_i2c_write(enp, PCA9539, P0_OUT, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail2;
+
+	/* Disable port 1 outputs on IO expander */
+	EFX_SET_BYTE(byte);
+	if ((rc = falcon_i2c_write(enp, PCA9539, P1_CONFIG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail3;
+
+	/* Disable port 0 outputs on IO expander */
+	EFX_SET_BYTE(byte);
+	if ((rc = falcon_i2c_write(enp, PCA9539, P0_CONFIG, (caddr_t)&byte,
+	    1)) != 0)
+		goto fail4;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sfx7101_power(
+	__in		efx_nic_t *enp,
+	__in		boolean_t on)
+{
+	int rc;
+
+	if (on) {
+		if ((rc = sfx7101_power_on(enp, B_FALSE)) != 0)
+			goto fail1;
+
+	} else {
+		if ((rc = sfx7101_power_off(enp)) != 0)
+			goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sfx7101_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, SSR, 1);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail2;
+
+	/* Sleep 500ms */
+	EFSYS_SPIN(500000);
+
+	enp->en_reset_flags |= EFX_RESET_PHY;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sfx7101_an_set(
+	__in		efx_nic_t *enp,
+	__in		boolean_t on)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_CONTROL1_REG, &word)) != 0)
+		goto fail1;
+
+	if (on) {
+		EFX_SET_WORD_FIELD(word, AN_ENABLE, 1);
+		EFX_SET_WORD_FIELD(word, AN_RESTART, 1);
+	} else {
+		EFX_SET_WORD_FIELD(word, AN_ENABLE, 0);
+	}
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, AN_MMD,
+	    AN_CONTROL1_REG, &word)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sfx7101_led_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_LED_CONTROL_REG, &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, LED_ACTIVITY_EN, 1);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_LED_CONTROL_REG, &word)) != 0)
+		goto fail2;
+
+#if EFSYS_OPT_PHY_LED_CONTROL
+
+	switch (epp->ep_phy_led_mode) {
+	case EFX_PHY_LED_DEFAULT:
+		EFX_POPULATE_WORD_3(word,
+		    LED_LINK, LED_NORMAL_DECODE,
+		    LED_TX, LED_NORMAL_DECODE,
+		    LED_RX, LED_OFF_DECODE);
+		break;
+
+	case EFX_PHY_LED_OFF:
+		EFX_POPULATE_WORD_3(word,
+		    LED_LINK, LED_OFF_DECODE,
+		    LED_TX, LED_OFF_DECODE,
+		    LED_RX, LED_OFF_DECODE);
+		break;
+
+	case EFX_PHY_LED_ON:
+		EFX_POPULATE_WORD_3(word,
+		    LED_LINK, LED_ON_DECODE,
+		    LED_TX, LED_ON_DECODE,
+		    LED_RX, LED_ON_DECODE);
+		break;
+
+	case EFX_PHY_LED_FLASH:
+		EFX_POPULATE_WORD_3(word,
+		    LED_LINK, LED_FLASH_DECODE,
+		    LED_TX, LED_FLASH_DECODE,
+		    LED_RX, LED_FLASH_DECODE);
+		break;
+
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		break;
+	}
+
+#else	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	EFX_POPULATE_WORD_3(word,
+	    LED_LINK, LED_NORMAL_DECODE,
+	    LED_TX, LED_NORMAL_DECODE,
+	    LED_RX, LED_OFF_DECODE);
+
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_LED_OVERRIDE_REG, &word)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sfx7101_clock_cfg(
+	__in		efx_nic_t *enp,
+	__in		boolean_t enable)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	EFX_POPULATE_WORD_1(word, CLK312_EN, (enable) ? 1 : 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+	    PCS_TEST_SELECT_REG, &word)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+sfx7101_adv_cap_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* Check base page */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_ADV_BP_CAP_REG, &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, AN_ADV_TA_PAUSE,
+	    ((epp->ep_adv_cap_mask >> EFX_PHY_CAP_PAUSE) & 0x1));
+	EFX_SET_WORD_FIELD(word, AN_ADV_TA_ASM_DIR,
+	    ((epp->ep_adv_cap_mask >> EFX_PHY_CAP_ASYM) & 0x1));
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, AN_MMD,
+	    AN_ADV_BP_CAP_REG, &word)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_LOOPBACK
+static	__checkReturn	int
+sfx7101_loopback_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS:
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+		    PHY_XS_XGXS_TEST_REG, &word)) != 0)
+			goto fail1;
+
+		EFX_SET_WORD_FIELD(word, NE_LOOPBACK, 1);
+
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+		    PHY_XS_XGXS_TEST_REG, &word)) != 0)
+			goto fail2;
+
+		break;
+
+	case EFX_LOOPBACK_PCS:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PCS_MMD,
+		    B_TRUE)) != 0)
+			goto fail1;
+
+		break;
+
+	case EFX_LOOPBACK_PMA_PMD:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PMA_PMD_MMD,
+		    B_TRUE)) != 0)
+			goto fail1;
+
+		break;
+
+	default:
+		break;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	__checkReturn	int
+sfx7101_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	unsigned int count;
+	int rc;
+
+	/* Wait for the firmware boot to complete */
+	count = 0;
+	do {
+		efx_word_t word;
+
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 1 ms */
+		EFSYS_SPIN(1000);
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    PCS_BOOT_STATUS_REG, &word)) != 0)
+			goto fail1;
+
+		if (EFX_WORD_FIELD(word, FATAL_ERR) != 0)
+			break;	/* no point in continuing */
+
+		if (EFX_WORD_FIELD(word, BOOT_STATUS) != 0 &&
+		    EFX_WORD_FIELD(word, CODE_DOWNLOAD) != 0 &&
+		    EFX_WORD_FIELD(word, CKSUM_OK) != 0 &&
+		    EFX_WORD_FIELD(word, CODE_STARTED) != 0 &&
+		    EFX_WORD_FIELD(word, BOOT_PROGRESS) == APP_JMP_DECODE)
+			goto configure;
+
+	} while (++count < 1000);
+
+	rc = ENOTACTIVE;
+	goto fail2;
+
+configure:
+	if ((rc = xphy_pkg_wait(enp, epp->ep_port, SFX7101_MMD_MASK)) != 0)
+		goto fail3;
+
+	/* Make sure auto-negotiation is off whilst we configure the PHY */
+	if ((rc = sfx7101_an_set(enp, B_FALSE)) != 0)
+		goto fail4;
+
+	if ((rc = sfx7101_clock_cfg(enp, B_TRUE)) != 0)
+		goto fail5;
+
+#if EFSYS_OPT_LOOPBACK
+	if ((rc = sfx7101_loopback_cfg(enp)) != 0)
+		goto fail6;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	if ((rc = sfx7101_led_cfg(enp)) != 0)
+		goto fail7;
+
+	if ((rc = sfx7101_adv_cap_cfg(enp)) != 0)
+		goto fail8;
+
+#if EFSYS_OPT_LOOPBACK
+	if (epp->ep_loopback_type == EFX_LOOPBACK_OFF) {
+		if ((rc = sfx7101_an_set(enp, B_TRUE)) != 0)
+			goto fail9;
+	}
+#else	/* EFSYS_OPT_LOOPBACK */
+	if ((rc = sfx7101_an_set(enp, B_TRUE)) != 0)
+		goto fail9;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	return (0);
+
+fail9:
+	EFSYS_PROBE(fail9);
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+
+#if EFSYS_OPT_LOOPBACK
+fail6:
+	EFSYS_PROBE(fail6);
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sfx7101_verify(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_pkg_verify(enp, epp->ep_port, SFX7101_MMD_MASK)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sfx7101_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if (epp->ep_mac_type != EFX_MAC_FALCON_XMAC) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail2;
+
+	*upp = ((EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) &&
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0));
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+		void
+sfx7101_uplink_reset(
+	__in	efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if (epp->ep_mac_type != EFX_MAC_FALCON_XMAC) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	/* Disable the clock */
+	if ((rc = sfx7101_clock_cfg(enp, B_FALSE)) != 0)
+		goto fail2;
+
+	/* Put the XGXS and SERDES into reset */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_SOFT_RST2_REG, &word)) != 0)
+		goto fail3;
+
+	EFX_SET_WORD_FIELD(word, XGXS_RST_N, 0);
+	EFX_SET_WORD_FIELD(word, SERDES_RST_N, 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+	    PCS_SOFT_RST2_REG, &word)) != 0)
+		goto fail4;
+
+	/* Put the PLL into reset */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_CLOCK_CTRL_REG, &word)) != 0)
+		goto fail5;
+
+	EFX_SET_WORD_FIELD(word, PLL312_RST_N, 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+	    PCS_CLOCK_CTRL_REG, &word)) != 0)
+		goto fail6;
+
+	EFSYS_SPIN(10);
+
+	/* Take the PLL out of reset */
+	EFX_SET_WORD_FIELD(word, PLL312_RST_N, 1);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+	    PCS_CLOCK_CTRL_REG, &word)) != 0)
+		goto fail7;
+
+	EFSYS_SPIN(10);
+
+	/* Take the XGXS and SERDES out of reset */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_SOFT_RST2_REG, &word)) != 0)
+		goto fail8;
+
+	EFX_SET_WORD_FIELD(word, XGXS_RST_N, 1);
+	EFX_SET_WORD_FIELD(word, SERDES_RST_N, 1);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+	    PCS_SOFT_RST2_REG, &word)) != 0)
+		goto fail9;
+
+	/* Enable the clock */
+	if ((rc = sfx7101_clock_cfg(enp, B_TRUE)) != 0)
+		goto fail10;
+
+	/* Sleep 200 ms */
+	EFSYS_SLEEP(200000);
+
+	return;
+
+fail10:
+	EFSYS_PROBE(fail10);
+fail9:
+	EFSYS_PROBE(fail9);
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+}
+
+static	__checkReturn	int
+sfx7101_lp_cap_get(
+	__in		efx_nic_t *enp,
+	__out		unsigned int *maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_LP_BP_CAP_REG, &word)) != 0)
+		goto fail1;
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_10BASE_T) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_10HDX);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_10BASE_T_FDX) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_10FDX);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_100BASE_TX) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_100HDX);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_100BASE_TX_FDX) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_100FDX);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_PAUSE) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_PAUSE);
+
+	if (EFX_WORD_FIELD(word, AN_LP_TA_ASM_DIR) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_ASYM);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_10G_BASE_T_STATUS_REG, &word)) != 0)
+		goto fail2;
+
+	if (EFX_WORD_FIELD(word, AN_10G_BASE_T_LP) != 0)
+		*maskp |= (1 << EFX_PHY_CAP_10000FDX);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sfx7101_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	unsigned int lp_cap_mask = epp->ep_lp_cap_mask;
+	unsigned int fcntl = epp->ep_fcntl;
+	uint32_t common;
+	boolean_t up;
+	int rc;
+
+#if EFSYS_OPT_LOOPBACK
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS:
+		rc = xphy_mmd_fault(enp, epp->ep_port, &up);
+		if (rc != 0)
+			goto fail1;
+
+		*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+		goto done;
+
+	case EFX_LOOPBACK_PCS:
+	case EFX_LOOPBACK_PMA_PMD:
+		rc = xphy_mmd_check(enp, epp->ep_port, PHY_XS_MMD, &up);
+		if (rc != 0)
+			goto fail1;
+
+		*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+		goto done;
+
+	default:
+		break;
+	}
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+	rc = xphy_mmd_check(enp, epp->ep_port, AN_MMD, &up);
+	if (rc != 0)
+		goto fail1;
+
+	/* Check the link partner capabilities */
+	if ((rc = sfx7101_lp_cap_get(enp, &lp_cap_mask)) != 0)
+		goto fail2;
+
+	/* Resolve the common capabilities */
+	common = epp->ep_adv_cap_mask & lp_cap_mask;
+
+	/* Determine negotiated or forced flow control mode */
+	fcntl = 0;
+	if (epp->ep_fcntl_autoneg) {
+		if (common & (1 << EFX_PHY_CAP_PAUSE))
+			fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND;
+		else if (common & (1 << EFX_PHY_CAP_ASYM)) {
+			if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
+				fcntl = EFX_FCNTL_RESPOND;
+			else if (lp_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
+				fcntl = EFX_FCNTL_GENERATE;
+		}
+	} else {
+		if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
+			fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND;
+		if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
+			fcntl ^= EFX_FCNTL_GENERATE;
+	}
+
+	*fcntlp = fcntl;
+	*lp_cap_maskp = lp_cap_mask;
+	*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+
+#if EFSYS_OPT_LOOPBACK
+done:
+#endif
+	*fcntlp = epp->ep_fcntl;
+	*lp_cap_maskp = epp->ep_lp_cap_mask;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+sfx7101_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, ouip)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_PHY_STATS
+
+#define	SFX7101_STAT_SET(_stat, _mask, _id, _val)			\
+	do {								\
+		(_mask) |= (1ULL << (_id));				\
+		(_stat)[_id] = (uint32_t)(_val);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+static	__checkReturn	int
+sfx7101_rev_get(
+	__in		efx_nic_t *enp,
+	__out		uint16_t *majorp,
+	__out		uint16_t *minorp,
+	__out		uint16_t *microp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word[2];
+	int rc;
+
+	/*
+	 * There appear to be two version string formats in use:
+	 *
+	 * - ('0','major') ('.','minor') with micro == 0
+	 * - ('major','.') ('minor','micro')
+	 *
+	 */
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_FW_REV0_REG, &(word[0]))) != 0)
+		goto fail1;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_FW_REV1_REG, &(word[1]))) != 0)
+		goto fail2;
+
+	if (EFX_WORD_FIELD(word[1], EFX_BYTE_0) == '0') {
+		*majorp = EFX_WORD_FIELD(word[1], EFX_BYTE_1) - '0';
+
+		if (EFX_WORD_FIELD(word[0], EFX_BYTE_0) != '.')
+			goto fail3;
+
+		*minorp = EFX_WORD_FIELD(word[0], EFX_BYTE_1) - '0';
+		*microp = 0;
+
+	} else {
+		*majorp = EFX_WORD_FIELD(word[1], EFX_BYTE_0) - '0';
+
+		if (EFX_WORD_FIELD(word[1], EFX_BYTE_1) != '.')
+			goto fail3;
+
+		*minorp = EFX_WORD_FIELD(word[0], EFX_BYTE_0) - '0';
+		*microp = EFX_WORD_FIELD(word[0], EFX_BYTE_1) - '0';
+	}
+
+	return (0);
+
+fail3:
+	rc = EIO;
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+sfx7101_pma_pmd_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	uint16_t major;
+	uint16_t minor;
+	uint16_t micro;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_LINK_UP,
+	    (EFX_WORD_FIELD(word, PMA_PMD_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_RX_FAULT) != 0) ? 1 : 0);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = sfx7101_rev_get(enp, &major, &minor, &micro)) != 0)
+		goto fail3;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_MAJOR, major);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_MINOR, minor);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_MICRO, micro);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_CHANNELA_SNR_REG, &word)) != 0)
+		goto fail4;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_A,
+	    EFX_WORD_FIELD(word, PMA_PMD_SNR));
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_CHANNELB_SNR_REG, &word)) != 0)
+		goto fail5;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_B,
+	    EFX_WORD_FIELD(word, PMA_PMD_SNR));
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_CHANNELC_SNR_REG, &word)) != 0)
+		goto fail6;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_C,
+	    EFX_WORD_FIELD(word, PMA_PMD_SNR));
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_CHANNELD_SNR_REG, &word)) != 0)
+		goto fail7;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_D,
+	    EFX_WORD_FIELD(word, PMA_PMD_SNR));
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+sfx7101_pcs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PCS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_RX_FAULT) != 0) ? 1 : 0);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_10GBASE_R_STATUS2_REG, &word)) != 0)
+		goto fail3;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BER,
+	    EFX_WORD_FIELD(word, PCS_BER));
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BLOCK_ERRORS,
+	    EFX_WORD_FIELD(word, PCS_ERR));
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+sfx7101_phy_xs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PHY_XS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_RX_FAULT) != 0) ? 1 : 0);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail3;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_ALIGN,
+	    (EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) ? 1 : 0);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_A,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) ? 1 : 0);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_B,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) ? 1 : 0);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_C,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) ? 1 : 0);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_D,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0) ? 1 : 0);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+sfx7101_an_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_LINK_UP,
+	    (EFX_WORD_FIELD(word, AN_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
+	    AN_10G_BASE_T_STATUS_REG, &word)) != 0)
+		goto fail2;
+
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_MASTER,
+	    (EFX_WORD_FIELD(word, AN_MASTER) != 0) ? 1 : 0);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_LOCAL_RX_OK,
+	    (EFX_WORD_FIELD(word, AN_LOCAL_RX_OK) != 0) ? 1 : 0);
+	SFX7101_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_REMOTE_RX_OK,
+	    (EFX_WORD_FIELD(word, AN_REMOTE_RX_OK) != 0) ? 1 : 0);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+sfx7101_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint64_t mask = 0;
+	uint32_t oui;
+	int rc;
+
+	_NOTE(ARGUNUSED(esmp))
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, &oui)) != 0)
+		goto fail1;
+
+	SFX7101_STAT_SET(stat, mask, EFX_PHY_STAT_OUI, oui);
+
+	if ((rc = sfx7101_pma_pmd_stats_update(enp, &mask, stat)) != 0)
+		goto fail2;
+
+	if ((rc = sfx7101_pcs_stats_update(enp, &mask, stat)) != 0)
+		goto fail3;
+
+	if ((rc = sfx7101_phy_xs_stats_update(enp, &mask, stat)) != 0)
+		goto fail4;
+
+	if ((rc = sfx7101_an_stats_update(enp, &mask, stat)) != 0)
+		goto fail5;
+
+	/* Ensure all the supported statistics are up to date */
+	EFSYS_ASSERT(mask == encp->enc_phy_stat_mask);
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+		const char __cs *
+sfx7101_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	_NOTE(ARGUNUSED(enp, id))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (NULL);
+}
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn	int
+sfx7101_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp)
+{
+	_NOTE(ARGUNUSED(enp, id, flags, valp))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+
+	__checkReturn	int
+sfx7101_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val)
+{
+	_NOTE(ARGUNUSED(enp, id, val))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#if EFSYS_OPT_NVRAM_SFX7101
+
+static	__checkReturn		int
+sfx7101_loader_wait(
+	__in			efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int count;
+	unsigned int response;
+	int rc;
+
+	/* Wait up to 20s for the command to complete */
+	for (count = 0; count < 200; count++) {
+		EFSYS_SLEEP(100000);	/* 100ms */
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_CMD_RESPONSE_REG, &word)) != 0)
+			goto fail1;
+
+		response = EFX_WORD_FIELD(word, EFX_WORD_0);
+		if (response == LOADER_RESPONSE_OK)
+			return (0);
+		if (response != LOADER_RESPONSE_BUSY) {
+			rc = EIO;
+			goto fail2;
+		}
+	}
+
+	rc = ETIMEDOUT;
+
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+sfx7101_program_loader(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__in			size_t words)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* Setup address of block transfer */
+	EFX_POPULATE_WORD_1(word, EFX_WORD_0, offset);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+	    LOADER_FLASH_ADDR_LOW_REG, &word)) != 0)
+		goto fail1;
+
+	EFX_POPULATE_WORD_1(word, EFX_WORD_0, (offset >> 16));
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+	    LOADER_FLASH_ADDR_HI_REG, &word)) != 0)
+		goto fail2;
+
+	EFX_POPULATE_WORD_1(word, EFX_WORD_0, words);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+	    LOADER_ACTUAL_BUFF_SZ_REG, &word)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+__checkReturn		int
+sfx7101_nvram_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT(sizep);
+
+	*sizep = FIRMWARE_MAX_SIZE;
+
+	return (0);
+}
+
+	__checkReturn		int
+sfx7101_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4])
+{
+	uint16_t major, minor, micro;
+	int rc;
+
+	if ((rc = sfx7101_rev_get(enp, &major, &minor, &micro)) != 0)
+		goto fail1;
+
+	version[0] = major;
+	version[1] = minor;
+	version[2] = 0;
+	version[3] = 0;
+
+	*subtypep = PHY_TYPE_SFX7101_DECODE;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (0);
+}
+
+	__checkReturn		int
+sfx7101_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__out			size_t *block_sizep)
+{
+	efx_port_t *epp = &(enp->en_port);
+	sfx7101_firmware_header_t header;
+	efx_word_t word;
+	unsigned int pos;
+	int rc;
+
+	/* Ensure the PHY is on */
+	if ((rc = sfx7101_power_on(enp, B_TRUE)) != 0)
+		goto fail1;
+
+	/* Special software reset */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+		    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail2;
+	EFX_SET_WORD_FIELD(word, SSR, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+		    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail3;
+
+	/* Sleep for 500ms */
+	EFSYS_SLEEP(500000);
+
+	/* Check that the C166 is idle, and in download mode */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail4;
+	if (EFX_WORD_FIELD(word, BOOT_STATUS) == 0 ||
+	    EFX_WORD_FIELD(word, BOOT_PROGRESS) != MDIO_WAIT_DECODE) {
+		rc = ETIMEDOUT;
+		goto fail5;
+	}
+
+	/* Download loader code into PHY RAM */
+	EFX_ZERO_WORD(word);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+		    PCS_LM_RAM_LS_ADDR_REG, &word)) != 0)
+		goto fail6;
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+		    PCS_LM_RAM_MS_ADDR_REG, &word)) != 0)
+		goto fail7;
+
+	for (pos = 0; pos < sfx7101_loader_size / sizeof (uint16_t); pos++) {
+		/* Firmware is little endian */
+		word.ew_u8[0] = sfx7101_loader[pos];
+		word.ew_u8[1] = sfx7101_loader[pos+1];
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+			    PCS_LM_RAM_DATA_REG, &word)) != 0)
+			goto fail8;
+	}
+
+	/* Sleep for 500ms */
+	EFSYS_SLEEP(500000);
+
+	/* Start downloaded code */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail9;
+	EFX_SET_WORD_FIELD(word, CODE_DOWNLOAD, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
+		    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail10;
+
+	/* Sleep 1s */
+	EFSYS_SLEEP(1000000);
+
+	/* And check it started */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail11;
+
+	if (!EFX_WORD_FIELD(word, CODE_STARTED)) {
+		rc = ETIMEDOUT;
+		goto fail12;
+	}
+
+	/* Verify program block size is appropriate */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_MAX_BUFF_SZ_REG, &word)) != 0)
+		goto fail13;
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) < FIRMWARE_BLOCK_SIZE) {
+		rc = EIO;
+		goto fail14;
+	}
+	if (block_sizep != NULL)
+		*block_sizep = FIRMWARE_BLOCK_SIZE;
+
+	/* Read firmware header */
+	if ((rc = sfx7101_nvram_read_chunk(enp, 0, (void *)&header,
+	    sizeof (header))) != 0)
+		goto fail15;
+
+	/* Verify firmware isn't too large */
+	if (EFX_DWORD_FIELD(header.code_length, EFX_DWORD_0) +
+	    sizeof (sfx7101_firmware_header_t) > FIRMWARE_MAX_SIZE) {
+		rc = EIO;
+		goto fail16;
+	}
+
+	return (0);
+
+fail16:
+	EFSYS_PROBE(fail16);
+fail15:
+	EFSYS_PROBE(fail15);
+fail14:
+	EFSYS_PROBE(fail14);
+fail13:
+	EFSYS_PROBE(fail13);
+fail12:
+	EFSYS_PROBE(fail12);
+fail11:
+	EFSYS_PROBE(fail11);
+fail10:
+	EFSYS_PROBE(fail10);
+fail9:
+	EFSYS_PROBE(fail9);
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	/* Restore the original image */
+	sfx7101_nvram_rw_finish(enp);
+
+	return (rc);
+}
+
+	__checkReturn		int
+sfx7101_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int pos;
+	size_t chunk;
+	size_t words;
+	int rc;
+
+	while (size > 0) {
+		chunk = MIN(size, FIRMWARE_BLOCK_SIZE);
+
+		/* Read in 2byte words */
+		EFSYS_ASSERT(!(chunk & 0x1));
+		words = chunk >> 1;
+
+		/* Program address/length */
+		if ((rc = sfx7101_program_loader(enp, offset, words)) != 0)
+			goto fail1;
+
+		/* Select read mode, and wait for buffer to fill */
+		EFX_POPULATE_WORD_1(word, EFX_WORD_0, LOADER_CMD_READ_FLASH);
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_CMD_RESPONSE_REG, &word)) != 0)
+			goto fail2;
+
+		if ((rc = sfx7101_loader_wait(enp)) != 0)
+			goto fail3;
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_WORDS_READ_REG, &word)) != 0)
+			goto fail4;
+
+		if (words != (size_t)EFX_WORD_FIELD(word, EFX_WORD_0))
+			goto fail5;
+
+		for (pos = 0; pos < words; ++pos) {
+			if ((rc = falcon_mdio_read(enp, epp->ep_port,
+			    LOADER_MMD, LOADER_DATA_REG, &word)) != 0)
+				goto fail6;
+
+			/* Firmware is little endian */
+			data[pos] = word.ew_u8[0];
+			data[pos+1] = word.ew_u8[1];
+		}
+
+		offset += chunk;
+		data += chunk;
+		size -= chunk;
+	}
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn				int
+sfx7101_nvram_erase(
+	__in					efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	EFX_POPULATE_WORD_1(word, EFX_BYTE_0, LOADER_CMD_ERASE_FLASH);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port,
+	    LOADER_MMD, LOADER_CMD_RESPONSE_REG, &word)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn				int
+sfx7101_nvram_write_chunk(
+	__in					efx_nic_t *enp,
+	__in					unsigned int offset,
+	__in_bcount(size)			caddr_t data,
+	__in					size_t size)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int pos;
+	size_t chunk;
+	size_t words;
+	int rc;
+
+	while (size > 0) {
+		chunk = MIN(size, FIRMWARE_BLOCK_SIZE);
+
+		/* Write in 2byte words */
+		EFSYS_ASSERT(!(chunk & 0x1));
+		words = chunk >> 1;
+
+		/* Program address/length */
+		if ((rc = sfx7101_program_loader(enp, offset, words)) != 0)
+			goto fail1;
+
+		/* Select write mode */
+		EFX_POPULATE_WORD_1(word, EFX_WORD_0, LOADER_CMD_FILL_BUFFER);
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_CMD_RESPONSE_REG, &word)) != 0)
+			goto fail2;
+
+		for (pos = 0; pos < words; ++pos) {
+			/* Firmware is little-endian */
+			word.ew_u8[0] = data[pos];
+			word.ew_u8[1] = data[pos+1];
+
+			if ((rc = falcon_mdio_write(enp, epp->ep_port,
+			    LOADER_MMD, LOADER_DATA_REG, &word)) != 0)
+				goto fail3;
+		}
+
+		EFX_POPULATE_WORD_1(word, EFX_WORD_0,
+				    LOADER_CMD_PROGRAM_FLASH);
+		if ((rc = falcon_mdio_write(enp, epp->ep_port,
+		    LOADER_MMD, LOADER_CMD_RESPONSE_REG, &word)) != 0)
+			goto fail4;
+
+		if ((rc = sfx7101_loader_wait(enp)) != 0)
+			goto fail5;
+
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
+		    LOADER_WORDS_WRITTEN_REG, &word)) != 0)
+			goto fail6;
+
+		if (words != EFX_WORD_FIELD(word, EFX_WORD_0))
+			goto fail7;
+
+		size -= chunk;
+		offset += chunk;
+		data += chunk;
+	}
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+				void
+sfx7101_nvram_rw_finish(
+	__in			efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	efx_byte_t byte;
+	int rc;
+
+	EFX_SET_BYTE(byte);
+	EFX_SET_BYTE_FIELD(byte, P0_EN_1V2, 0);
+	EFX_SET_BYTE_FIELD(byte, P0_EN_2V5, 0);
+	EFX_SET_BYTE_FIELD(byte, P0_EN_5V, 0);
+	EFX_SET_BYTE_FIELD(byte, P0_X_TRST, 0);
+	EFX_SET_BYTE_FIELD(byte, P0_FLASH_CFG_EN, 0);
+
+	if ((rc = falcon_i2c_write(enp, PCA9539, P0_OUT,
+		    (caddr_t)&byte, 1)) != 0)
+		goto fail1;
+
+	/* Special software reset */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+			    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail2;
+	EFX_SET_WORD_FIELD(word, SSR, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+			    PMA_PMD_XCONTROL_REG, &word)) != 0)
+		goto fail3;
+
+	/* Sleep 1/2 second */
+	EFSYS_SLEEP(500000);
+
+	/* Verify that PHY rebooted */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+			    PCS_BOOT_STATUS_REG, &word)) != 0)
+		goto fail4;
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0x7E)
+		goto fail5;
+
+	return;
+
+fail5:
+	EFSYS_PROBE(fail4);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+}
+
+#endif	/* EFSYS_OPT_NVRAM_SFX7101 */
+
+#endif	/* EFSYS_OPT_PHY_SFX7101 */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfx7101.h	2013-08-22 18:57:32.831706606 -0400
@@ -0,0 +1,231 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_SFX7101_H
+#define	_SYS_SFX7101_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_SFX7101
+
+#define	SFX7101_LOOPBACK_MASK						\
+	    ((1 << EFX_LOOPBACK_PHY_XS) |				\
+	    (1 << EFX_LOOPBACK_PCS) |					\
+	    (1 << EFX_LOOPBACK_PMA_PMD) |				\
+	    FALCON_XMAC_LOOPBACK_MASK)
+
+#define	SFX7101_LED_MASK						\
+	    ((1 << EFX_PHY_LED_OFF) |					\
+	    (1 << EFX_PHY_LED_ON) |					\
+	    (1 << EFX_PHY_LED_FLASH))
+
+#define	SFX7101_NPROPS		0
+
+#define	SFX7101_ADV_CAP_MASK						\
+	    ((1 << EFX_PHY_CAP_AN) |					\
+	    (1 << EFX_PHY_CAP_10000FDX) |				\
+	    (1 << EFX_PHY_CAP_ASYM) |					\
+	    (1 << EFX_PHY_CAP_PAUSE))
+
+#define	SFX7101_ADV_CAP_PERM	0
+
+#define	SFX7101_BIST_MASK	0
+
+extern	__checkReturn	int
+sfx7101_power(
+	__in		efx_nic_t *enp,
+	__in		boolean_t on);
+
+extern	__checkReturn	int
+sfx7101_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+sfx7101_reconfigure(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+sfx7101_verify(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+sfx7101_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp);
+
+extern		void
+sfx7101_uplink_reset(
+	__in	efx_nic_t *enp);
+
+extern	__checkReturn	int
+sfx7101_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp);
+
+extern	__checkReturn	int
+sfx7101_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip);
+
+#if EFSYS_OPT_PHY_STATS
+
+/* START MKCONFIG GENERATED Sfx7101PhyHeaderStatsMask edaf3cd6dfd8b815 */
+#define	SFX7101_STAT_MASK \
+	(1ULL << EFX_PHY_STAT_OUI) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_REV_MAJOR) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_REV_MINOR) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_REV_MICRO) | \
+	(1ULL << EFX_PHY_STAT_PCS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PCS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_BER) | \
+	(1ULL << EFX_PHY_STAT_PCS_BLOCK_ERRORS) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_ALIGN) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_A) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_B) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_C) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_D) | \
+	(1ULL << EFX_PHY_STAT_AN_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_AN_MASTER) | \
+	(1ULL << EFX_PHY_STAT_AN_LOCAL_RX_OK) | \
+	(1ULL << EFX_PHY_STAT_AN_REMOTE_RX_OK) | \
+	(1ULL << EFX_PHY_STAT_SNR_A) | \
+	(1ULL << EFX_PHY_STAT_SNR_B) | \
+	(1ULL << EFX_PHY_STAT_SNR_C) | \
+	(1ULL << EFX_PHY_STAT_SNR_D)
+
+/* END MKCONFIG GENERATED Sfx7101PhyHeaderStatsMask */
+
+extern	__checkReturn			int
+sfx7101_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat);
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+sfx7101_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id);
+
+#endif
+
+extern	__checkReturn	int
+sfx7101_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp);
+
+extern	__checkReturn	int
+sfx7101_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val);
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#if EFSYS_OPT_NVRAM_SFX7101
+
+extern	__checkReturn		int
+sfx7101_nvram_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep);
+
+extern	__checkReturn		int
+sfx7101_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4]);
+
+extern	__checkReturn		int
+sfx7101_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__out			size_t *block_sizep);
+
+extern	__checkReturn		int
+sfx7101_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+sfx7101_nvram_erase(
+	__in			efx_nic_t *enp);
+
+extern	__checkReturn		int
+sfx7101_nvram_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern				void
+sfx7101_nvram_rw_finish(
+	__in			efx_nic_t *enp);
+
+extern const uint8_t * const sfx7101_loader;
+extern const size_t sfx7101_loader_size;
+
+#pragma pack(1)
+
+typedef struct sfx7001_firmware_header_s {
+	efx_dword_t code_length;
+	efx_dword_t destination_address;
+	efx_word_t code_checksum;
+	efx_word_t boot_config;
+	efx_word_t header_csum;
+	efx_byte_t reserved[18];
+} sfx7101_firmware_header_t;
+
+#pragma pack()
+
+#endif	/* EFSYS_OPT_NVRAM_SFX7101 */
+
+#endif	/* EFSYS_OPT_PHY_SFX7101 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_SFX7101_H */
--- /dev/null	2013-08-22 18:57:32.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfx7101_impl.h	2013-08-22 18:57:32.918058881 -0400
@@ -0,0 +1,203 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_SFX7101_IMPL_H
+#define	_SYS_SFX7101_IMPL_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_SFX7101
+
+#define	SFX7101_MMD_MASK						\
+	    ((1 << PMA_PMD_MMD) |					\
+	    (1 << PCS_MMD) |						\
+	    (1 << PHY_XS_MMD) |						\
+	    (1 << AN_MMD))
+
+/* IO expender */
+#define	PCA9539 0x74
+
+#define	P0_IN 0x00
+#define	P0_OUT 0x02
+#define	P0_INVERT 0x04
+#define	P0_CONFIG 0x06
+
+#define	P0_EN_1V0X_LBN 0
+#define	P0_EN_1V0X_WIDTH 1
+#define	P0_EN_1V2_LBN 1
+#define	P0_EN_1V2_WIDTH 1
+#define	P0_EN_2V5_LBN 2
+#define	P0_EN_2V5_WIDTH 1
+#define	P0_FLASH_CFG_EN_LBN 3
+#define	P0_FLASH_CFG_EN_WIDTH 1
+#define	P0_EN_5V_LBN 4
+#define	P0_EN_5V_WIDTH 1
+#define	P0_SHORTEN_JTAG_LBN 5
+#define	P0_SHORTEN_JTAG_WIDTH 1
+#define	P0_X_TRST_LBN 6
+#define	P0_X_TRST_WIDTH 1
+#define	P0_DSP_RESET_LBN 7
+#define	P0_DSP_RESET_WIDTH 1
+
+#define	P1_IN 0x01
+#define	P1_OUT 0x03
+#define	P1_INVERT 0x05
+#define	P1_CONFIG 0x07
+
+#define	P1_AFE_PWD_LBN 0
+#define	P1_AFE_PWD_WIDTH 1
+#define	P1_DSP_PWD25_LBN 1
+#define	P1_DSP_PWD25_WIDTH 1
+#define	P1_RESERVED_LBN 2
+#define	P1_RESERVED_WIDTH 2
+#define	P1_SPARE_LBN 4
+#define	P1_SPARE_WIDTH 4
+
+#define	PMA_PMD_XCONTROL_REG 0xc000
+#define	SSR_LBN 15
+#define	SSR_WIDTH 1
+#define	LNPGA_POWERDOWN_LBN 8
+#define	LNPGA_POWERDOWN_WIDTH 1
+#define	AFE_POWERDOWN_LBN 9
+#define	AFE_POWERDOWN_WIDTH 1
+#define	DSP_POWERDOWN_LBN 10
+#define	DSP_POWERDOWN_WIDTH 1
+#define	PHY_POWERDOWN_LBN 11
+#define	PHY_POWERDOWN_WIDTH 1
+
+#define	PMA_PMD_XSTATUS_REG 0xc001
+#define	FLP_RCVD_LBN 12
+#define	FLP_RCVD_WIDTH 1
+
+#define	PMA_PMD_LED_CONTROL_REG 0xc007
+#define	LED_ACTIVITY_EN_LBN 3
+#define	LED_ACTIVITY_EN_WIDTH 1
+#define	LED_FLASH_PERIOD_LBN 0
+#define	LED_FLASH_PERIOD_WIDTH 3
+
+#define	PMA_PMD_LED_OVERRIDE_REG 0xc009
+#define	LED_LINK_LBN 0 /* Green */
+#define	LED_LINK_WIDTH 2
+#define	LED_TX_LBN 4 /* Amber */
+#define	LED_TX_WIDTH 2
+#define	LED_RX_LBN 6 /* Red */
+#define	LED_RX_WIDTH 2
+#define	LED_NORMAL_DECODE 0x0
+#define	LED_ON_DECODE 0x1
+#define	LED_OFF_DECODE 0x2
+#define	LED_FLASH_DECODE 0x3
+
+#define	PMA_PMD_FW_REV0_REG 0xc026
+#define	PMA_PMD_FW_REV1_REG 0xc027
+
+#define	PCS_BOOT_STATUS_REG 0xd000	/* PRM 10.4.1 */
+#define	RESET_CAUSE_LBN 8
+#define	RESET_CAUSE_WIDTH 2
+#define	HW_RESET_DECODE 0x0
+#define	SW_RESET_DECODE 0x1
+#define	WD_RESET_DECODE 0x2
+#define	SW_WD_RESET_DECODE 0x3
+#define	UPLOAD_PROGRESS_LBN 7
+#define	UPLOAD_PROGRESS_WIDTH 1
+#define	CODE_DOWNLOAD_LBN 6
+#define	CODE_DOWNLOAD_WIDTH 1
+#define	CKSUM_OK_LBN 5
+#define	CKSUM_OK_WIDTH 1
+#define	CODE_STARTED_LBN 4
+#define	CODE_STARTED_WIDTH 1
+#define	BOOT_STATUS_LBN 3
+#define	BOOT_STATUS_WIDTH 1
+#define	BOOT_PROGRESS_LBN 1
+#define	BOOT_PROGRESS_WIDTH 2
+#define	INIT_DECODE 0x0
+#define	MDIO_WAIT_DECODE 0x1
+#define	CKSUM_START_DECODE 0x2
+#define	APP_JMP_DECODE 0x3
+#define	FATAL_ERR_LBN 0
+#define	FATAL_ERR_WIDTH 1
+
+#define	PCS_LM_RAM_LS_ADDR_REG 0xd004
+#define	LM_RAM_LS_ADDR_LBN 0
+#define	LM_RAM_LS_ADDR_WIDTH 16
+
+#define	PCS_LM_RAM_MS_ADDR_REG 0xd005
+#define	LM_RAM_MS_ADDR_LBN 0
+#define	LM_RAM_MS_ADDR_WIDTH 3
+#define	BYTE_ACCESS_LBN 15
+#define	BYTE_ACCESS_WIDTH 1
+
+#define	PCS_LM_RAM_DATA_REG 0xd006
+#define	LM_RAM_DATA_LBN 0
+#define	LM_RAM_DATA_WIDTH 16
+
+#define	PCS_TEST_SELECT_REG 0xd807	/* PRM 10.5.8 */
+#define	CLK312_EN_LBN 3
+#define	CLK312_EN_WIDTH 1
+
+#define	PCS_CLOCK_CTRL_REG 0xd801
+#define	PLL312_RST_N_LBN 2
+#define	PLL312_RST_N_WIDTH 1
+
+#define	PCS_SOFT_RST2_REG 0xd806
+#define	SERDES_RST_N_LBN 13
+#define	SERDES_RST_N_WIDTH 1
+#define	XGXS_RST_N_LBN 12
+#define	XGXS_RST_N_WIDTH 1
+
+#define	PHY_XS_XGXS_TEST_REG 0xc00a
+#define	SERDES_LOOPBACK_LBN 9
+#define	SERDES_LOOPBACK_WIDTH 1
+#define	NE_LOOPBACK_LBN 8
+#define	NE_LOOPBACK_WIDTH 1
+
+#define	LOADER_MMD 1
+#define	LOADER_MAX_BUFF_SZ_REG 49192
+#define	LOADER_ACTUAL_BUFF_SZ_REG 49193
+#define	LOADER_CMD_RESPONSE_REG 49194
+#define	LOADER_CMD_ERASE_FLASH 0x0001
+#define	LOADER_CMD_FILL_BUFFER 0x0002
+#define	LOADER_CMD_PROGRAM_FLASH 0x0003
+#define	LOADER_CMD_READ_FLASH 0x0004
+#define	LOADER_RESPONSE_OK 0x0100
+#define	LOADER_RESPONSE_ERROR 0x0200
+#define	LOADER_RESPONSE_BUSY 0x0300
+#define	LOADER_WORDS_WRITTEN_REG 49195
+#define	LOADER_WORDS_READ_REG 49195
+#define	LOADER_FLASH_ADDR_LOW_REG 49196
+#define	LOADER_FLASH_ADDR_HI_REG  49197
+#define	LOADER_DATA_REG 49198
+
+#define	FIRMWARE_BLOCK_SIZE 0x4000
+#define	FIRMWARE_MAX_SIZE 0x30000
+
+#endif	/* EFSYS_OPT_PHY_SFX7101 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_SFX7101_IMPL_H */
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge.c	2013-08-22 18:57:33.004689749 -0400
@@ -0,0 +1,1462 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/modctl.h>
+#include <sys/conf.h>
+#include <sys/ethernet.h>
+#include <sys/pci.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/processor.h>
+#include <sys/cpuvar.h>
+#include <sys/pghw.h>
+
+#include "version.h"
+
+#include "sfxge.h"
+#include "efsys.h"
+#include "efx.h"
+
+#ifdef	DEBUG
+boolean_t sfxge_aask = B_FALSE;
+#endif
+
+/* Receive queue TRIM default polling interval (in microseconds) */
+#define	SFXGE_RX_QPOLL_USEC	(5000000)
+
+/* Broadcast address */
+uint8_t	sfxge_brdcst[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/* Soft state head */
+static void	*sfxge_ss;
+
+/*
+ * By default modinfo will display lines truncated to 80 characters and so just
+ * show 32 characters of our sfxge_ident string. At the moment CI_VERSION_STRING
+ * is 12 characters. To show the whole string use modinfo -w
+ */
+#if defined(_USE_GLD_V3_SOL10) && !defined(_USE_GLD_V3_SOL11)
+#ifdef DEBUG
+/*
+ * The (DEBUG) part of this string will not be displayed in modinfo by
+ * default. See previous comment.
+ */
+const char sfxge_ident[] =
+    CI_VERSION_STRING" for Sol10u8,u9,u10 (DEBUG)";
+#else
+const char sfxge_ident[] =
+    CI_VERSION_STRING" for Sol10u8,u9,u10";
+#endif
+#elif defined(_USE_GLD_V3_SOL11)
+#ifdef DEBUG
+const char sfxge_ident[] = CI_VERSION_STRING" for Sol11 (DEBUG)";
+#else
+const char sfxge_ident[] = CI_VERSION_STRING" for Sol11";
+#endif
+#elif defined(_USE_GLD_V3)
+#ifdef DEBUG
+const char sfxge_ident[] = CI_VERSION_STRING" GLDv3 (DEBUG)";
+#else
+const char sfxge_ident[] = CI_VERSION_STRING" GLDv3";
+#endif
+#elif defined(_USE_GLD_V2)
+#ifdef DEBUG
+const char sfxge_ident[] = CI_VERSION_STRING" GLDv2 (DEBUG)";
+#else
+const char sfxge_ident[] = CI_VERSION_STRING" GLDv2";
+#endif
+#else
+#error "sfxge_ident undefined"
+#endif
+const char sfxge_version[] = CI_VERSION_STRING;
+
+static void
+sfxge_cfg_build(sfxge_t *sp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sp->s_enp);
+	(void) snprintf(sp->s_cfg_kstat.buf.sck_mac, 64,
+			"%02X:%02X:%02X:%02X:%02X:%02X",
+			encp->enc_mac_addr[0], encp->enc_mac_addr[1],
+			encp->enc_mac_addr[2], encp->enc_mac_addr[3],
+			encp->enc_mac_addr[4], encp->enc_mac_addr[5]);
+}
+
+static int
+sfxge_create(dev_info_t *dip, sfxge_t **spp)
+{
+	int instance = ddi_get_instance(dip);
+	sfxge_t *sp;
+	efx_nic_t *enp;
+	char name[MAXNAMELEN];
+	unsigned int rxq_size;
+	int rxq_poll_usec;
+	int rc;
+
+	/* Allocate the soft state object */
+	if (ddi_soft_state_zalloc(sfxge_ss, instance) != DDI_SUCCESS) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	sp = ddi_get_soft_state(sfxge_ss, instance);
+	ASSERT(sp != NULL);
+
+	SFXGE_OBJ_CHECK(sp, sfxge_t);
+
+	sp->s_dip = dip;
+
+	mutex_init(&(sp->s_state_lock), "", MUTEX_DRIVER, NULL);
+	sp->s_state = SFXGE_UNINITIALIZED;
+
+	/* Get property values */
+	sp->s_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "mtu", ETHERMTU);
+
+	sp->s_action_on_hw_err = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "action_on_hw_err", SFXGE_RECOVER);
+
+	rxq_size = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "rxq_size", SFXGE_DEFAULT_RXQ_SIZE);
+	if (!(IS_POW2(rxq_size)))
+		rxq_size = SFXGE_DEFAULT_RXQ_SIZE;
+	rxq_size = min(rxq_size, EFX_RXQ_MAXNDESCS);
+	sp->s_rxq_size = max(rxq_size, EFX_RXQ_MINNDESCS);
+
+	/* Configure polling interval for queue refill/trim */
+	rxq_poll_usec = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+		DDI_PROP_DONTPASS, "rxq_poll_usec", SFXGE_RX_QPOLL_USEC);
+	if (rxq_poll_usec <= 0)
+		rxq_poll_usec = SFXGE_RX_QPOLL_USEC;
+	sp->s_rxq_poll_usec = rxq_poll_usec;
+
+	/* Create a taskq */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_tq", ddi_driver_name(dip));
+	sp->s_tqp = ddi_taskq_create(dip, name, 1, TASKQ_DEFAULTPRI, DDI_SLEEP);
+	if (sp->s_tqp == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	/* Check and initialize PCI configuration space */
+	if ((rc = sfxge_pci_init(sp)) != 0)
+		goto fail3;
+
+	/* Map the device registers */
+	if ((rc = sfxge_bar_init(sp)) != 0)
+		goto fail4;
+
+	/* Create the NIC object */
+	mutex_init(&(sp->s_nic_lock), NULL, MUTEX_DRIVER, NULL);
+
+	if ((rc = efx_nic_create(sp->s_family, (efsys_identifier_t *)sp,
+	    &(sp->s_bar), &(sp->s_nic_lock), &enp)) != 0)
+		goto fail5;
+
+	sp->s_enp = enp;
+
+	/* Initialize MCDI to talk to the Microcontroller */
+	if ((rc = sfxge_mcdi_init(sp)) != 0)
+		goto fail6;
+
+	/* Probe the NIC and build the configuration data area */
+	if ((rc = efx_nic_probe(enp)) != 0)
+		goto fail7;
+
+	if (sp->s_family == EFX_FAMILY_SIENA) {
+		sfxge_pcie_check_link(sp, 8, 2); /* PCI 8x Gen2 */
+
+	} else if (sp->s_family == EFX_FAMILY_FALCON) {
+		sfxge_pcie_check_link(sp, 8, 1); /* PCI 8x Gen1 */
+
+		rc = efx_nic_pcie_tune(enp, sp->s_pcie_nlanes);
+		ASSERT(rc == 0);
+	}
+
+	if ((rc = efx_nvram_init(enp)) != 0)
+		goto fail8;
+
+	if ((rc = efx_vpd_init(enp)) != 0)
+		goto fail9;
+
+	if ((rc = efx_nic_reset(enp)) != 0)
+		goto fail10;
+
+	sfxge_sram_init(sp);
+
+	if ((rc = sfxge_intr_init(sp)) != 0)
+		goto fail11;
+
+	if ((rc = sfxge_ev_init(sp)) != 0)
+		goto fail12;
+
+	if ((rc = sfxge_rx_init(sp)) != 0)
+		goto fail13;
+
+	if ((rc = sfxge_tx_init(sp)) != 0)
+		goto fail14;
+
+	if ((rc = sfxge_mon_init(sp)) != 0)
+		goto fail15;
+
+	if ((rc = sfxge_mac_init(sp)) != 0)
+		goto fail16;
+
+	mutex_init(&(sp->s_tx_flush_lock), "", MUTEX_DRIVER,
+	    DDI_INTR_PRI(sp->s_intr.si_intr_pri));
+	cv_init(&(sp->s_tx_flush_kv), "", CV_DRIVER, NULL);
+
+	sp->s_state = SFXGE_INITIALIZED;
+
+	*spp = sp;
+	return (0);
+
+fail16:
+	DTRACE_PROBE(fail16);
+	sfxge_mon_fini(sp);
+
+fail15:
+	DTRACE_PROBE(fail15);
+	sfxge_tx_fini(sp);
+
+fail14:
+	DTRACE_PROBE(fail14);
+	sfxge_rx_fini(sp);
+
+fail13:
+	DTRACE_PROBE(fail13);
+	sfxge_ev_fini(sp);
+
+fail12:
+	DTRACE_PROBE(fail12);
+	sfxge_intr_fini(sp);
+
+fail11:
+	DTRACE_PROBE(fail11);
+	sfxge_sram_fini(sp);
+	(void) efx_nic_reset(sp->s_enp);
+
+fail10:
+	DTRACE_PROBE(fail10);
+	efx_vpd_fini(enp);
+
+fail9:
+	DTRACE_PROBE(fail9);
+	efx_nvram_fini(enp);
+
+fail8:
+	DTRACE_PROBE(fail8);
+	efx_nic_unprobe(enp);
+
+fail7:
+	DTRACE_PROBE(fail7);
+	sfxge_mcdi_fini(sp);
+
+fail6:
+	DTRACE_PROBE(fail6);
+	sp->s_enp = NULL;
+	efx_nic_destroy(enp);
+
+fail5:
+	DTRACE_PROBE(fail5);
+	mutex_destroy(&(sp->s_nic_lock));
+	sfxge_bar_fini(sp);
+
+fail4:
+	DTRACE_PROBE(fail4);
+	sfxge_pci_fini(sp);
+
+fail3:
+	DTRACE_PROBE(fail3);
+	ddi_taskq_destroy(sp->s_tqp);
+	sp->s_tqp = NULL;
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Clear property values */
+	sp->s_mtu = 0;
+
+	mutex_destroy(&(sp->s_state_lock));
+
+	/* Free the soft state */
+	sp->s_dip = NULL;
+
+	SFXGE_OBJ_CHECK(sp, sfxge_t);
+	ddi_soft_state_free(sfxge_ss, instance);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+static int
+sfxge_start_locked(sfxge_t *sp, boolean_t restart)
+{
+	int rc;
+
+	ASSERT(mutex_owned(&(sp->s_state_lock)));
+
+	if (sp->s_state == SFXGE_STARTED)
+		goto done;
+
+	if (sp->s_state != SFXGE_REGISTERED) {
+		rc = EINVAL;
+		goto fail1;
+	}
+	sp->s_state = SFXGE_STARTING;
+
+	if ((rc = efx_nic_reset(sp->s_enp)) != 0)
+		goto fail2;
+
+	if ((rc = efx_nic_init(sp->s_enp)) != 0)
+		goto fail3;
+
+	if ((rc = sfxge_sram_start(sp)) != 0)
+		goto fail4;
+
+	if ((rc = sfxge_intr_start(sp)) != 0)
+		goto fail5;
+
+	if ((rc = sfxge_ev_start(sp)) != 0)
+		goto fail6;
+
+	if ((rc = sfxge_rx_start(sp)) != 0)
+		goto fail7;
+
+	if ((rc = sfxge_tx_start(sp)) != 0)
+		goto fail8;
+
+	if ((rc = sfxge_mon_start(sp)) != 0)
+		goto fail9;
+
+	if ((rc = sfxge_mac_start(sp, restart)) != 0)
+		goto fail10;
+
+	ASSERT3U(sp->s_state, ==, SFXGE_STARTING);
+	sp->s_state = SFXGE_STARTED;
+
+	/* Notify any change of MTU */
+	sfxge_gld_mtu_update(sp);
+
+done:
+	return (0);
+
+fail10:
+	DTRACE_PROBE(fail10);
+	sfxge_mon_stop(sp);
+
+fail9:
+	DTRACE_PROBE(fail9);
+	sfxge_tx_stop(sp);
+
+fail8:
+	DTRACE_PROBE(fail8);
+	sfxge_rx_stop(sp);
+
+fail7:
+	DTRACE_PROBE(fail7);
+	sfxge_ev_stop(sp);
+
+fail6:
+	DTRACE_PROBE(fail6);
+	sfxge_intr_stop(sp);
+
+fail5:
+	DTRACE_PROBE(fail5);
+	sfxge_sram_stop(sp);
+
+fail4:
+	DTRACE_PROBE(fail4);
+	efx_nic_fini(sp->s_enp);
+
+fail3:
+	DTRACE_PROBE(fail3);
+	(void) efx_nic_reset(sp->s_enp);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	ASSERT3U(sp->s_state, ==, SFXGE_STARTING);
+	sp->s_state = SFXGE_REGISTERED;
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+int
+sfxge_start(sfxge_t *sp, boolean_t restart)
+{
+	int rc;
+
+	mutex_enter(&(sp->s_state_lock));
+	rc = sfxge_start_locked(sp, restart);
+	mutex_exit(&(sp->s_state_lock));
+	return (rc);
+}
+
+
+static void
+sfxge_stop_locked(sfxge_t *sp)
+{
+	ASSERT(mutex_owned(&(sp->s_state_lock)));
+
+	if (sp->s_state != SFXGE_STARTED) {
+		return;
+	}
+	sp->s_state = SFXGE_STOPPING;
+
+	sfxge_mac_stop(sp);
+	sfxge_mon_stop(sp);
+	sfxge_tx_stop(sp);
+	sfxge_rx_stop(sp);
+
+	/* Stop event processing - must be after rx_stop see sfxge_rx_qpoll() */
+	sfxge_ev_stop(sp);
+	sfxge_intr_stop(sp); /* cope with late flush/soft events until here */
+	sfxge_sram_stop(sp);
+
+	efx_nic_fini(sp->s_enp);
+	efx_nic_reset(sp->s_enp);
+
+	ASSERT3U(sp->s_state, ==, SFXGE_STOPPING);
+	sp->s_state = SFXGE_REGISTERED;
+}
+
+void
+sfxge_stop(sfxge_t *sp)
+{
+	mutex_enter(&(sp->s_state_lock));
+	sfxge_stop_locked(sp);
+	mutex_exit(&(sp->s_state_lock));
+}
+
+static void
+_sfxge_restart(void *arg)
+{
+	sfxge_t *sp = arg;
+	int rc;
+
+	/* logging on entry is in sfxge_restart_dispatch */
+	mutex_enter(&(sp->s_state_lock));
+
+	DTRACE_PROBE(_sfxge_restart);
+	if (sp->s_state != SFXGE_STARTED)
+		goto done;
+
+	/* inform the OS that the link is down - may trigger IPMP failover */
+	if (sp->s_hw_err && sp->s_action_on_hw_err != SFXGE_INVISIBLE) {
+		sp->s_mac.sm_link_mode = EFX_LINK_DOWN;
+		sfxge_gld_link_update(sp);
+	}
+
+	/* Stop processing */
+	sfxge_stop_locked(sp);
+
+	if (sp->s_hw_err && sp->s_action_on_hw_err == SFXGE_LEAVE_DEAD) {
+		cmn_err(CE_WARN, SFXGE_CMN_ERR "[%s%d] NIC error - interface is"
+		    " being left permanently DOWN per driver config",
+		    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
+		mutex_exit(&(sp->s_state_lock));
+		return;
+	} else
+		sp->s_hw_err = SFXGE_HW_OK;
+
+	/* Start processing */
+	if ((rc = sfxge_start_locked(sp, B_TRUE)) != 0)
+		goto fail1;
+
+done:
+	mutex_exit(&(sp->s_state_lock));
+	cmn_err(CE_WARN, SFXGE_CMN_ERR "[%s%d] NIC restart complete",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
+	return;
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	cmn_err(CE_WARN,
+	    SFXGE_CMN_ERR "[%s%d] FATAL ERROR: NIC restart failed rc=%d",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip), rc);
+
+	mutex_exit(&(sp->s_state_lock));
+}
+
+int
+sfxge_restart_dispatch(sfxge_t *sp, uint_t cflags, sfxge_hw_err_t hw_err,
+    const char *reason, uint32_t errval)
+{
+	if (hw_err == SFXGE_HW_OK)
+		sp->s_num_restarts++;
+	else {
+		sp->s_hw_err = hw_err;
+		sp->s_num_restarts_hw_err++;
+	}
+
+	DTRACE_PROBE2(sfxge_restart_dispatch, sfxge_hw_err_t, hw_err, char *,
+	    reason);
+
+	cmn_err(CE_WARN, SFXGE_CMN_ERR "[%s%d] NIC restart due to %s:%d",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip), reason,
+	    errval);
+
+	/* If cflags == DDI_SLEEP then guaranteed to succeed */
+	return (ddi_taskq_dispatch(sp->s_tqp, _sfxge_restart, sp, cflags));
+}
+
+
+static int
+sfxge_can_destroy(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	int index;
+
+	/*
+	 * In SFC bug 19834 it was noted that a mblk passed up to STREAMS
+	 * could be reused for transmit and sit in the sfxge_tx_packet_cache.
+	 * This call to empty the TX deferred packet list may result in
+	 * rx_loaned reducing.
+	 */
+	index = sip->si_nalloc;
+	while (--index >= 0) {
+		sfxge_txq_t *stp = sp->s_stp[index];
+		sfxge_tx_qdpl_flush(stp);
+	}
+
+	/* Need to wait for desballoc free_func callback */
+	return (sfxge_rx_loaned(sp));
+}
+
+
+static int
+sfxge_destroy(sfxge_t *sp)
+{
+	dev_info_t *dip = sp->s_dip;
+	int instance = ddi_get_instance(dip);
+	ddi_taskq_t *tqp;
+	efx_nic_t *enp;
+	int rc;
+
+	ASSERT3U(sp->s_state, ==, SFXGE_INITIALIZED);
+	enp = sp->s_enp;
+
+	if (sfxge_can_destroy(sp) != 0) {
+		rc = EBUSY;
+		goto fail1;
+	}
+
+	sp->s_state = SFXGE_UNINITIALIZED;
+
+	cv_destroy(&(sp->s_tx_flush_kv));
+	mutex_destroy(&(sp->s_tx_flush_lock));
+
+	sfxge_mac_fini(sp);
+	sfxge_mon_fini(sp);
+	sfxge_tx_fini(sp);
+	sfxge_rx_fini(sp);
+	sfxge_ev_fini(sp);
+	sfxge_intr_fini(sp);
+	sfxge_sram_fini(sp);
+	(void) efx_nic_reset(enp);
+
+	efx_vpd_fini(enp);
+	efx_nvram_fini(enp);
+	efx_nic_unprobe(enp);
+	sfxge_mcdi_fini(sp);
+
+	/* Destroy the NIC object */
+	sp->s_enp = NULL;
+	efx_nic_destroy(enp);
+
+	mutex_destroy(&(sp->s_nic_lock));
+
+	/* Unmap the device registers */
+	sfxge_bar_fini(sp);
+
+	/* Tear down PCI configuration space */
+	sfxge_pci_fini(sp);
+
+	/* Destroy the taskq */
+	tqp = sp->s_tqp;
+	sp->s_tqp = NULL;
+	ddi_taskq_destroy(tqp);
+
+	mutex_destroy(&(sp->s_state_lock));
+
+	/* Clear property values */
+	sp->s_mtu = 0;
+
+	/* Free the soft state */
+	sp->s_dip = NULL;
+
+	SFXGE_OBJ_CHECK(sp, sfxge_t);
+	ddi_soft_state_free(sfxge_ss, instance);
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_ioctl(sfxge_t *sp, queue_t *wq, mblk_t *mp)
+{
+	struct iocblk *iocp;
+	int rc, taskq_wait = 0;
+	size_t ioclen = 0;
+
+	/*
+	 * single concurrent IOCTL
+	 * serialized from sfxge_create, _destroy, _(re)start, _stop
+	 */
+	mutex_enter(&(sp->s_state_lock));
+
+	/*LINTED*/
+	iocp = (struct iocblk *)mp->b_rptr;
+
+	switch (iocp->ioc_cmd) {
+	case SFXGE_TX_IOC:
+		ioclen = sizeof (sfxge_tx_ioc_t);
+		break;
+	case SFXGE_RX_IOC:
+		ioclen = sizeof (sfxge_rx_ioc_t);
+		break;
+	case SFXGE_BAR_IOC:
+		ioclen = sizeof (sfxge_bar_ioc_t);
+		break;
+	case SFXGE_PCI_IOC:
+		ioclen = sizeof (sfxge_pci_ioc_t);
+		break;
+	case SFXGE_MAC_IOC:
+		ioclen = sizeof (sfxge_mac_ioc_t);
+		break;
+	case SFXGE_PHY_IOC:
+		ioclen = sizeof (sfxge_phy_ioc_t);
+		break;
+	case SFXGE_PHY_BIST_IOC:
+		ioclen = sizeof (sfxge_phy_bist_ioc_t);
+		break;
+	case SFXGE_SRAM_IOC:
+		ioclen = sizeof (sfxge_sram_ioc_t);
+		break;
+	case SFXGE_NVRAM_IOC:
+		ioclen = sizeof (sfxge_nvram_ioc_t);
+		break;
+	case SFXGE_MCDI_IOC:
+		ioclen = sizeof (sfxge_mcdi_ioc_t);
+		break;
+	case SFXGE_VPD_IOC:
+		ioclen = sizeof (sfxge_vpd_ioc_t);
+		break;
+	case SFXGE_START_IOC:
+	case SFXGE_STOP_IOC:
+	case SFXGE_NIC_RESET_IOC:
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (iocp->ioc_count != ioclen) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	/* if in multiple fragments pull it up to one linear buffer */
+	if ((rc = miocpullup(mp, ioclen)) != 0) {
+		goto fail3;
+	}
+
+	switch (iocp->ioc_cmd) {
+	case SFXGE_START_IOC:
+		if ((rc = sfxge_start_locked(sp, B_TRUE)) != 0)
+			goto fail4;
+
+		break;
+
+	case SFXGE_STOP_IOC:
+		sfxge_stop_locked(sp);
+		break;
+
+	case SFXGE_TX_IOC: {
+		sfxge_tx_ioc_t *stip = (sfxge_tx_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_tx_ioctl(sp, stip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case SFXGE_RX_IOC: {
+		sfxge_rx_ioc_t *srip = (sfxge_rx_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_rx_ioctl(sp, srip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case SFXGE_BAR_IOC: {
+		sfxge_bar_ioc_t *sbip = (sfxge_bar_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_bar_ioctl(sp, sbip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case SFXGE_PCI_IOC: {
+		sfxge_pci_ioc_t *spip = (sfxge_pci_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_pci_ioctl(sp, spip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case SFXGE_MAC_IOC: {
+		sfxge_mac_ioc_t *smip = (sfxge_mac_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_mac_ioctl(sp, smip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case SFXGE_PHY_IOC: {
+		sfxge_phy_ioc_t *spip = (sfxge_phy_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_phy_ioctl(sp, spip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case SFXGE_PHY_BIST_IOC: {
+		sfxge_phy_bist_ioc_t *spbip;
+
+		spbip = (sfxge_phy_bist_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_phy_bist_ioctl(sp, spbip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case SFXGE_SRAM_IOC: {
+		sfxge_sram_ioc_t *ssip = (sfxge_sram_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_sram_ioctl(sp, ssip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case SFXGE_NVRAM_IOC: {
+		sfxge_nvram_ioc_t *snip =
+		    (sfxge_nvram_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_nvram_ioctl(sp, snip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	case SFXGE_MCDI_IOC: {
+		sfxge_mcdi_ioc_t *smip = (sfxge_mcdi_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_mcdi_ioctl(sp, smip)) != 0)
+			goto fail4;
+		taskq_wait = 1;
+
+		break;
+	}
+	case SFXGE_NIC_RESET_IOC: {
+		DTRACE_PROBE(nic_reset_ioc);
+
+		/* sp->s_state_lock held */
+		(void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_OK,
+		    "NIC_RESET_IOC", 0);
+		taskq_wait = 1;
+
+		break;
+	}
+	case SFXGE_VPD_IOC: {
+		sfxge_vpd_ioc_t *svip = (sfxge_vpd_ioc_t *)mp->b_cont->b_rptr;
+
+		if ((rc = sfxge_vpd_ioctl(sp, svip)) != 0)
+			goto fail4;
+
+		break;
+	}
+	default:
+		ASSERT(0);
+	}
+
+	mutex_exit(&(sp->s_state_lock));
+
+	if (taskq_wait) {
+		/*
+		 * Wait for any tasks that may be accessing GLD functions
+		 * This may end up waiting for multiple nic_resets
+		 * as it needs to be outside of s_state_lock for sfxge_restart()
+		 */
+		ddi_taskq_wait(sp->s_tqp);
+	}
+
+	/* The entire structure is the acknowledgement */
+	miocack(wq, mp, iocp->ioc_count, 0);
+
+	return;
+
+fail4:
+	DTRACE_PROBE(fail4);
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(sp->s_state_lock));
+
+	/* no data returned */
+	miocnak(wq, mp, 0, rc);
+}
+
+static int
+sfxge_register(sfxge_t *sp)
+{
+	int rc;
+
+	ASSERT3U(sp->s_state, ==, SFXGE_INITIALIZED);
+
+	if ((rc = sfxge_gld_register(sp)) != 0)
+		goto fail1;
+
+	sp->s_state = SFXGE_REGISTERED;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_unregister(sfxge_t *sp)
+{
+	int rc;
+
+	ASSERT3U(sp->s_state, ==, SFXGE_REGISTERED);
+
+	/* Wait for any tasks that may be accessing GLD functions */
+	ddi_taskq_wait(sp->s_tqp);
+
+	if ((rc = sfxge_gld_unregister(sp)) != 0)
+		goto fail1;
+
+	sp->s_state = SFXGE_INITIALIZED;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+_sfxge_vpd_kstat_init(sfxge_t *sp, caddr_t vpd, size_t size, efx_vpd_tag_t tag,
+	    const char *keyword, sfxge_vpd_type_t type)
+{
+	static const char unknown[] = "?";
+	efx_nic_t *enp = sp->s_enp;
+	sfxge_vpd_kstat_t *svkp = &(sp->s_vpd_kstat);
+	kstat_named_t *knp;
+	efx_vpd_value_t *evvp;
+
+	evvp = svkp->svk_vv + type;
+	evvp->evv_tag = tag;
+	evvp->evv_keyword = EFX_VPD_KEYWORD(keyword[0], keyword[1]);
+
+	if (efx_vpd_get(enp, vpd, size, evvp) != 0) {
+		evvp->evv_length = strlen(unknown) + 1;
+		memcpy(evvp->evv_value, unknown, evvp->evv_length);
+	}
+
+	knp = &(svkp->svk_stat[type]);
+
+	kstat_named_init(knp, (char *)keyword, KSTAT_DATA_STRING);
+	kstat_named_setstr(knp, (char *)evvp->evv_value);
+	svkp->svk_ksp->ks_data_size += sizeof (*evvp);
+}
+
+static int
+sfxge_vpd_kstat_init(sfxge_t *sp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	sfxge_vpd_kstat_t *svkp = &(sp->s_vpd_kstat);
+	dev_info_t *dip = sp->s_dip;
+	char name[MAXNAMELEN];
+	kstat_t *ksp;
+	caddr_t vpd;
+	size_t size;
+	int rc;
+
+	SFXGE_OBJ_CHECK(svkp, sfxge_vpd_kstat_t);
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_vpd", ddi_driver_name(dip));
+
+	/* Get a copy of the VPD space */
+	if ((rc = efx_vpd_size(enp, &size)) != 0)
+		goto fail1;
+
+	if ((vpd = kmem_zalloc(size, KM_NOSLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	if ((svkp->svk_vv = kmem_zalloc(sizeof (efx_vpd_value_t) *
+	    SFXGE_VPD_MAX, KM_NOSLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail3;
+	}
+
+	if ((rc = efx_vpd_read(enp, vpd, size)) != 0)
+		goto fail4;
+
+	if ((ksp = kstat_create((char *)ddi_driver_name(dip),
+	    ddi_get_instance(dip), name, "vpd", KSTAT_TYPE_NAMED, SFXGE_VPD_MAX,
+	    KSTAT_FLAG_VIRTUAL)) == NULL) {
+		rc = ENOMEM;
+		goto fail5;
+	}
+	svkp->svk_ksp = ksp;
+	ksp->ks_data = &(svkp->svk_stat);
+
+	_sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_ID, "ID", SFXGE_VPD_ID);
+	_sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "PN", SFXGE_VPD_PN);
+	_sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "SN", SFXGE_VPD_SN);
+	_sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "EC", SFXGE_VPD_EC);
+	_sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "VD", SFXGE_VPD_VD);
+
+	kstat_install(ksp);
+	kmem_free(vpd, size);
+
+	return (0);
+
+fail5:
+	DTRACE_PROBE(fail5);
+fail4:
+	DTRACE_PROBE(fail4);
+	kmem_free(svkp->svk_vv, sizeof (efx_vpd_value_t) * SFXGE_VPD_MAX);
+fail3:
+	DTRACE_PROBE(fail3);
+	kmem_free(vpd, size);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	SFXGE_OBJ_CHECK(svkp, sfxge_vpd_kstat_t);
+
+	return (rc);
+}
+
+static void
+sfxge_vpd_kstat_fini(sfxge_t *sp)
+{
+	sfxge_vpd_kstat_t *svkp = &(sp->s_vpd_kstat);
+
+	/* NOTE: VPD support is optional, so kstats might not be registered */
+	if (svkp->svk_ksp != NULL) {
+
+		kstat_delete(svkp->svk_ksp);
+
+		kmem_free(svkp->svk_vv,
+		    sizeof (efx_vpd_value_t) * SFXGE_VPD_MAX);
+
+		bzero(svkp->svk_stat,
+		    sizeof (kstat_named_t) * SFXGE_VPD_MAX);
+
+		svkp->svk_ksp = NULL;
+	}
+
+	SFXGE_OBJ_CHECK(svkp, sfxge_vpd_kstat_t);
+}
+
+static int
+sfxge_cfg_kstat_init(sfxge_t *sp)
+{
+	dev_info_t *dip = sp->s_dip;
+	char name[MAXNAMELEN];
+	kstat_t *ksp;
+	sfxge_cfg_kstat_t *sckp;
+	int rc;
+
+	sfxge_cfg_build(sp);
+
+	/* Create the set */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_cfg", ddi_driver_name(dip));
+
+	if ((ksp = kstat_create((char *)ddi_driver_name(dip),
+	    ddi_get_instance(dip), name, "cfg", KSTAT_TYPE_NAMED,
+	    sizeof (sckp->kstat) / sizeof (kstat_named_t),
+	    KSTAT_FLAG_VIRTUAL)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	sp->s_cfg_ksp = ksp;
+
+	ksp->ks_data = sckp = &(sp->s_cfg_kstat);
+
+	kstat_named_init(&(sckp->kstat.sck_mac), "mac", KSTAT_DATA_STRING);
+	kstat_named_setstr(&(sckp->kstat.sck_mac), sckp->buf.sck_mac);
+	ksp->ks_data_size += sizeof (sckp->buf.sck_mac);
+
+	kstat_named_init(&(sckp->kstat.sck_version), "version",
+	    KSTAT_DATA_STRING);
+	kstat_named_setstr(&(sckp->kstat.sck_version), sfxge_version);
+	ksp->ks_data_size += sizeof (sfxge_version);
+
+	kstat_install(ksp);
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_cfg_kstat_fini(sfxge_t *sp)
+{
+	if (sp->s_cfg_ksp == NULL)
+		return;
+
+	kstat_delete(sp->s_cfg_ksp);
+	sp->s_cfg_ksp = NULL;
+
+	bzero(&(sp->s_cfg_kstat), sizeof (sfxge_cfg_kstat_t));
+}
+
+static int
+sfxge_resume(dev_info_t *dip)
+{
+	sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
+	int rc;
+
+	/* Start processing */
+	if ((rc = sfxge_start(sp, B_FALSE)) != 0)
+		goto fail1;
+
+	return (DDI_SUCCESS);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (DDI_FAILURE);
+}
+
+static int
+sfxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+	sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
+	int rc;
+
+	switch (cmd) {
+	case DDI_ATTACH:
+		if (sp != NULL) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] ATTACH for attached instance\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip));
+			return (DDI_FAILURE);
+		}
+		break;
+
+	case DDI_RESUME:
+		if (sp == NULL) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] RESUME for missing instance\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip));
+			return (DDI_FAILURE);
+		}
+		return (sfxge_resume(dip));
+
+	default:
+		return (DDI_FAILURE);
+	}
+
+	/* Create the soft state */
+	if ((rc = sfxge_create(dip, &sp)) != 0)
+		goto fail1;
+
+	/* Create the configuration kstats */
+	if ((rc = sfxge_cfg_kstat_init(sp)) != 0)
+		goto fail2;
+
+	/* Create the VPD kstats */
+	if ((rc = sfxge_vpd_kstat_init(sp)) != 0) {
+		if (rc != ENOTSUP)
+			goto fail3;
+	}
+
+	/* Register the interface */
+	if ((rc = sfxge_register(sp)) != 0)
+		goto fail4;
+
+	/* Announce ourselves in the system log */
+	ddi_report_dev(dip);
+
+	return (DDI_SUCCESS);
+
+fail4:
+	DTRACE_PROBE(fail4);
+
+	/* Destroy the VPD kstats */
+	sfxge_vpd_kstat_fini(sp);
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	/* Destroy the configuration kstats */
+	sfxge_cfg_kstat_fini(sp);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Destroy the soft state */
+	(void) sfxge_destroy(sp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (DDI_FAILURE);
+}
+
+static int
+sfxge_suspend(dev_info_t *dip)
+{
+	sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
+
+	/* Stop processing */
+	sfxge_stop(sp);
+
+	return (DDI_SUCCESS);
+}
+
+static int
+sfxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+	sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
+	int rc;
+
+	switch (cmd) {
+	case DDI_DETACH:
+		if (sp == NULL) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] DETACH for missing instance\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip));
+			return (DDI_FAILURE);
+		}
+		break;
+
+	case DDI_SUSPEND:
+		if (sp == NULL) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] SUSPEND for missing instance\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip));
+			return (DDI_FAILURE);
+		}
+		return (sfxge_suspend(dip));
+
+	default:
+		return (DDI_FAILURE);
+	}
+
+	ASSERT(sp != NULL);
+
+	/* Wait for any pending restarts to complete */
+	ddi_taskq_wait(sp->s_tqp);
+
+	/*
+	 * IOCTLs from utilites can cause GLD mc_start() (SFXGE_STARTED state)
+	 * And mc_stop() may not occur until detach time and race. SFC bug 19855
+	 * Holding the lock seems to be enough - the log message is not seen
+	 */
+	mutex_enter(&(sp->s_state_lock));
+	if (sp->s_state == SFXGE_STARTED) {
+		cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] STREAMS detach when STARTED\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip));
+		sfxge_stop_locked(sp);
+		ASSERT3U(sp->s_state, ==, SFXGE_REGISTERED);
+	}
+	mutex_exit(&(sp->s_state_lock));
+
+	ASSERT(sp->s_state == SFXGE_REGISTERED ||
+	    sp->s_state == SFXGE_INITIALIZED);
+
+	if (sp->s_state != SFXGE_REGISTERED)
+		goto destroy;
+
+	/* Unregister the interface */
+	if ((rc = sfxge_unregister(sp)) != 0)
+		goto fail1;
+
+destroy:
+	/* Destroy the VPD kstats */
+	sfxge_vpd_kstat_fini(sp);
+
+	/* Destroy the configuration kstats */
+	sfxge_cfg_kstat_fini(sp);
+
+	/*
+	 * Destroy the soft state - this might fail until rx_loaned packets that
+	 * have been passed up the STREAMS stack are returned
+	 */
+	if ((rc = sfxge_destroy(sp)) != 0)
+		goto fail2;
+
+	return (DDI_SUCCESS);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (DDI_FAILURE);
+}
+
+#ifdef _USE_GLD_V3
+#ifndef _USE_GLD_V3_SOL10
+static int
+sfxge_quiesce(dev_info_t *dip)
+{
+	sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
+	int rc;
+
+	/* Reset the hardware */
+	if ((rc = sfxge_reset(sp, B_FALSE)) != 0)
+		goto fail1;
+
+	return (DDI_SUCCESS);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (DDI_FAILURE);
+}
+#endif
+#endif
+
+/*
+ * modlinkage
+ */
+DDI_DEFINE_STREAM_OPS(sfxge_dev_ops, nulldev, nulldev, sfxge_attach,
+    sfxge_detach, nulldev, NULL, D_MP, NULL, NULL);
+
+#ifdef _USE_GLD_V2
+
+static struct module_info	sfxge_module_info = {
+	0,
+	SFXGE_DRIVER_NAME,
+	0,
+	INFPSZ,
+	1,
+	0
+};
+
+static struct qinit		sfxge_rqinit = {
+	NULL,
+	gld_rsrv,
+	gld_open,
+	gld_close,
+	NULL,
+	&sfxge_module_info,
+	NULL
+};
+
+static struct qinit		sfxge_wqinit = {
+	gld_wput,
+	gld_wsrv,
+	NULL,
+	NULL,
+	NULL,
+	&sfxge_module_info,
+	NULL
+};
+
+static struct streamtab		sfxge_streamtab = {
+	&sfxge_rqinit,
+	&sfxge_wqinit,
+	NULL,
+	NULL
+};
+
+static struct cb_ops		sfxge_cb_ops = {
+	nulldev,		/* cb_open */
+	nulldev,		/* 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 */
+	&sfxge_streamtab,	/* cb_stream */
+	D_MP,			/* cb_flag */
+	CB_REV,			/* cb_rev */
+	nodev,			/* cb_aread */
+	nodev,			/* cb_awrite */
+};
+
+static struct dev_ops		sfxge_dev_ops = {
+	DEVO_REV,		/* devo_rev */
+	0,			/* devo_refcnt */
+	NULL,			/* devo_getinfo */
+	nulldev,		/* devo_identify */
+	nulldev,		/* devo_probe */
+	sfxge_attach,		/* devo_attach */
+	sfxge_detach,		/* devo_detach */
+	nulldev,		/* devo_reset */
+	&sfxge_cb_ops,		/* devo_cb_ops */
+	(struct bus_ops *)NULL,	/* devo_bus_ops */
+	NULL			/* devo_power */
+};
+
+#endif
+
+static struct modldrv		sfxge_modldrv = {
+	&mod_driverops,
+	(char *)sfxge_ident,
+	&sfxge_dev_ops,
+};
+
+static struct modlinkage	sfxge_modlinkage = {
+	MODREV_1,
+	{ &sfxge_modldrv, NULL }
+};
+
+kmutex_t	sfxge_global_lock;
+unsigned int	*sfxge_cpu;
+#ifdef	_USE_CPU_PHYSID
+unsigned int	*sfxge_core;
+unsigned int	*sfxge_cache;
+unsigned int	*sfxge_chip;
+#endif
+
+int
+_init(void)
+{
+	int rc;
+
+	mutex_init(&sfxge_global_lock, NULL, MUTEX_DRIVER, NULL);
+
+	/* Create tables for CPU, core, cache and chip counts */
+	sfxge_cpu = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
+#ifdef	_USE_CPU_PHYSID
+	sfxge_core = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
+	sfxge_cache = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
+	sfxge_chip = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
+#endif
+
+	if ((rc = ddi_soft_state_init(&sfxge_ss, sizeof (sfxge_t), 0)) != 0)
+		goto fail1;
+
+#ifdef _USE_GLD_V3
+	mac_init_ops(&sfxge_dev_ops, SFXGE_DRIVER_NAME);
+#endif
+
+	if ((rc = mod_install(&sfxge_modlinkage)) != 0)
+		goto fail2;
+
+	cmn_err(CE_NOTE, SFXGE_CMN_ERR
+	    "LOAD: Solarflare Ethernet Driver (%s) %s",
+	    SFXGE_DRIVER_NAME, sfxge_ident);
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+#ifdef _USE_GLD_V3
+//	mac_fini_ops(&sfxge_dev_ops);
+#endif
+
+	ddi_soft_state_fini(&sfxge_ss);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+int
+_fini(void)
+{
+	int rc;
+
+	if ((rc = mod_remove(&sfxge_modlinkage)) != 0)
+		return (rc);
+
+	cmn_err(CE_NOTE, SFXGE_CMN_ERR
+	    "UNLOAD: Solarflare Ethernet Driver (%s) %s",
+	    SFXGE_DRIVER_NAME, sfxge_ident);
+
+#ifdef _USE_GLD_V3
+	mac_fini_ops(&sfxge_dev_ops);
+#endif
+
+	ddi_soft_state_fini(&sfxge_ss);
+
+	/* Destroy tables */
+#ifdef	_USE_CPU_PHYSID
+	kmem_free(sfxge_chip, sizeof (unsigned int) * NCPU);
+	kmem_free(sfxge_cache, sizeof (unsigned int) * NCPU);
+	kmem_free(sfxge_core, sizeof (unsigned int) * NCPU);
+#endif
+	kmem_free(sfxge_cpu, sizeof (unsigned int) * NCPU);
+
+	mutex_destroy(&sfxge_global_lock);
+
+	return (0);
+}
+
+int
+_info(struct modinfo *mip)
+{
+	return (mod_info(&sfxge_modlinkage, mip));
+}
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge.conf	2013-08-22 18:57:33.102871784 -0400
@@ -0,0 +1,248 @@
+#### This file contains configuration parameters for the Solarflare
+#### network adapter driver "sfxge"
+
+################################################################################
+#### HOW TO MAKE CHANGES TO THIS FILE TAKE EFFECT
+################################################################################
+#### In order for changes made to this file to be used by the driver either:
+#### i) reboot
+#### OR
+#### ii) Unplumb all sfxge inet,inet6 interfaces or link aggregations: e.g.
+####       $ ifconfig sfxge0 unplumb
+####       $ ifconfig sfxge0 inet6 unplumb
+####     Delete any link aggregations that setup (see dladm show-aggr):
+####       $ dladm delete-aggr <key>
+####     Update the driver config
+####       $ update_drv sfxge
+####     Note update_drv will unload then reload the driver, otherwise it warns:
+####       "Cannot unload module: sfxge"
+####     Then plumb interfaces and reconfigure IP addresses as required
+#### 
+################################################################################
+
+################################################################################
+#### PER PORT SETTINGS
+################################################################################
+#### Note that is possible to have different settings per network port
+#### First using the file "/etc/path_to_inst" you can identify some information
+####
+####  $ grep sfxge /etc/path_to_inst
+####   # "/pci@3a,0/pci8086,340c@5/pci1924,6201@0"   4 "sfxge"
+####   # "/pci@3a,0/pci8086,340c@5/pci1924,6201@0,1" 5 "sfxge"
+####   #  ^^^^^^^^^^^^^^^^^^^^^^^^             ^^^
+####   #         parent                    unit-address
+####
+#### Using the information gathered above to create entries in this file
+#### based on the example below; this tries to allocate 4 MSI-X interrupts
+#### to port0 and 8 MSI-X interrupts to port 1
+####
+####  name="sfxge" parent="/pci@3a,0/pci8086,340c@5" unit-address="0"
+####               rx_scale_count=4;
+####  name="sfxge" parent="/pci@3a,0/pci8086,340c@5" unit-address="0,1"
+####               rx_scale_count=8;
+################################################################################
+
+################################################################################
+#### RECEIVE SIDE SCALING
+################################################################################
+#### Maximum number of RSS-channels to use per port (default 0, global max 32)
+#### This spreads RX flows across CPUs using multiple MSI-X interrupts
+####
+#### - A value of 0 tries to allocate the same number of RSS-channels as logical
+####   CPUs in order to provide the best spreading accross the entire system.
+####
+#### - actual number may be lower due to availability of MSI-X interrupts
+####
+#### - to successfully use >2 MSI-X interrupts per port you also need to use
+####  "set ddi_msix_alloc_limit=8" (maximum) in /etc/system and reboot
+####   OR temporarily adjust this limit using mdb and then reload the driver
+####     # mdb -kw
+####    > ddi_msix_alloc_limit/W 8
+####    ddi_msix_alloc_limit:           0x2            =       0x8
+####    > ddi_msix_alloc_limit/X
+####    ddi_msix_alloc_limit:
+####    ddi_msix_alloc_limit:           8
+####
+#### - Note that the total MSI-X interrupt vector assigned to all network
+####     drivers (in IPL 6; interrupt priority level) is 32
+####   See the "INTERUPT PRIORITY" section for a way overcome this
+####
+####  -  You can see the current allocation with this run as root:
+####   $ echo "::interrupts -d" | mdb -k | egrep 'IRQ| 6 '
+####     IRQ  Vector IPL Bus   Type  CPU Share APIC/INT# Driver Name(s)
+####     93   0x60   6         MSI-X 2   1     -         sfxge#0
+####     94   0x61   6         MSI-X 3   1     -         sfxge#0
+####                ^^^
+####
+#### - If the sysadmin does not take care to partition the interupts between
+####     the network ports then later ports could use a single legacy interrupt
+####     i.e. no RSS, significantly reducing performance
+####   See PER PORT SETTINGS ABOVE for how to apply rx_scale_count per port
+####
+#### - rx_scale_count can be manipulated dynamically via ndd but the number
+####   of interrupts will stay the same; though only a subset will fire for RX. 
+####   All interrupts will still see ~10 interrupts/sec
+####
+#### - note that the number of RSS-channels can be set to be greater than the
+####   number of logical CPUs. This can be useful to prevent some types of RX
+####   drops
+
+rx_scale_count=0;
+
+################################################################################
+#### USING NON_DEFAULT INTERRUPT PRIORITY LEVEL (IPL)
+################################################################################
+#### To overcome the Solaris limitation of 32 MSI-X vectors per IPL
+#### it is possible to set this driver to allocate interrupts in a different IPL
+#### Please only do this if necessary
+####
+#### See http://download.oracle.com/docs/cd/E20815_01/html/E20816/gjtag.html
+#### Verify with:
+####   $ echo "::interrupts -d" | mdb -k | egrep 'IRQ|sfxge'
+####     IRQ  Vector IPL Bus   Type  CPU Share APIC/INT# Driver Name(s)
+####     93   0x60   5         MSI-X 2   1     -         sfxge#0
+####     94   0x61   5         MSI-X 3   1     -         sfxge#0
+####                ^^^
+####
+#### (default IPL 6; the document referenced recommends 5 or 4)
+
+#interrupt-priorities=5;
+
+################################################################################
+#### RX DMA RING SIZE
+################################################################################
+#### Number of entries in the per receive queue hardware DMA ring
+####
+#### Increase this value if you see increasing values of "rx_nodesc_drop_cnt"
+#### as reported by "kstat -m sfxge -c mac -s rx_nodesc_drop_cnt" and you think
+#### the traffic is bursty
+####
+#### Increasing this value can increase driver memory usage and reduce the
+#### cache-hit rates seen for RX buffers so the largest value is not
+#### necessarily the best
+####
+#### (minimum 512)
+#### (default 1024)
+#### (maximum 4096)
+#### The value must be a power of two else it will be ignored.
+
+#rxq_size=1024;
+
+################################################################################
+#### LARGE RECEIVE OFFLOAD
+################################################################################
+#### Coalesce RX packets (aka Large Receive Offload)
+####  0 => off (default)
+####  1 => on
+####  2 => on, respecting TCP PSH boundaries
+
+#rx_coalesce_mode=1;
+
+################################################################################
+#### INTERRUPT MODERATION
+################################################################################
+#### Interrupt moderation in us (default 30, minimum 0)
+#### Decreasing this reduces latency but increases interrupt rate and therefore
+#### CPU usage which will decrease maximum bandwidth achievable
+####
+#### Decrease this value if you see increasing values of "rx_nodesc_drop_cnt"
+#### as reported by "kstat -m sfxge -c mac -s rx_nodesc_drop_cnt" so that
+#### the driver has more opportunities to refill the hardware RX descriptor
+#### ring
+####
+#### (maximum 20000 us)
+#### (default 30 us)
+
+#intr_moderation=10;
+
+################################################################################
+#### MAXIMUM MTU
+################################################################################
+#### Maximum MTU of an sfxge interface (in bytes - excludes ethernet framing)
+#### Increase this value to support Jumbo frames
+####
+#### NB increasing this value consumes more memory for all RX buffers
+#### even for network interfaces not configured with high MTUs
+####
+#### MTUs over 3968 mean that >1 contiguous 4k page of memory are allocated
+#### for all receive buffers. Contiguous pages of memory can be harder for
+#### the OS to allocate when under memory pressue.
+#### 
+#### In Solaris 11 the MTU can be dynamically changed so you should not
+#### need to alter the setting below. A non-default MTU can be persistently
+#### configured depending on your network configuration:
+#### 1) For manual mode or using NWAM with the DefaultFixed profile:
+####    dladm set-linkprop -p mtu=<MTU> sfxge<n>
+#### 2) If using NWAM using a custom profile please set the property link-mtu:
+####    netcfg "select ncp myprofile; select ncu phys sfxge0; set link-mtu=9000"
+####
+#### (maximum 9000)
+#### (default 1500)
+
+#mtu=1500;
+
+################################################################################
+#### PER PORT MEMORY LIMIT FOR RX PACKET BUFFERS
+################################################################################
+#### Limit max memory for RX packets allocated per instance (port) in bytes
+####
+#### RX packets are passed up from the driver to the kernel TCP/IP stack
+#### and freed after the data is delivered to the application socket
+#### buffers. If the OS falls behind this allocation can grow.
+####
+#### This parameter can help make behaviour reasonable when approaching
+#### an overload condition. Other ways to avoid overload would be RSS
+####
+#### The size of each bufer, number in use can be seen with
+####    echo "::kmastat" | mdb -k
+#### OR kstat -c kmem_cache -n sfxgeX_rx_packet_cache # replace X
+####
+#### (default unlimited when unset)
+####
+#### Note In Solarflare driver package versions 3.1.x.xxxx and earlier set
+#### the RX buffering limit to 10773741824 (1GB) per interface in this file.
+####
+#### 64MB of RX buffering per interface is still oversized for nearly all
+#### applications but provides a hard limit.
+
+rx_pkt_mem_max=67108864;
+
+################################################################################
+#### PREALLOCATION OF RX PACKET BUFFERS
+################################################################################
+#### Number of rx packet buffers to allocate at start of an rxq and keep a
+#### free packet pool of atleast this many.
+####
+#### Keeping a free packet pool of rx packet buffers means we do not need to
+#### repeatedly allocate and map dma buffers.
+####
+#### (minimum 0 => off)
+#### (default 0 => off)
+#### (maximum is limited by available memory)
+
+#rx_prealloc_pkt_buffers=512;
+
+################################################################################
+#### ACTION ON HARDWARE ERRORS
+################################################################################
+#### This parameter controls the action taken on a hardware error
+#### which may be a PCIe error or the driver detecting unexpected behaviour
+#### from the hardware
+####
+#### Currently this driver does not reports error into the Solaris fault
+#### management architecture (but the PCIe root-port may do so)
+####
+#### 0 => recover the server adapter to a working state
+#### 1 => do not advertise to the kernel that the link is down during the reset
+#### 2 => reset the hardware, but do not attempt to use it again.
+####      this is useful if you have a failover mechanism, and want to ensure
+####      that this server adapter does not become the active link again
+####      note that the interface will stay plumbed but will not pass traffic
+####
+#### All of the above log a message and increment a kstat counter viewable with:
+####    kstat -m sfxge -c mon -s num_restarts_hw_err
+####
+#### (default 0 => recover)
+
+action_on_hw_err=0;
+
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge.h	2013-08-22 18:57:33.190749227 -0400
@@ -0,0 +1,1085 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Solaris 10 9/10 (U9) is required to build this driver, as earlier Solaris
+ * releases do not ship with the required header files for GLDv3.  The driver
+ * will run on Solaris 10 10/09 (U8) and later versions.
+ */
+
+
+#ifndef	_SYS_SFXGE_H
+#define	_SYS_SFXGE_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stream.h>
+#include <sys/ethernet.h>
+#include <sys/cpuvar.h>
+
+#ifdef _USE_GLD_V3
+#include <sys/mac.h>
+#include <sys/mac_ether.h>
+#include <sys/mac_provider.h>
+#endif
+
+#ifdef _USE_GLD_V2
+#include <sys/gld.h>
+#endif
+
+#include "sfxge_ioc.h"
+#include "sfxge_debug.h"
+
+#include "efx.h"
+#include "efx_regs.h"
+
+#ifdef _USE_GLD_V3_SOL10
+#include "compat.h"
+#endif
+
+#if defined(_USE_MAC_PRIV_PROP) && !defined(_USE_GLD_V3_PROPS)
+#error "The _USE_MAC_PRIV_PROP build option is dependent on _USE_GLD_V3_PROPS"
+#endif
+
+#ifdef	_KERNEL
+
+#define	SFXGE_DRIVER_NAME "sfxge"
+
+#define	SFXGE_CPU_CACHE_SIZE	64
+
+#define	IS_POW2(x)  ((x) && ! ((x) & ((x) - 1)))
+
+typedef struct sfxge_s	sfxge_t;
+
+typedef enum sfxge_intr_state_e {
+	SFXGE_INTR_UNINITIALIZED = 0,
+	SFXGE_INTR_INITIALIZED,
+	SFXGE_INTR_TESTING,
+	SFXGE_INTR_STARTED
+} sfxge_intr_state_t;
+
+typedef struct sfxge_intr_s {
+	ddi_intr_handle_t	*si_table;
+	int			si_table_size;
+	int			si_nalloc;
+	int			si_type;
+	int			si_cap;
+	efsys_mem_t		si_mem;
+	uint64_t		si_mask;
+	sfxge_intr_state_t	si_state;
+	uint32_t		si_zero_count;
+	int			si_intr_pri;
+} sfxge_intr_t;
+
+typedef enum sfxge_promisc_type_e {
+	SFXGE_PROMISC_OFF = 0,
+	SFXGE_PROMISC_ALL_MULTI,
+	SFXGE_PROMISC_ALL_PHYS
+} sfxge_promisc_type_t;
+
+typedef enum sfxge_link_duplex_e {
+	SFXGE_LINK_DUPLEX_UNKNOWN = 0,
+	SFXGE_LINK_DUPLEX_HALF,
+	SFXGE_LINK_DUPLEX_FULL
+} sfxge_link_duplex_t;
+
+typedef enum sfxge_unicst_type_e {
+	SFXGE_UNICST_BIA = 0,
+	SFXGE_UNICST_LAA,
+	SFXGE_UNICST_NTYPES
+} sfxge_unicst_type_t;
+
+typedef struct sfxge_phy_s {
+		kstat_t			*sp_ksp;
+		kstat_named_t		*sp_stat;
+		uint32_t		*sp_statbuf;
+		efsys_mem_t		sp_mem;
+} sfxge_phy_t;
+
+typedef enum sfxge_mac_state_e {
+	SFXGE_MAC_UNINITIALIZED = 0,
+	SFXGE_MAC_INITIALIZED,
+	SFXGE_MAC_STARTED
+} sfxge_mac_state_t;
+
+typedef struct sfxge_mac_s {
+	sfxge_t			*sm_sp;
+	efsys_mem_t		sm_mem;
+	kstat_t			*sm_ksp;
+	kstat_named_t		*sm_stat;
+	uint8_t			sm_bia[ETHERADDRL];
+	uint8_t			sm_laa[ETHERADDRL];
+	boolean_t		sm_laa_valid;
+	unsigned int		sm_fcntl;
+	sfxge_promisc_type_t	sm_promisc;
+	unsigned int		sm_bucket[EFX_MAC_HASH_BITS];
+	clock_t			sm_lbolt;
+	kmutex_t		sm_lock;
+	efx_link_mode_t		sm_link_mode;
+	unsigned int		sm_link_speed;
+	sfxge_link_duplex_t	sm_link_duplex;
+	boolean_t		sm_link_up;
+	boolean_t		sm_link_poll_reqd;
+	kcondvar_t		sm_link_poll_kv;
+	boolean_t		sm_mac_stats_timer_reqd;
+	boolean_t		sm_mac_stats_pend;
+	ddi_taskq_t		*sm_tqp;
+	sfxge_mac_state_t	sm_state;
+	sfxge_phy_t		sm_phy;
+	uint32_t		sm_phy_cap_to_set;
+	uint32_t		sm_phy_cap_to_unset;
+} sfxge_mac_t;
+
+typedef enum sfxge_mon_state_e {
+	SFXGE_MON_UNINITIALIZED = 0,
+	SFXGE_MON_INITIALIZED,
+	SFXGE_MON_STARTED
+} sfxge_mon_state_t;
+
+typedef struct sfxge_mon_s {
+	sfxge_t			*sm_sp;
+	efx_mon_type_t		sm_type;
+	unsigned int		sm_devid;
+	kstat_t			*sm_ksp;
+	kstat_named_t		*sm_stat;
+	efx_mon_stat_value_t	*sm_statbuf;
+	kmutex_t		sm_lock;
+	sfxge_mon_state_t	sm_state;
+	efsys_mem_t		sm_mem;
+} sfxge_mon_t;
+
+typedef enum sfxge_sram_state_e {
+	SFXGE_SRAM_UNINITIALIZED = 0,
+	SFXGE_SRAM_INITIALIZED,
+	SFXGE_SRAM_STARTED
+} sfxge_sram_state_t;
+
+typedef struct sfxge_sram_s {
+	sfxge_t			*ss_sp;
+	kmutex_t		ss_lock;
+	vmem_t			*ss_buf_tbl;
+	unsigned int		ss_count;
+	sfxge_sram_state_t	ss_state;
+} sfxge_sram_t;
+
+typedef enum sfxge_mcdi_state_e {
+	SFXGE_MCDI_UNINITIALIZED = 0,
+	SFXGE_MCDI_INITIALIZED,
+	SFXGE_MCDI_BUSY,
+	SFXGE_MCDI_COMPLETED
+} sfxge_mcdi_state_t;
+
+typedef struct sfxge_mcdi_s {
+	sfxge_t			*sm_sp;
+	kmutex_t		sm_lock;
+	sfxge_mcdi_state_t	sm_state;
+	efx_mcdi_transport_t	sm_emt;
+	kcondvar_t		sm_kv;		/* MCDI poll complete */
+} sfxge_mcdi_t;
+
+#define	SFXGE_NEVS	4096
+#define	SFXGE_NDESCS	1024
+#define	SFXGE_TX_NDESCS	SFXGE_NDESCS
+#define	SFXGE_DEFAULT_RXQ_SIZE 1024
+
+#define	SFXGE_DEFAULT_MODERATION	30
+
+typedef enum sfxge_evq_state_e {
+	SFXGE_EVQ_UNINITIALIZED = 0,
+	SFXGE_EVQ_INITIALIZED,
+	SFXGE_EVQ_STARTING,
+	SFXGE_EVQ_STARTED
+} sfxge_evq_state_t;
+
+#define	SFXGE_EV_BATCH	(SFXGE_NEVS / 4)
+
+typedef struct sfxge_txq_s	sfxge_txq_t;
+
+typedef struct sfxge_evq_s {
+	union {
+		struct {
+			sfxge_t			*__se_sp;
+			unsigned int		__se_index;
+			efsys_mem_t		__se_mem;
+			unsigned int		__se_id;
+			kstat_t			*__se_ksp;
+			kstat_named_t		*__se_stat;
+			efx_ev_callbacks_t	__se_eec;
+			sfxge_evq_state_t	__se_state;
+			boolean_t		__se_exception;
+		} __se_s1;
+		uint8_t __se_pad[SFXGE_CPU_CACHE_SIZE * 4];
+	} __se_u1;
+	union {
+		struct {
+			kmutex_t		__se_lock;
+			kcondvar_t		__se_init_kv;
+			efx_evq_t		*__se_eep;
+			unsigned int		__se_count;
+			unsigned int		__se_rx;
+			unsigned int		__se_tx;
+			sfxge_txq_t		*__se_stp;
+			sfxge_txq_t		**__se_stpp;
+			processorid_t		__se_cpu_id;
+#ifdef	_USE_CPU_PHYSID
+			id_t			__se_chip_id;
+			id_t			__se_core_id;
+			id_t			__se_cache_id;
+#endif
+			uint16_t		__se_ev_batch;
+		} __se_s2;
+		uint8_t	__se_pad[SFXGE_CPU_CACHE_SIZE];
+	} __se_u2;
+} sfxge_evq_t;
+
+#define	se_sp		__se_u1.__se_s1.__se_sp
+#define	se_index	__se_u1.__se_s1.__se_index
+#define	se_mem		__se_u1.__se_s1.__se_mem
+#define	se_id		__se_u1.__se_s1.__se_id
+#define	se_ksp		__se_u1.__se_s1.__se_ksp
+#define	se_stat		__se_u1.__se_s1.__se_stat
+#define	se_eec		__se_u1.__se_s1.__se_eec
+#define	se_state	__se_u1.__se_s1.__se_state
+#define	se_exception	__se_u1.__se_s1.__se_exception
+
+#define	se_lock		__se_u2.__se_s2.__se_lock
+#define	se_init_kv	__se_u2.__se_s2.__se_init_kv
+#define	se_eep		__se_u2.__se_s2.__se_eep
+#define	se_count	__se_u2.__se_s2.__se_count
+#define	se_rx		__se_u2.__se_s2.__se_rx
+#define	se_tx		__se_u2.__se_s2.__se_tx
+#define	se_stp		__se_u2.__se_s2.__se_stp
+#define	se_stpp		__se_u2.__se_s2.__se_stpp
+#define	se_cpu_id	__se_u2.__se_s2.__se_cpu_id
+#ifdef	_USE_CPU_PHYSID
+#define	se_chip_id	__se_u2.__se_s2.__se_chip_id
+#define	se_core_id	__se_u2.__se_s2.__se_core_id
+#define	se_cache_id	__se_u2.__se_s2.__se_cache_id
+#endif
+#define	se_ev_batch	__se_u2.__se_s2.__se_ev_batch
+
+#define	SFXGE_MAGIC_RESERVED	0x8000
+
+#define	SFXGE_MAGIC_DMAQ_LABEL_WIDTH  5
+#define	SFXGE_MAGIC_DMAQ_LABEL_MASK   ((1 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH) - 1)
+
+#define	SFXGE_MAGIC_RX_QFLUSH_DONE					\
+	(SFXGE_MAGIC_RESERVED | (1 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH))
+
+#define	SFXGE_MAGIC_RX_QFLUSH_FAILED					\
+	(SFXGE_MAGIC_RESERVED | (2 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH))
+
+#define	SFXGE_MAGIC_RX_QFPP_TRIM					\
+	(SFXGE_MAGIC_RESERVED | (3 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH))
+
+#define	SFXGE_MAGIC_TX_QFLUSH_DONE					\
+	(SFXGE_MAGIC_RESERVED | (4 << SFXGE_MAGIC_DMAQ_LABEL_WIDTH))
+
+typedef struct sfxge_rxq_s		sfxge_rxq_t;
+
+#define	SFXGE_IP_ALIGN	2
+
+#define	SFXGE_ETHERTYPE_LOOPBACK	0x9000	/* Xerox loopback */
+
+typedef struct sfxge_rx_packet_s	sfxge_rx_packet_t;
+
+struct sfxge_rx_packet_s {
+	union {
+		struct {
+			frtn_t			__srp_free;
+			uint16_t		__srp_flags;
+			uint16_t		__srp_size;
+			mblk_t			*__srp_mp;
+			struct ether_header	*__srp_etherhp;
+			struct ip		*__srp_iphp;
+			struct tcphdr		*__srp_thp;
+			size_t			__srp_off;
+		} __srp_s1;
+		uint8_t	__srp_pad[SFXGE_CPU_CACHE_SIZE];
+	} __srp_u1;
+	union {
+		struct {
+			sfxge_rxq_t		*__srp_srp;
+			ddi_dma_handle_t	__srp_dma_handle;
+			ddi_acc_handle_t	__srp_acc_handle;
+			unsigned char		*__srp_base;
+			size_t			__srp_mblksize;
+			uint64_t		__srp_addr;
+			boolean_t		__srp_recycle;
+			caddr_t			__srp_putp;
+		} __srp_s2;
+		uint8_t	__srp_pad[SFXGE_CPU_CACHE_SIZE * 2];
+	} __srp_u2;
+};
+
+#define	srp_free	__srp_u1.__srp_s1.__srp_free
+#define	srp_flags	__srp_u1.__srp_s1.__srp_flags
+#define	srp_size	__srp_u1.__srp_s1.__srp_size
+#define	srp_mp		__srp_u1.__srp_s1.__srp_mp
+#define	srp_etherhp	__srp_u1.__srp_s1.__srp_etherhp
+#define	srp_iphp	__srp_u1.__srp_s1.__srp_iphp
+#define	srp_thp		__srp_u1.__srp_s1.__srp_thp
+#define	srp_off		__srp_u1.__srp_s1.__srp_off
+
+#define	srp_srp		__srp_u2.__srp_s2.__srp_srp
+#define	srp_dma_handle	__srp_u2.__srp_s2.__srp_dma_handle
+#define	srp_acc_handle	__srp_u2.__srp_s2.__srp_acc_handle
+#define	srp_base	__srp_u2.__srp_s2.__srp_base
+#define	srp_mblksize	__srp_u2.__srp_s2.__srp_mblksize
+#define	srp_addr	__srp_u2.__srp_s2.__srp_addr
+#define	srp_recycle	__srp_u2.__srp_s2.__srp_recycle
+#define	srp_putp	__srp_u2.__srp_s2.__srp_putp
+
+#define	SFXGE_RX_FPP_NSLOTS	8
+#define	SFXGE_RX_FPP_MASK	(SFXGE_RX_FPP_NSLOTS - 1)
+
+/* Free packet pool putlist (dynamically allocated) */
+typedef struct sfxge_rx_fpp_putlist_s {
+	kmutex_t		srfpl_lock;
+	unsigned int		srfpl_count;
+	mblk_t			*srfpl_putp;
+	mblk_t			**srfpl_putpp;
+} sfxge_rx_fpp_putlist_t;
+
+/* Free packet pool */
+typedef struct sfxge_rx_fpp_s {
+	caddr_t		srfpp_putp;
+	unsigned int	srfpp_loaned;
+	mblk_t		*srfpp_get;
+	unsigned int	srfpp_count;
+	unsigned int	srfpp_min;
+	/* Low water mark: Don't trim to below this */
+	unsigned int    srfpp_lowat;
+} sfxge_rx_fpp_t;
+
+typedef struct sfxge_rx_flow_s	sfxge_rx_flow_t;
+
+struct sfxge_rx_flow_s {
+	uint32_t		srf_tag;
+	/* in-order segment count */
+	unsigned int		srf_count;
+	uint16_t		srf_tci;
+	uint32_t		srf_saddr;
+	uint32_t		srf_daddr;
+	uint16_t		srf_sport;
+	uint16_t		srf_dport;
+	/* sequence number */
+	uint32_t		srf_seq;
+	clock_t			srf_lbolt;
+	mblk_t			*srf_mp;
+	mblk_t			**srf_mpp;
+	struct ether_header	*srf_etherhp;
+	struct ip		*srf_iphp;
+	struct tcphdr		*srf_first_thp;
+	struct tcphdr		*srf_last_thp;
+	size_t			srf_len;
+	sfxge_rx_flow_t		*srf_next;
+};
+
+#define	SFXGE_MAX_FLOW		1024
+#define	SFXGE_SLOW_START	20
+
+typedef enum sfxge_flush_state_e {
+	SFXGE_FLUSH_INACTIVE = 0,
+	SFXGE_FLUSH_DONE,
+	SFXGE_FLUSH_PENDING,
+	SFXGE_FLUSH_FAILED
+} sfxge_flush_state_t;
+
+typedef enum sfxge_rxq_state_e {
+	SFXGE_RXQ_UNINITIALIZED = 0,
+	SFXGE_RXQ_INITIALIZED,
+	SFXGE_RXQ_STARTED
+} sfxge_rxq_state_t;
+
+
+#define	SFXGE_RX_BATCH	128
+#define	SFXGE_RX_NSTATS	8 /* note that *esballoc share one kstat */
+
+struct sfxge_rxq_s {
+	union {
+		struct {
+			sfxge_t				*__sr_sp;
+			unsigned int			__sr_index;
+			efsys_mem_t			__sr_mem;
+			unsigned int			__sr_id;
+			unsigned int			__sr_lowat;
+			unsigned int			__sr_hiwat;
+			volatile timeout_id_t		__sr_tid;
+			sfxge_rxq_state_t		__sr_state;
+		} __sr_s1;
+		uint8_t	__sr_pad[SFXGE_CPU_CACHE_SIZE * 2];
+	} __sr_u1;
+	union {
+		struct {
+			sfxge_rx_packet_t		**__sr_srpp;
+			unsigned int			__sr_added;
+			unsigned int			__sr_pending;
+			unsigned int			__sr_completed;
+			unsigned int			__sr_loopback;
+			mblk_t   			*__sr_mp;
+			mblk_t   			**__sr_mpp;
+			sfxge_rx_flow_t			*__sr_flow;
+			sfxge_rx_flow_t			*__sr_srfp;
+			sfxge_rx_flow_t			**__sr_srfpp;
+			clock_t				__sr_rto;
+		} __sr_s2;
+		uint8_t	__sr_pad[SFXGE_CPU_CACHE_SIZE * 2];
+	} __sr_u2;
+	union {
+		struct {
+			sfxge_rx_fpp_t			__sr_fpp;
+			efx_rxq_t			*__sr_erp;
+			volatile sfxge_flush_state_t	__sr_flush;
+			kcondvar_t			__sr_flush_kv;
+			kstat_t				*__sr_ksp;
+		} __sr_s3;
+		uint8_t	__sr_pad[SFXGE_CPU_CACHE_SIZE];
+	} __sr_u3;
+	struct {
+		/* NB must match SFXGE_RX_NSTATS */
+		uint32_t    srk_rx_pkt_mem_limit;
+		uint32_t    srk_kcache_alloc_nomem;
+		uint32_t    srk_dma_alloc_nomem;
+		uint32_t    srk_dma_alloc_fail;
+		uint32_t    srk_dma_bind_nomem;
+		uint32_t    srk_dma_bind_fail;
+		/* Following two are mutually exclusive */
+#ifdef _USE_XESBALLOC
+		uint32_t    srk_xesballoc_fail;
+#endif
+#ifdef _USE_DESBALLOC
+		uint32_t    srk_desballoc_fail;
+#endif
+		uint32_t    srk_rxq_empty_discard;
+	} sr_kstat;
+};
+
+#define	sr_sp		__sr_u1.__sr_s1.__sr_sp
+#define	sr_index	__sr_u1.__sr_s1.__sr_index
+#define	sr_mem		__sr_u1.__sr_s1.__sr_mem
+#define	sr_id		__sr_u1.__sr_s1.__sr_id
+#define	sr_mrh		__sr_u1.__sr_s1.__sr_mrh
+#define	sr_lowat	__sr_u1.__sr_s1.__sr_lowat
+#define	sr_hiwat	__sr_u1.__sr_s1.__sr_hiwat
+#define	sr_tid		__sr_u1.__sr_s1.__sr_tid
+#define	sr_state	__sr_u1.__sr_s1.__sr_state
+
+#define	sr_srpp		__sr_u2.__sr_s2.__sr_srpp
+#define	sr_added	__sr_u2.__sr_s2.__sr_added
+#define	sr_pending	__sr_u2.__sr_s2.__sr_pending
+#define	sr_completed	__sr_u2.__sr_s2.__sr_completed
+#define	sr_loopback	__sr_u2.__sr_s2.__sr_loopback
+#define	sr_mp		__sr_u2.__sr_s2.__sr_mp
+#define	sr_mpp		__sr_u2.__sr_s2.__sr_mpp
+#define	sr_flow		__sr_u2.__sr_s2.__sr_flow
+#define	sr_srfp		__sr_u2.__sr_s2.__sr_srfp
+#define	sr_srfpp	__sr_u2.__sr_s2.__sr_srfpp
+#define	sr_rto		__sr_u2.__sr_s2.__sr_rto
+
+#define	sr_fpp		__sr_u3.__sr_s3.__sr_fpp
+#define	sr_erp		__sr_u3.__sr_s3.__sr_erp
+#define	sr_flush	__sr_u3.__sr_s3.__sr_flush
+#define	sr_flush_kv	__sr_u3.__sr_s3.__sr_flush_kv
+#define	sr_ksp		__sr_u3.__sr_s3.__sr_ksp
+
+typedef struct sfxge_tx_packet_s	sfxge_tx_packet_t;
+
+struct sfxge_tx_packet_s {
+	sfxge_tx_packet_t	*stp_next;
+	mblk_t			*stp_mp;
+	struct ether_header	*stp_etherhp;
+	struct ip 		*stp_iphp;
+	struct tcphdr		*stp_thp;
+	size_t			stp_off;
+	size_t			stp_size;
+	size_t			stp_mss;
+	uint32_t		stp_dpl_put_len;
+};
+
+#define	SFXGE_TX_FPP_MAX	64
+
+typedef struct sfxge_tx_fpp_s {
+	sfxge_tx_packet_t	*stf_stpp;
+	unsigned int		stf_count;
+} sfxge_tx_fpp_t;
+
+typedef struct sfxge_tx_mapping_s	sfxge_tx_mapping_t;
+
+#define	SFXGE_TX_MAPPING_NADDR	(((1 << 16) >> 12) + 2)
+
+struct sfxge_tx_mapping_s {
+	sfxge_tx_mapping_t	*stm_next;
+	sfxge_t			*stm_sp;
+	mblk_t			*stm_mp;
+	ddi_dma_handle_t	stm_dma_handle;
+	caddr_t			stm_base;
+	size_t			stm_size;
+	size_t			stm_off;
+	uint64_t		stm_addr[SFXGE_TX_MAPPING_NADDR];
+};
+
+typedef struct sfxge_tx_fmp_s {
+	sfxge_tx_mapping_t	*stf_stmp;
+	unsigned int		stf_count;
+} sfxge_tx_fmp_t;
+
+typedef struct sfxge_tx_buffer_s	sfxge_tx_buffer_t;
+
+struct sfxge_tx_buffer_s {
+	sfxge_tx_buffer_t	*stb_next;
+	size_t			stb_off;
+	efsys_mem_t		stb_esm;
+};
+
+#define	SFXGE_TX_BUFFER_SIZE	0x400
+#define	SFXGE_TX_HEADER_SIZE	0x100
+#define	SFXGE_TX_COPY_THRESHOLD	0x200
+
+typedef struct sfxge_tx_fbp_s {
+	sfxge_tx_buffer_t	*stf_stbp;
+	unsigned int		stf_count;
+} sfxge_tx_fbp_t;
+
+typedef struct sfxge_tx_dpl_s {
+	uintptr_t		std_put;
+	sfxge_tx_packet_t	*std_get;
+	sfxge_tx_packet_t	**std_getp;
+	unsigned int		std_count; /* only get list count */
+	unsigned int		get_pkt_limit;
+	unsigned int		put_pkt_limit;
+	unsigned int		get_full_count;
+	unsigned int		put_full_count;
+} sfxge_tx_dpl_t;
+
+typedef enum sfxge_txq_state_e {
+	SFXGE_TXQ_UNINITIALIZED = 0,
+	SFXGE_TXQ_INITIALIZED,
+	SFXGE_TXQ_STARTED
+} sfxge_txq_state_t;
+
+typedef enum sfxge_txq_type_e {
+	SFXGE_TXQ_NON_CKSUM = 0,
+	SFXGE_TXQ_IP_CKSUM,
+	SFXGE_TXQ_IP_TCP_UDP_CKSUM,
+	SFXGE_TXQ_NTYPES
+} sfxge_txq_type_t;
+
+#define	SFXGE_TXQ_UNBLOCK_LEVEL1	(EFX_TXQ_LIMIT(SFXGE_NDESCS) / 4)
+#define	SFXGE_TXQ_UNBLOCK_LEVEL2	0
+#define	SFXGE_TXQ_NOT_BLOCKED		-1
+
+#define	SFXGE_TX_BATCH	64
+
+struct sfxge_txq_s {
+	union {
+		struct {
+			sfxge_t				*__st_sp;
+			unsigned int			__st_index;
+			sfxge_txq_type_t		__st_type;
+			unsigned int			__st_evq;
+			efsys_mem_t			__st_mem;
+			unsigned int			__st_id;
+			kstat_t				*__st_ksp;
+			kstat_named_t			*__st_stat;
+			sfxge_txq_state_t		__st_state;
+		} __st_s1;
+		uint8_t	__st_pad[SFXGE_CPU_CACHE_SIZE * 2];
+	} __st_u1;
+	union {
+		struct {
+			sfxge_tx_dpl_t			__st_dpl;
+		} __st_s2;
+		uint8_t	__st_pad[SFXGE_CPU_CACHE_SIZE];
+	} __st_u2;
+	union {
+		struct {
+			kmutex_t			__st_lock;
+			/* mapping pool - sfxge_tx_mapping_t */
+			sfxge_tx_fmp_t			__st_fmp;
+			/* buffer pool - sfxge_tx_buffer_t */
+			sfxge_tx_fbp_t			__st_fbp;
+			/* packet pool - sfxge_tx_packet_t */
+			sfxge_tx_fpp_t			__st_fpp;
+			efx_buffer_t			*__st_eb;
+			unsigned int			__st_n;
+			efx_txq_t			*__st_etp;
+			sfxge_tx_mapping_t		**__st_stmp;
+			sfxge_tx_buffer_t		**__st_stbp;
+			mblk_t				**__st_mp;
+			unsigned int			__st_added;
+			unsigned int			__st_reaped;
+			int				__st_unblock;
+		} __st_s3;
+		uint8_t	__st_pad[SFXGE_CPU_CACHE_SIZE * 3];
+	} __st_u3;
+	union {
+		struct {
+			sfxge_txq_t			*__st_next;
+			unsigned int			__st_pending;
+			unsigned int			__st_completed;
+			volatile sfxge_flush_state_t	__st_flush;
+
+		} __st_s4;
+		uint8_t	__st_pad[SFXGE_CPU_CACHE_SIZE];
+	} __st_u4;
+};
+
+#define	st_sp		__st_u1.__st_s1.__st_sp
+#define	st_index	__st_u1.__st_s1.__st_index
+#define	st_type		__st_u1.__st_s1.__st_type
+#define	st_evq		__st_u1.__st_s1.__st_evq
+#define	st_mem		__st_u1.__st_s1.__st_mem
+#define	st_id		__st_u1.__st_s1.__st_id
+#define	st_ksp		__st_u1.__st_s1.__st_ksp
+#define	st_stat		__st_u1.__st_s1.__st_stat
+#define	st_state	__st_u1.__st_s1.__st_state
+
+#define	st_dpl		__st_u2.__st_s2.__st_dpl
+
+#define	st_lock		__st_u3.__st_s3.__st_lock
+#define	st_fmp		__st_u3.__st_s3.__st_fmp
+#define	st_fbp		__st_u3.__st_s3.__st_fbp
+#define	st_fpp		__st_u3.__st_s3.__st_fpp
+#define	st_eb		__st_u3.__st_s3.__st_eb
+#define	st_n		__st_u3.__st_s3.__st_n
+#define	st_etp		__st_u3.__st_s3.__st_etp
+#define	st_stmp		__st_u3.__st_s3.__st_stmp
+#define	st_stbp		__st_u3.__st_s3.__st_stbp
+#define	st_mp		__st_u3.__st_s3.__st_mp
+#define	st_added	__st_u3.__st_s3.__st_added
+#define	st_reaped	__st_u3.__st_s3.__st_reaped
+#define	st_unblock	__st_u3.__st_s3.__st_unblock
+
+#define	st_next		__st_u4.__st_s4.__st_next
+#define	st_pending	__st_u4.__st_s4.__st_pending
+#define	st_completed	__st_u4.__st_s4.__st_completed
+#define	st_flush	__st_u4.__st_s4.__st_flush
+
+typedef enum sfxge_rx_scale_state_e {
+	SFXGE_RX_SCALE_UNINITIALIZED = 0,
+	SFXGE_RX_SCALE_INITIALIZED,
+	SFXGE_RX_SCALE_STARTED
+} sfxge_rx_scale_state_t;
+
+#define	SFXGE_RX_SCALE_MAX	EFX_RSS_TBL_SIZE
+
+typedef struct sfxge_rx_scale_s {
+	kmutex_t		srs_lock;
+	unsigned int		*srs_cpu;
+#ifdef	_USE_CPU_PHYSID
+	unsigned int		*srs_core;
+	unsigned int		*srs_cache;
+	unsigned int		*srs_chip;
+#endif
+	unsigned int		srs_tbl[SFXGE_RX_SCALE_MAX];
+	unsigned int		srs_count;
+	kstat_t			*srs_ksp;
+	sfxge_rx_scale_state_t	srs_state;
+} sfxge_rx_scale_t;
+
+
+#if defined(_USE_GLD_V2) || defined(_USE_GLD_V3_SOL10)
+typedef struct sfxge_ndd_param_s {
+	sfxge_t		*snp_sp;
+	unsigned int	snp_id;
+	const char	*snp_name;
+	int		(*snp_get)(queue_t *, mblk_t *, caddr_t, cred_t *);
+	int		(*snp_set)(queue_t *, mblk_t *, char *, caddr_t,
+	    cred_t *);
+} sfxge_ndd_param_t;
+
+#endif
+typedef enum sfxge_rx_coalesce_mode_e {
+	SFXGE_RX_COALESCE_OFF = 0,
+	SFXGE_RX_COALESCE_DISALLOW_PUSH = 1,
+	SFXGE_RX_COALESCE_ALLOW_PUSH = 2
+} sfxge_rx_coalesce_mode_t;
+
+typedef enum sfxge_vpd_type_e {
+	SFXGE_VPD_ID = 0,
+	SFXGE_VPD_PN = 1,
+	SFXGE_VPD_SN = 2,
+	SFXGE_VPD_EC = 3,
+	SFXGE_VPD_MN = 4,
+	SFXGE_VPD_VD = 5,
+	SFXGE_VPD_MAX = 6,
+} sfxge_vpd_type_t;
+
+typedef struct sfxge_vpd_kstat_s {
+	kstat_t		*svk_ksp;
+	kstat_named_t	svk_stat[SFXGE_VPD_MAX];
+	efx_vpd_value_t	*svk_vv;
+} sfxge_vpd_kstat_t;
+
+typedef struct sfxge_cfg_kstat_s {
+	struct {
+		kstat_named_t	sck_mac;
+		kstat_named_t	sck_version;
+	} kstat;
+	struct {
+		char		sck_mac[64 + 1];
+	} buf;
+} sfxge_cfg_kstat_t;
+
+typedef enum sfxge_state_e {
+	SFXGE_UNINITIALIZED = 0,
+	SFXGE_INITIALIZED,
+	SFXGE_REGISTERED,
+	SFXGE_STARTING,
+	SFXGE_STARTED,
+	SFXGE_STOPPING
+} sfxge_state_t;
+
+typedef enum sfxge_hw_err_e {
+	SFXGE_HW_OK = 0,
+	SFXGE_HW_ERR,
+} sfxge_hw_err_t;
+
+typedef enum sfxge_action_on_hw_err_e {
+	SFXGE_RECOVER = 0,
+	SFXGE_INVISIBLE = 1,
+	SFXGE_LEAVE_DEAD = 2,
+} sfxge_action_on_hw_err_t;
+
+typedef char *sfxge_mac_priv_prop_t;
+
+struct sfxge_s {
+	kmutex_t			s_state_lock;
+	sfxge_state_t			s_state;
+	dev_info_t			*s_dip;
+	ddi_taskq_t			*s_tqp;
+	ddi_acc_handle_t		s_pci_handle;
+	uint16_t			s_pci_venid;
+	uint16_t			s_pci_devid;
+	efx_family_t			s_family;
+	unsigned int			s_pcie_nlanes;
+	unsigned int 			s_pcie_linkspeed;
+	kmutex_t			s_nic_lock;
+	efsys_bar_t			s_bar;
+	sfxge_intr_t			s_intr;
+	sfxge_mac_t			s_mac;
+	sfxge_mon_t			s_mon;
+	sfxge_sram_t			s_sram;
+	sfxge_mcdi_t			s_mcdi;
+	kmem_cache_t			*s_eq0c; /* eventQ 0 */
+	kmem_cache_t			*s_eqXc; /* all other eventQs */
+	sfxge_evq_t			*s_sep[SFXGE_RX_SCALE_MAX];
+	unsigned int			s_ev_moderation;
+	kmem_cache_t			*s_rqc;
+	sfxge_rxq_t			*s_srp[SFXGE_RX_SCALE_MAX];
+	sfxge_rx_scale_t		s_rx_scale;
+	size_t				s_rx_prefix_size;
+	size_t				s_rx_buffer_size;
+	size_t				s_rx_buffer_align;
+	sfxge_rx_coalesce_mode_t	s_rx_coalesce_mode;
+	int64_t				s_rx_pkt_mem_max;
+	volatile uint64_t		s_rx_pkt_mem_alloc;
+	kmem_cache_t			*s_rpc;
+	kmem_cache_t			*s_tqc;
+	int 				s_tx_qcount;
+	sfxge_txq_t			*s_stp[SFXGE_TXQ_NTYPES +
+	    SFXGE_RX_SCALE_MAX];
+	kmem_cache_t			*s_tpc;
+	int				s_tx_flush_pending;
+	kmutex_t			s_tx_flush_lock;
+	kcondvar_t			s_tx_flush_kv;
+	kmem_cache_t			*s_tbc;
+	kmem_cache_t			*s_tmc;
+	efx_nic_t			*s_enp;
+	sfxge_vpd_kstat_t		s_vpd_kstat;
+	sfxge_cfg_kstat_t		s_cfg_kstat;
+	kstat_t				*s_cfg_ksp;
+	size_t				s_mtu;
+	int				s_rxq_poll_usec;
+#ifdef _USE_GLD_V3
+	mac_callbacks_t			s_mc;
+	mac_handle_t			s_mh;
+#ifdef _USE_MAC_PRIV_PROP
+	sfxge_mac_priv_prop_t		*s_mac_priv_props;
+	int				s_mac_priv_props_alloc;
+#endif
+#endif
+#if defined(_USE_GLD_V2) || defined(_USE_GLD_V3)
+	sfxge_ndd_param_t		*s_ndp;
+	kstat_named_t			*s_nd_stat;
+	caddr_t				s_ndh;
+	kstat_t				*s_nd_ksp;
+#endif
+#ifdef _USE_GLD_V2
+	gld_mac_info_t			*s_gmip;
+	kmutex_t			s_rx_lock;
+	mblk_t				*s_mp;
+	mblk_t				**s_mpp;
+#endif
+	uint32_t			s_num_restarts;
+	uint32_t			s_num_restarts_hw_err;
+	sfxge_hw_err_t			s_hw_err;
+	sfxge_action_on_hw_err_t	s_action_on_hw_err;
+	uint16_t			s_rxq_size;
+	uint16_t			s_evq0_size;
+	uint16_t			s_evqX_size;
+};
+
+typedef struct sfxge_dma_buffer_attr_s {
+	dev_info_t		*sdba_dip;
+	ddi_dma_attr_t		*sdba_dattrp;
+	int			(*sdba_callback) (caddr_t);
+	size_t			sdba_length;
+	uint_t			sdba_memflags;
+	ddi_device_acc_attr_t	*sdba_devaccp;
+	uint_t			sdba_bindflags;
+	int			sdba_maxcookies;
+	boolean_t		sdba_zeroinit;
+} sfxge_dma_buffer_attr_t;
+
+extern const char		sfxge_ident[];
+extern uint8_t			sfxge_brdcst[];
+
+extern kmutex_t			sfxge_global_lock;
+
+extern unsigned int		*sfxge_cpu;
+#ifdef	_USE_CPU_PHYSID
+extern unsigned int		*sfxge_core;
+extern unsigned int		*sfxge_cache;
+extern unsigned int		*sfxge_chip;
+#endif
+
+extern int			sfxge_start(sfxge_t *, boolean_t);
+extern void			sfxge_stop(sfxge_t *);
+extern void			sfxge_ioctl(sfxge_t *, queue_t *, mblk_t *);
+extern int			sfxge_restart_dispatch(sfxge_t *, uint_t,
+    sfxge_hw_err_t, const char *, uint32_t);
+
+extern void			sfxge_gld_link_update(sfxge_t *);
+extern void			sfxge_gld_mtu_update(sfxge_t *);
+extern void			sfxge_gld_rx_post(sfxge_t *, unsigned int,
+    mblk_t *);
+extern void			sfxge_gld_rx_push(sfxge_t *);
+extern int			sfxge_gld_register(sfxge_t *);
+extern int			sfxge_gld_unregister(sfxge_t *);
+
+extern int			sfxge_gld_nd_register(sfxge_t *);
+extern void			sfxge_gld_nd_unregister(sfxge_t *);
+#ifdef _USE_MAC_PRIV_PROP
+extern void			sfxge_gld_priv_prop_rename(sfxge_t *);
+#endif
+
+extern int			sfxge_dma_buffer_create(efsys_mem_t *,
+    const sfxge_dma_buffer_attr_t *);
+extern void			sfxge_dma_buffer_destroy(efsys_mem_t *);
+
+extern int			sfxge_intr_init(sfxge_t *);
+extern int			sfxge_intr_start(sfxge_t *);
+extern void			sfxge_intr_stop(sfxge_t *);
+extern void			sfxge_intr_fini(sfxge_t *);
+extern void			sfxge_intr_fatal(sfxge_t *);
+
+extern int			sfxge_ev_init(sfxge_t *);
+extern int			sfxge_ev_start(sfxge_t *);
+extern void			sfxge_ev_moderation_get(sfxge_t *,
+    unsigned int *);
+extern int			sfxge_ev_moderation_set(sfxge_t *,
+    unsigned int);
+extern int			sfxge_ev_qmoderate(sfxge_t *, unsigned int,
+    unsigned int);
+extern int			sfxge_ev_qpoll(sfxge_t *, unsigned int);
+extern int			sfxge_ev_qprime(sfxge_t *, unsigned int);
+extern void			sfxge_ev_stop(sfxge_t *);
+extern void			sfxge_ev_fini(sfxge_t *);
+
+extern int			sfxge_mon_init(sfxge_t *);
+extern int			sfxge_mon_start(sfxge_t *);
+extern void			sfxge_mon_stop(sfxge_t *);
+extern void			sfxge_mon_fini(sfxge_t *);
+
+extern int			sfxge_mac_init(sfxge_t *);
+extern int			sfxge_mac_start(sfxge_t *, boolean_t);
+extern void			sfxge_mac_stat_get(sfxge_t *, unsigned int,
+    uint64_t *);
+extern void			sfxge_mac_link_check(sfxge_t *, boolean_t *);
+extern void			sfxge_mac_link_speed_get(sfxge_t *,
+    unsigned int *);
+extern void			sfxge_mac_link_duplex_get(sfxge_t *,
+    sfxge_link_duplex_t *);
+extern void			sfxge_mac_fcntl_get(sfxge_t *, unsigned int *);
+extern int			sfxge_mac_fcntl_set(sfxge_t *, unsigned int);
+extern int			sfxge_mac_unicst_get(sfxge_t *,
+    sfxge_unicst_type_t, uint8_t *);
+extern int			sfxge_mac_unicst_set(sfxge_t *,
+    uint8_t *);
+extern int			sfxge_mac_promisc_set(sfxge_t *,
+    sfxge_promisc_type_t);
+extern int			sfxge_mac_multicst_add(sfxge_t *,
+    uint8_t *);
+extern int			sfxge_mac_multicst_remove(sfxge_t *,
+    uint8_t *);
+extern int			sfxge_mac_ioctl(sfxge_t *, sfxge_mac_ioc_t *);
+extern void			sfxge_mac_stop(sfxge_t *);
+extern void			sfxge_mac_fini(sfxge_t *);
+extern void			sfxge_mac_link_update(sfxge_t *sp,
+    efx_link_mode_t mode);
+
+extern int			sfxge_mcdi_init(sfxge_t *sp);
+extern void			sfxge_mcdi_fini(sfxge_t *sp);
+extern int			sfxge_mcdi_ioctl(sfxge_t *sp,
+    sfxge_mcdi_ioc_t *smip);
+
+extern int			sfxge_phy_init(sfxge_t *);
+extern void			sfxge_phy_link_mode_get(sfxge_t *,
+    efx_link_mode_t *);
+extern int			sfxge_phy_ioctl(sfxge_t *, sfxge_phy_ioc_t *);
+extern int			sfxge_phy_bist_ioctl(sfxge_t *,
+    sfxge_phy_bist_ioc_t *);
+extern void			sfxge_phy_fini(sfxge_t *);
+extern int			sfxge_phy_kstat_init(sfxge_t *sp);
+extern void			sfxge_phy_kstat_fini(sfxge_t *sp);
+extern uint8_t			sfxge_phy_lp_cap_test(sfxge_t *sp,
+    uint32_t field);
+extern int			sfxge_phy_cap_apply(sfxge_t *sp,
+    boolean_t use_default);
+extern uint8_t			sfxge_phy_cap_test(sfxge_t *sp, uint32_t flags,
+    uint32_t field, boolean_t *mutablep);
+extern int			sfxge_phy_cap_set(sfxge_t *sp, uint32_t field,
+    int set);
+#ifdef _USE_MAC_PRIV_PROP
+extern int			sfxge_phy_prop_get(sfxge_t *sp, unsigned int id,
+    uint32_t flags, uint32_t *valp);
+extern int			sfxge_phy_prop_set(sfxge_t *sp, unsigned int id,
+    uint32_t val);
+#endif
+
+extern int			sfxge_rx_init(sfxge_t *);
+extern int			sfxge_rx_start(sfxge_t *);
+extern void			sfxge_rx_coalesce_mode_get(sfxge_t *,
+    sfxge_rx_coalesce_mode_t *);
+extern int			sfxge_rx_coalesce_mode_set(sfxge_t *,
+    sfxge_rx_coalesce_mode_t);
+extern unsigned int		sfxge_rx_scale_prop_get(sfxge_t *);
+extern void			sfxge_rx_scale_update(void *);
+extern int			sfxge_rx_scale_count_get(sfxge_t *,
+    unsigned int *);
+extern int			sfxge_rx_scale_count_set(sfxge_t *,
+    unsigned int);
+extern void			sfxge_rx_qcomplete(sfxge_rxq_t *, boolean_t);
+extern void			sfxge_rx_qflush_done(sfxge_rxq_t *);
+extern void			sfxge_rx_qflush_failed(sfxge_rxq_t *);
+extern void			sfxge_rx_qfpp_trim(sfxge_rxq_t *);
+extern int			sfxge_rx_ioctl(sfxge_t *, sfxge_rx_ioc_t *);
+extern void			sfxge_rx_stop(sfxge_t *);
+extern unsigned int 		sfxge_rx_loaned(sfxge_t *);
+extern void			sfxge_rx_fini(sfxge_t *);
+
+extern int			sfxge_tx_init(sfxge_t *);
+extern int			sfxge_tx_start(sfxge_t *);
+extern int			sfxge_tx_packet_add(sfxge_t *, mblk_t *);
+extern void			sfxge_tx_qcomplete(sfxge_txq_t *);
+extern void			sfxge_tx_qflush_done(sfxge_txq_t *);
+extern int			sfxge_tx_ioctl(sfxge_t *, sfxge_tx_ioc_t *);
+extern void			sfxge_tx_stop(sfxge_t *);
+extern void			sfxge_tx_fini(sfxge_t *);
+extern void			sfxge_tx_qdpl_flush(sfxge_txq_t *stp);
+
+extern void			sfxge_sram_init(sfxge_t *);
+extern int			sfxge_sram_buf_tbl_alloc(sfxge_t *, size_t,
+    uint32_t *);
+extern int			sfxge_sram_start(sfxge_t *);
+extern int			sfxge_sram_buf_tbl_set(sfxge_t *, uint32_t,
+    efsys_mem_t *, size_t);
+extern void			sfxge_sram_buf_tbl_clear(sfxge_t *, uint32_t,
+    size_t);
+extern void			sfxge_sram_stop(sfxge_t *);
+extern void			sfxge_sram_buf_tbl_free(sfxge_t *, uint32_t,
+    size_t);
+extern int			sfxge_sram_ioctl(sfxge_t *, sfxge_sram_ioc_t *);
+extern void			sfxge_sram_fini(sfxge_t *);
+
+extern void			sfxge_tcp_parse(mblk_t *,
+    struct ether_header **, struct ip **, struct tcphdr **, size_t *, size_t *);
+
+#define	SFXGE_TCP_HASH(_raddr, _rport, _laddr, _lport, _hash)		\
+	do {								\
+		uint32_t raddr = (uint32_t)(_raddr);			\
+		uint32_t rport = (uint32_t)(_rport);			\
+		uint32_t laddr = (uint32_t)(_laddr);			\
+		uint32_t lport = (uint32_t)(_lport);			\
+		uint32_t key;						\
+		uint32_t lfsr;						\
+		unsigned int index;					\
+									\
+		key = laddr ^						\
+		    ((lport << 16) | (raddr >> 16)) ^			\
+		    ((raddr << 16) | rport);				\
+									\
+		lfsr = 0xffffffff;					\
+		for (index = 0; index < 32; index++) {			\
+			uint32_t input;					\
+			uint32_t key_bit32;				\
+			uint32_t lfsr_bit16;				\
+			uint32_t lfsr_bit3;				\
+									\
+			key_bit32 = key >> 31;				\
+			key <<= 1;					\
+									\
+			lfsr_bit16 = (lfsr >> 15) & 1;			\
+			lfsr_bit3 = (lfsr >> 2) & 1;			\
+									\
+			input = (lfsr_bit16 ^ lfsr_bit3) ^ key_bit32;	\
+			ASSERT((input & ~1) == 0);			\
+									\
+			lfsr = (lfsr << 1) | input;			\
+		}							\
+									\
+		(_hash) = (uint16_t)lfsr;				\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+extern int		sfxge_nvram_ioctl(sfxge_t *, sfxge_nvram_ioc_t *);
+
+extern int		sfxge_pci_init(sfxge_t *);
+extern void		sfxge_pcie_check_link(sfxge_t *, unsigned int,
+    unsigned int);
+extern int		sfxge_pci_ioctl(sfxge_t *, sfxge_pci_ioc_t *);
+extern void		sfxge_pci_fini(sfxge_t *);
+
+extern int		sfxge_bar_init(sfxge_t *);
+extern int		sfxge_bar_ioctl(sfxge_t *, sfxge_bar_ioc_t *);
+extern void		sfxge_bar_fini(sfxge_t *);
+
+extern int		sfxge_vpd_ioctl(sfxge_t *, sfxge_vpd_ioc_t *);
+
+#endif /* _KERNEL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_SFXGE_H */
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_bar.c	2013-08-22 18:57:33.285705274 -0400
@@ -0,0 +1,121 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stream.h>
+#include <sys/dlpi.h>
+
+#include "sfxge.h"
+
+int
+sfxge_bar_init(sfxge_t *sp)
+{
+	efsys_bar_t *esbp = &(sp->s_bar);
+	ddi_device_acc_attr_t devacc;
+	int rc;
+
+	devacc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
+	devacc.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
+	devacc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
+
+	if (ddi_regs_map_setup(sp->s_dip, EFX_MEM_BAR, &(esbp->esb_base), 0, 0,
+	    &devacc, &(esbp->esb_handle)) != DDI_SUCCESS) {
+		rc = ENODEV;
+		goto fail1;
+	}
+
+	mutex_init(&(esbp->esb_lock), NULL, MUTEX_DRIVER, NULL);
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+int
+sfxge_bar_ioctl(sfxge_t *sp, sfxge_bar_ioc_t *sbip)
+{
+	efsys_bar_t *esbp = &(sp->s_bar);
+	efx_oword_t oword;
+	int rc;
+
+	if (!IS_P2ALIGNED(sbip->sbi_addr, sizeof (efx_oword_t))) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	switch (sbip->sbi_op) {
+	case SFXGE_BAR_OP_READ:
+		EFSYS_BAR_READO(esbp, sbip->sbi_addr, &oword, B_TRUE);
+
+		sbip->sbi_data[0] = EFX_OWORD_FIELD(oword, EFX_DWORD_0);
+		sbip->sbi_data[1] = EFX_OWORD_FIELD(oword, EFX_DWORD_1);
+		sbip->sbi_data[2] = EFX_OWORD_FIELD(oword, EFX_DWORD_2);
+		sbip->sbi_data[3] = EFX_OWORD_FIELD(oword, EFX_DWORD_3);
+
+		break;
+
+	case SFXGE_BAR_OP_WRITE:
+		EFX_POPULATE_OWORD_4(oword,
+		    EFX_DWORD_0, sbip->sbi_data[0],
+		    EFX_DWORD_1, sbip->sbi_data[1],
+		    EFX_DWORD_2, sbip->sbi_data[2],
+		    EFX_DWORD_3, sbip->sbi_data[3]);
+
+		EFSYS_BAR_WRITEO(esbp, sbip->sbi_addr, &oword, B_TRUE);
+		break;
+
+	default:
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_bar_fini(sfxge_t *sp)
+{
+	efsys_bar_t *esbp = &(sp->s_bar);
+
+	ddi_regs_map_free(&(esbp->esb_handle));
+
+	mutex_destroy(&(esbp->esb_lock));
+
+	esbp->esb_base = NULL;
+	esbp->esb_handle = NULL;
+}
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_debug.h	2013-08-22 18:57:33.371653160 -0400
@@ -0,0 +1,79 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_SYS_SFXGE_DEBUG_H
+#define	_SYS_SFXGE_DEBUG_H
+
+#include <sys/types.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#ifdef	DEBUG
+
+extern boolean_t sfxge_aask;
+
+#define	SFXGE_OBJ_CHECK(_objp, _type)					\
+	do {								\
+		uint8_t *p = (uint8_t *)(_objp);			\
+		size_t off;						\
+									\
+		for (off = 0; off < sizeof (_type); off++) {		\
+			char buf[MAXNAMELEN];				\
+									\
+			if (*p++ == 0)					\
+				continue;				\
+									\
+			(void) snprintf(buf, MAXNAMELEN - 1,		\
+			    "%s[%d]: non-zero byte found in %s "	\
+			    "at 0x%p+%lx", __FILE__, __LINE__, #_type,	\
+			    (void *)(_objp), off);			\
+									\
+			if (sfxge_aask)					\
+				debug_enter(buf);			\
+			break;						\
+		}							\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+/* Log cmn_err(9F) messages to console and system log */
+#define	SFXGE_CMN_ERR	""
+
+#else	/* DEBUG */
+
+#define	SFXGE_OBJ_CHECK(_objp, _type)
+
+/* Log cmn_err(9F) messages to system log only */
+#define	SFXGE_CMN_ERR	"!"
+
+#endif	/* DEBUG */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_SFXGE_DEBUG_H */
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_dma.c	2013-08-22 18:57:33.457392192 -0400
@@ -0,0 +1,180 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/ddi.h>
+
+#include "sfxge.h"
+#include "efx.h"
+
+static int
+sfxge_dma_buffer_unbind_handle(efsys_mem_t *esmp)
+{
+	int rc;
+
+	esmp->esm_addr = 0;
+	rc = ddi_dma_unbind_handle(esmp->esm_dma_handle);
+	if (rc != DDI_SUCCESS)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_dma_buffer_mem_free(efsys_mem_t *esmp)
+{
+	esmp->esm_base = NULL;
+	ddi_dma_mem_free(&(esmp->esm_acc_handle));
+	esmp->esm_acc_handle = NULL;
+}
+
+static void
+sfxge_dma_buffer_handle_free(ddi_dma_handle_t *dhandlep)
+{
+	ddi_dma_free_handle(dhandlep);
+	*dhandlep = NULL;
+}
+
+int
+sfxge_dma_buffer_create(efsys_mem_t *esmp, const sfxge_dma_buffer_attr_t *sdbap)
+{
+	int err;
+	int rc;
+	size_t unit;
+	ddi_dma_cookie_t dmac;
+	unsigned int ncookies;
+
+	/* Allocate a DMA handle */
+	err = ddi_dma_alloc_handle(sdbap->sdba_dip, sdbap->sdba_dattrp,
+	    sdbap->sdba_callback, NULL, &(esmp->esm_dma_handle));
+	switch (err) {
+	case DDI_SUCCESS:
+		break;
+
+	case DDI_DMA_BADATTR:
+		rc = EINVAL;
+		goto fail1;
+
+	case DDI_DMA_NORESOURCES:
+		rc = ENOMEM;
+		goto fail1;
+
+	default:
+		rc = EFAULT;
+		goto fail1;
+	}
+
+	/* Allocate some DMA memory */
+	err = ddi_dma_mem_alloc(esmp->esm_dma_handle, sdbap->sdba_length,
+	    sdbap->sdba_devaccp, sdbap->sdba_memflags,
+	    sdbap->sdba_callback, NULL,
+	    &(esmp->esm_base), &unit, &(esmp->esm_acc_handle));
+	switch (err) {
+	case DDI_SUCCESS:
+		break;
+
+	case DDI_FAILURE:
+		/*FALLTHRU*/
+	default:
+		rc = EFAULT;
+		goto fail2;
+	}
+
+	if (sdbap->sdba_zeroinit)
+		bzero(esmp->esm_base, sdbap->sdba_length);
+
+	/* Bind the DMA memory to the DMA handle */
+	/* We aren't handling partial mappings */
+	ASSERT3U(sdbap->sdba_bindflags & DDI_DMA_PARTIAL, !=, DDI_DMA_PARTIAL);
+	err = ddi_dma_addr_bind_handle(esmp->esm_dma_handle, NULL,
+	    esmp->esm_base, sdbap->sdba_length, sdbap->sdba_bindflags,
+	    sdbap->sdba_callback, NULL, &dmac, &ncookies);
+	switch (err) {
+	case DDI_DMA_MAPPED:
+		break;
+
+	case DDI_DMA_INUSE:
+		rc = EEXIST;
+		goto fail3;
+
+	case DDI_DMA_NORESOURCES:
+		rc = ENOMEM;
+		goto fail3;
+
+	case DDI_DMA_NOMAPPING:
+		rc = ENOTSUP;
+		goto fail3;
+
+	case DDI_DMA_TOOBIG:
+		rc = EFBIG;
+		goto fail3;
+
+	default:
+		rc = EFAULT;
+		goto fail3;
+	}
+	ASSERT3U(ncookies, >=, 1);
+	ASSERT3U(ncookies, <=, sdbap->sdba_maxcookies);
+
+	esmp->esm_addr = dmac.dmac_laddress;
+	DTRACE_PROBE1(addr, efsys_dma_addr_t, esmp->esm_addr);
+
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	sfxge_dma_buffer_mem_free(esmp);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	sfxge_dma_buffer_handle_free(&(esmp->esm_dma_handle));
+	esmp->esm_dma_handle = NULL;
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (-1);
+}
+
+void
+sfxge_dma_buffer_destroy(efsys_mem_t *esmp)
+{
+	int rc;
+
+	rc = sfxge_dma_buffer_unbind_handle(esmp);
+	if (rc != 0) {
+		cmn_err(CE_WARN, SFXGE_CMN_ERR "ERROR: DMA Unbind failed rc=%d",
+		    rc);
+	}
+	sfxge_dma_buffer_mem_free(esmp);
+	sfxge_dma_buffer_handle_free(&(esmp->esm_dma_handle));
+}
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_err.c	2013-08-22 18:57:33.549201593 -0400
@@ -0,0 +1,85 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+
+#include "sfxge.h"
+
+#include "efx.h"
+
+static const char *__sfxge_err[] = {
+	"",
+	"SRAM out-of-bounds",
+	"Buffer ID out-of-bounds",
+	"Internal memory parity",
+	"Receive buffer ownership",
+	"Transmit buffer ownership",
+	"Receive descriptor ownership",
+	"Transmit descriptor ownership",
+	"Event queue ownership",
+	"Event queue FIFO overflow",
+	"Illegal address",
+	"SRAM parity"
+};
+
+void
+sfxge_err(efsys_identifier_t *arg, unsigned int code, uint32_t dword0,
+    uint32_t dword1)
+{
+	sfxge_t *sp = (sfxge_t *)arg;
+	dev_info_t *dip = sp->s_dip;
+
+	ASSERT3U(code, <, EFX_ERR_NCODES);
+
+	cmn_err(CE_WARN, SFXGE_CMN_ERR "[%s%d] FATAL ERROR: %s (0x%08x%08x)",
+	    ddi_driver_name(dip), ddi_get_instance(dip), __sfxge_err[code],
+	    dword1, dword0);
+}
+
+void
+sfxge_intr_fatal(sfxge_t *sp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	int err;
+
+	efx_intr_disable(enp);
+	efx_intr_fatal(enp);
+
+	err = sfxge_restart_dispatch(sp, DDI_NOSLEEP, SFXGE_HW_ERR,
+	    "Fatal Interrupt", 0);
+	if (err != 0) {
+		cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] UNRECOVERABLE ERROR:"
+			    " Could not schedule driver restart."
+			    " err=%d\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip),
+			    err);
+		ASSERT(B_FALSE);
+	}
+}
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_ev.c	2013-08-22 18:57:33.636241881 -0400
@@ -0,0 +1,1218 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/cpu.h>
+#include <sys/pghw.h>
+
+#include "sfxge.h"
+
+#include "efx.h"
+
+
+/* Event queue DMA attributes */
+static ddi_device_acc_attr_t sfxge_evq_devacc = {
+
+	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
+	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
+	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
+};
+
+static ddi_dma_attr_t sfxge_evq_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	EFX_BUF_SIZE,		/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	1,			/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+static int
+_sfxge_ev_qctor(sfxge_t *sp, sfxge_evq_t *sep, int kmflags, uint16_t evq_size)
+{
+	efsys_mem_t *esmp = &(sep->se_mem);
+	sfxge_dma_buffer_attr_t dma_attr;
+	int rc;
+
+	/* Compile-time structure layout checks */
+	EFX_STATIC_ASSERT(sizeof (sep->__se_u1.__se_s1) <=
+	    sizeof (sep->__se_u1.__se_pad));
+	EFX_STATIC_ASSERT(sizeof (sep->__se_u2.__se_s2) <=
+	    sizeof (sep->__se_u2.__se_pad));
+
+	bzero(sep, sizeof (sfxge_evq_t));
+
+	sep->se_sp = sp;
+
+	dma_attr.sdba_dip	 = sp->s_dip;
+	dma_attr.sdba_dattrp	 = &sfxge_evq_dma_attr;
+	dma_attr.sdba_callback	 = (kmflags == KM_SLEEP) ?
+	    DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
+	dma_attr.sdba_length	 = EFX_EVQ_SIZE(evq_size);
+	dma_attr.sdba_memflags	 = DDI_DMA_CONSISTENT;
+	dma_attr.sdba_devaccp	 = &sfxge_evq_devacc;
+	dma_attr.sdba_bindflags	 = DDI_DMA_READ | DDI_DMA_CONSISTENT;
+	dma_attr.sdba_maxcookies = 1;
+	dma_attr.sdba_zeroinit	 = B_FALSE;
+
+	if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
+		goto fail1;
+
+	/* Allocate some buffer table entries */
+	if ((rc = sfxge_sram_buf_tbl_alloc(sp, EFX_EVQ_NBUFS(evq_size),
+	    &(sep->se_id))) != 0)
+		goto fail2;
+
+	sep->se_stpp = &(sep->se_stp);
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Tear down DMA setup */
+	esmp->esm_addr = 0;
+	sfxge_dma_buffer_destroy(esmp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	sep->se_sp = NULL;
+
+	SFXGE_OBJ_CHECK(sep, sfxge_evq_t);
+
+	return (-1);
+}
+
+static int
+sfxge_ev_q0ctor(void *buf, void *arg, int kmflags)
+{
+	sfxge_evq_t *sep = buf;
+	sfxge_t *sp = arg;
+	return (_sfxge_ev_qctor(sp, sep, kmflags, sp->s_evq0_size));
+}
+
+static int
+sfxge_ev_qXctor(void *buf, void *arg, int kmflags)
+{
+	sfxge_evq_t *sep = buf;
+	sfxge_t *sp = arg;
+	return (_sfxge_ev_qctor(sp, sep, kmflags, sp->s_evqX_size));
+}
+static void
+_sfxge_ev_qdtor(sfxge_t *sp, sfxge_evq_t *sep, uint16_t evq_size)
+{
+	efsys_mem_t *esmp = &(sep->se_mem);
+	ASSERT3P(sep->se_sp, ==, sp);
+	ASSERT3P(sep->se_stpp, ==, &(sep->se_stp));
+	sep->se_stpp = NULL;
+
+	/* Free the buffer table entries */
+	sfxge_sram_buf_tbl_free(sp, sep->se_id, EFX_EVQ_NBUFS(evq_size));
+	sep->se_id = 0;
+
+	/* Tear down DMA setup */
+	sfxge_dma_buffer_destroy(esmp);
+
+	sep->se_sp = NULL;
+
+	SFXGE_OBJ_CHECK(sep, sfxge_evq_t);
+}
+
+static void
+sfxge_ev_q0dtor(void *buf, void *arg)
+{
+	sfxge_evq_t *sep = buf;
+	sfxge_t *sp = arg;
+	_sfxge_ev_qdtor(sp, sep, sp->s_evq0_size);
+}
+
+static void
+sfxge_ev_qXdtor(void *buf, void *arg)
+{
+	sfxge_evq_t *sep = buf;
+	sfxge_t *sp = arg;
+	_sfxge_ev_qdtor(sp, sep, sp->s_evqX_size);
+}
+
+static boolean_t
+sfxge_ev_initialized(void *arg)
+{
+	sfxge_evq_t *sep = arg;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTING);
+	sep->se_state = SFXGE_EVQ_STARTED;
+
+	cv_broadcast(&(sep->se_init_kv));
+
+	return (B_FALSE);
+}
+
+static void
+sfxge_ev_qcomplete(sfxge_evq_t *sep, boolean_t eop)
+{
+	sfxge_t *sp = sep->se_sp;
+	unsigned int index = sep->se_index;
+	sfxge_rxq_t *srp = sp->s_srp[index];
+	sfxge_txq_t *stp;
+
+	if ((stp = sep->se_stp) != NULL) {
+		sep->se_stp = NULL;
+		sep->se_stpp = &(sep->se_stp);
+
+		do {
+			sfxge_txq_t *next;
+
+			next = stp->st_next;
+			stp->st_next = NULL;
+
+			ASSERT3U(stp->st_evq, ==, index);
+
+			if (stp->st_pending != stp->st_completed)
+				sfxge_tx_qcomplete(stp);
+
+			stp = next;
+		} while (stp != NULL);
+	}
+
+	if (srp != NULL) {
+		if (srp->sr_pending != srp->sr_completed)
+			sfxge_rx_qcomplete(srp, eop);
+	}
+}
+
+static boolean_t
+sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size,
+    uint16_t flags)
+{
+	sfxge_evq_t *sep = arg;
+	sfxge_t *sp = sep->se_sp;
+	sfxge_rxq_t *srp;
+	sfxge_rx_packet_t *srpp;
+	unsigned int expected;
+	unsigned int prefetch;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	if (sep->se_exception)
+		goto done;
+
+	srp = sp->s_srp[label];
+	if (srp == NULL)
+		goto done;
+
+	ASSERT3U(sep->se_index, ==, srp->sr_index);
+	ASSERT3U(id, <, sp->s_rxq_size);
+
+	/*
+	 * Note that in sfxge_stop() EVQ stopped after RXQ, and will be reset
+	 * So the return missing srp->sr_pending++ is safe
+	 */
+	if (srp->sr_state != SFXGE_RXQ_STARTED)
+		goto done;
+
+	expected = srp->sr_pending++ & (sp->s_rxq_size - 1);
+	if (id != expected) {
+		sep->se_exception = B_TRUE;
+
+		DTRACE_PROBE(restart_ev_rx_id);
+		/* sfxge_evq_t->se_lock held */
+		(void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_ERR,
+		    "Out of order RX event", id - expected);
+
+		goto done;
+	}
+
+	prefetch = (id + 4) & (sp->s_rxq_size - 1);
+	if ((srpp = srp->sr_srpp[prefetch]) != NULL)
+		prefetch_read_many(srpp);
+
+	srpp = srp->sr_srpp[id];
+	ASSERT(srpp != NULL);
+
+	ASSERT3U(srpp->srp_flags, ==, EFX_DISCARD);
+	srpp->srp_flags = flags;
+
+	ASSERT3U(size, <, (1 << 16));
+	srpp->srp_size = (uint16_t)size;
+
+	prefetch_read_many(srpp->srp_mp);
+
+	sep->se_rx++;
+
+	DTRACE_PROBE2(qlevel, unsigned int, srp->sr_index,
+	    unsigned int, srp->sr_added - srp->sr_pending);
+
+	if (srp->sr_pending - srp->sr_completed >= SFXGE_RX_BATCH)
+		sfxge_ev_qcomplete(sep, B_FALSE);
+
+done:
+	/* returning B_TRUE makes efx_ev_qpoll() stop processing events */
+	return (sep->se_rx >= sep->se_ev_batch);
+}
+
+static boolean_t
+sfxge_ev_exception(void *arg, uint32_t code, uint32_t data)
+{
+	sfxge_evq_t *sep = arg;
+	sfxge_t *sp = sep->se_sp;
+
+	_NOTE(ARGUNUSED(code))
+	_NOTE(ARGUNUSED(data))
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+	sep->se_exception = B_TRUE;
+
+	if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) {
+
+		DTRACE_PROBE(restart_ev_exception);
+
+		/* sfxge_evq_t->se_lock held */
+		(void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_ERR,
+		    "Unknown EV", code);
+	}
+
+	return (B_FALSE);
+}
+
+static boolean_t
+sfxge_ev_rxq_flush_done(void *arg, uint32_t label)
+{
+	sfxge_evq_t *sep_targetq, *sep = arg;
+	sfxge_t *sp = sep->se_sp;
+	sfxge_rxq_t *srp;
+	unsigned int index;
+	uint16_t magic;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	/* Ensure RXQ exists, as events may arrive after RXQ was destroyed */
+	srp = sp->s_srp[label];
+	if (srp == NULL)
+		goto done;
+
+	/* Resend a software event on the correct queue */
+	index = srp->sr_index;
+	sep_targetq = sp->s_sep[index];
+
+	if (sep_targetq->se_state != SFXGE_EVQ_STARTED)
+		goto done; /* TBD: state test not under the lock */
+
+	ASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label);
+	magic = SFXGE_MAGIC_RX_QFLUSH_DONE | label;
+
+	efx_ev_qpost(sep_targetq->se_eep, magic);
+
+done:
+	return (B_FALSE);
+}
+
+static boolean_t
+sfxge_ev_rxq_flush_failed(void *arg, uint32_t label)
+{
+	sfxge_evq_t *sep_targetq, *sep = arg;
+	sfxge_t *sp = sep->se_sp;
+	sfxge_rxq_t *srp;
+	unsigned int index;
+	uint16_t magic;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	/* Ensure RXQ exists, as events may arrive after RXQ was destroyed */
+	srp = sp->s_srp[label];
+	if (srp == NULL)
+		goto done;
+
+	/* Resend a software event on the correct queue */
+	index = srp->sr_index;
+	sep_targetq = sp->s_sep[index];
+
+	ASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label);
+	magic = SFXGE_MAGIC_RX_QFLUSH_FAILED | label;
+
+	if (sep_targetq->se_state != SFXGE_EVQ_STARTED)
+		goto done; /* TBD: state test not under the lock */
+
+	efx_ev_qpost(sep_targetq->se_eep, magic);
+
+done:
+	return (B_FALSE);
+}
+
+static boolean_t
+sfxge_ev_tx(void *arg, uint32_t label, uint32_t id)
+{
+	sfxge_evq_t *sep = arg;
+	sfxge_t *sp = sep->se_sp;
+	sfxge_txq_t *stp;
+	unsigned int stop;
+	unsigned int delta;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	stp = sp->s_stp[label];
+	if (stp == NULL)
+		goto done;
+
+	if (stp->st_state != SFXGE_TXQ_STARTED)
+		goto done;
+
+	ASSERT3U(sep->se_index, ==, stp->st_evq);
+
+	stop = (id + 1) & (SFXGE_NDESCS - 1);
+	id = stp->st_pending & (SFXGE_NDESCS - 1);
+
+	delta = (stop >= id) ? (stop - id) : (SFXGE_NDESCS - id + stop);
+	stp->st_pending += delta;
+
+	sep->se_tx++;
+
+	if (stp->st_next == NULL &&
+	    sep->se_stpp != &(stp->st_next)) {
+		*(sep->se_stpp) = stp;
+		sep->se_stpp = &(stp->st_next);
+	}
+
+	DTRACE_PROBE2(qlevel, unsigned int, stp->st_index,
+	    unsigned int, stp->st_added - stp->st_pending);
+
+	if (stp->st_pending - stp->st_completed >= SFXGE_TX_BATCH)
+		sfxge_tx_qcomplete(stp);
+
+done:
+	/* returning B_TRUE makes efx_ev_qpoll() stop processing events */
+	return (sep->se_tx >= sep->se_ev_batch);
+}
+
+static boolean_t
+sfxge_ev_txq_flush_done(void *arg, uint32_t label)
+{
+	sfxge_evq_t *sep = arg;
+	sfxge_t *sp = sep->se_sp;
+	sfxge_txq_t *stp;
+	unsigned int evq;
+	uint16_t magic;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	/* Ensure TXQ exists, as events may arrive after TXQ was destroyed */
+	stp = sp->s_stp[label];
+	if (stp == NULL)
+		goto done;
+
+	ASSERT3U(stp->st_state, ==, SFXGE_TXQ_INITIALIZED);
+
+	/* Resend a software event on the correct queue */
+	evq = stp->st_evq;
+	sep = sp->s_sep[evq];
+
+	ASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label);
+	magic = SFXGE_MAGIC_TX_QFLUSH_DONE | label;
+
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
+	efx_ev_qpost(sep->se_eep, magic);
+
+done:
+	return (B_FALSE);
+}
+
+static boolean_t
+sfxge_ev_software(void *arg, uint16_t magic)
+{
+	sfxge_evq_t *sep = arg;
+	sfxge_t *sp = sep->se_sp;
+	dev_info_t *dip = sp->s_dip;
+	unsigned int label;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	EFX_STATIC_ASSERT(SFXGE_MAGIC_DMAQ_LABEL_WIDTH ==
+	    FSF_AZ_RX_EV_Q_LABEL_WIDTH);
+	EFX_STATIC_ASSERT(SFXGE_MAGIC_DMAQ_LABEL_WIDTH ==
+	    FSF_AZ_TX_EV_Q_LABEL_WIDTH);
+
+	label = magic & SFXGE_MAGIC_DMAQ_LABEL_MASK;
+	magic &= ~SFXGE_MAGIC_DMAQ_LABEL_MASK;
+
+	switch (magic) {
+	case SFXGE_MAGIC_RX_QFLUSH_DONE: {
+		sfxge_rxq_t *srp = sp->s_srp[label];
+
+		if (srp != NULL) {
+			ASSERT3U(sep->se_index, ==, srp->sr_index);
+
+			sfxge_rx_qflush_done(srp);
+		}
+		break;
+	}
+	case SFXGE_MAGIC_RX_QFLUSH_FAILED: {
+		sfxge_rxq_t *srp = sp->s_srp[label];
+
+		if (srp != NULL) {
+			ASSERT3U(sep->se_index, ==, srp->sr_index);
+
+			sfxge_rx_qflush_failed(srp);
+		}
+		break;
+	}
+	case SFXGE_MAGIC_RX_QFPP_TRIM: {
+		sfxge_rxq_t *srp = sp->s_srp[label];
+
+		if (srp != NULL) {
+			ASSERT3U(sep->se_index, ==, srp->sr_index);
+
+			sfxge_rx_qfpp_trim(srp);
+		}
+		break;
+	}
+	case SFXGE_MAGIC_TX_QFLUSH_DONE: {
+		sfxge_txq_t *stp = sp->s_stp[label];
+
+		if (stp != NULL) {
+			ASSERT3U(sep->se_index, ==, stp->st_evq);
+
+			sfxge_tx_qflush_done(stp);
+		}
+		break;
+	}
+	default:
+		cmn_err(CE_NOTE,
+			SFXGE_CMN_ERR "[%s%d] unknown software event 0x%x",
+			ddi_driver_name(dip), ddi_get_instance(dip), magic);
+		break;
+	}
+
+	return (B_FALSE);
+}
+
+static boolean_t
+sfxge_ev_sram(void *arg, uint32_t code)
+{
+	_NOTE(ARGUNUSED(arg))
+
+	switch (code) {
+	case EFX_SRAM_UPDATE:
+		DTRACE_PROBE(sram_update);
+		break;
+
+	case EFX_SRAM_CLEAR:
+		DTRACE_PROBE(sram_clear);
+		break;
+
+	case EFX_SRAM_ILLEGAL_CLEAR:
+		DTRACE_PROBE(sram_illegal_clear);
+		break;
+
+	default:
+		ASSERT(B_FALSE);
+		break;
+	}
+
+	return (B_FALSE);
+}
+
+static boolean_t
+sfxge_ev_timer(void *arg, uint32_t index)
+{
+	_NOTE(ARGUNUSED(arg, index))
+
+	return (B_FALSE);
+}
+
+static boolean_t
+sfxge_ev_wake_up(void *arg, uint32_t index)
+{
+	_NOTE(ARGUNUSED(arg, index))
+
+	return (B_FALSE);
+}
+
+static boolean_t
+sfxge_ev_monitor(void *arg, efx_mon_stat_t id, efx_mon_stat_value_t value)
+{
+	_NOTE(ARGUNUSED(arg, id, value))
+
+	return (B_FALSE);
+}
+
+static boolean_t
+sfxge_ev_link_change(void *arg, efx_link_mode_t	link_mode)
+{
+	sfxge_evq_t *sep = arg;
+	sfxge_t *sp = sep->se_sp;
+
+	sfxge_mac_link_update(sp, link_mode);
+
+	return (B_FALSE);
+}
+
+static int
+sfxge_ev_kstat_update(kstat_t *ksp, int rw)
+{
+	sfxge_evq_t *sep = ksp->ks_private;
+	kstat_named_t *knp;
+	int rc;
+
+	if (rw != KSTAT_READ) {
+		rc = EACCES;
+		goto fail1;
+	}
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	if (sep->se_state != SFXGE_EVQ_STARTED)
+		goto done;
+
+	efx_ev_qstats_update(sep->se_eep, sep->se_stat);
+
+	knp = ksp->ks_data;
+	knp += EV_NQSTATS;
+
+	knp->value.ui64 = sep->se_cpu_id;
+
+done:
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_ev_kstat_init(sfxge_evq_t *sep)
+{
+	sfxge_t *sp = sep->se_sp;
+	unsigned int index = sep->se_index;
+	dev_info_t *dip = sp->s_dip;
+	kstat_t *ksp;
+	kstat_named_t *knp;
+	char name[MAXNAMELEN];
+	unsigned int id;
+	int rc;
+
+	/* Determine the name */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_evq%04d",
+	    ddi_driver_name(dip), index);
+
+	/* Create the set */
+	if ((ksp = kstat_create((char *)ddi_driver_name(dip),
+	    ddi_get_instance(dip), name, "queue", KSTAT_TYPE_NAMED,
+	    EV_NQSTATS + 1, 0)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	sep->se_ksp = ksp;
+
+	ksp->ks_update = sfxge_ev_kstat_update;
+	ksp->ks_private = sep;
+	ksp->ks_lock = &(sep->se_lock);
+
+	/* Initialise the named stats */
+	sep->se_stat = knp = ksp->ks_data;
+	for (id = 0; id < EV_NQSTATS; id++) {
+		kstat_named_init(knp, (char *)efx_ev_qstat_name(sp->s_enp, id),
+		    KSTAT_DATA_UINT64);
+		knp++;
+	}
+
+	kstat_named_init(knp, "cpu", KSTAT_DATA_UINT64);
+
+	kstat_install(ksp);
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_ev_kstat_fini(sfxge_evq_t *sep)
+{
+	/* Destroy the set */
+	kstat_delete(sep->se_ksp);
+	sep->se_ksp = NULL;
+	sep->se_stat = NULL;
+}
+
+inline unsigned pow2_ge(unsigned int n) {
+	unsigned int order = 0;
+	ASSERT3U(n, >, 0);
+	while ((1ul << order) < n) ++order;
+	return (1ul << (order));
+}
+
+static int
+sfxge_ev_qinit(sfxge_t *sp, unsigned int index, unsigned int ev_batch)
+{
+	sfxge_evq_t *sep;
+	int rc;
+
+	ASSERT3U(index, <, SFXGE_RX_SCALE_MAX);
+
+	sep = kmem_cache_alloc(index ? sp->s_eqXc : sp->s_eq0c, KM_SLEEP);
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_UNINITIALIZED);
+
+	sep->se_index = index;
+
+	mutex_init(&(sep->se_lock), NULL,
+	    MUTEX_DRIVER, DDI_INTR_PRI(sp->s_intr.si_intr_pri));
+
+	cv_init(&(sep->se_init_kv), NULL, CV_DRIVER, NULL);
+
+	/* Initialize the statistics */
+	if ((rc = sfxge_ev_kstat_init(sep)) != 0)
+		goto fail1;
+
+	sep->se_state = SFXGE_EVQ_INITIALIZED;
+	sep->se_ev_batch = ev_batch;
+	sp->s_sep[index] = sep;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	sep->se_index = 0;
+
+	cv_destroy(&(sep->se_init_kv));
+	mutex_destroy(&(sep->se_lock));
+
+	kmem_cache_free(index ? sp->s_eqXc : sp->s_eq0c, sep);
+
+	return (rc);
+}
+
+static int
+sfxge_ev_qstart(sfxge_t *sp, unsigned int index)
+{
+	sfxge_evq_t *sep = sp->s_sep[index];
+	sfxge_intr_t *sip = &(sp->s_intr);
+	efx_nic_t *enp = sp->s_enp;
+	efx_ev_callbacks_t *eecp;
+	efsys_mem_t *esmp;
+	clock_t timeout;
+	int rc;
+	uint16_t evq_size = index ? sp->s_evqX_size : sp->s_evq0_size;
+
+	mutex_enter(&(sep->se_lock));
+	esmp = &(sep->se_mem);
+
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_INITIALIZED);
+
+	/* Set the memory to all ones */
+	(void) memset(esmp->esm_base, 0xff, EFX_EVQ_SIZE(evq_size));
+
+	/* Program the buffer table */
+	if ((rc = sfxge_sram_buf_tbl_set(sp, sep->se_id, esmp,
+	    EFX_EVQ_NBUFS(evq_size))) != 0)
+		goto fail1;
+
+	/* Set up the event callbacks */
+	eecp = &(sep->se_eec);
+	eecp->eec_initialized = sfxge_ev_initialized;
+	eecp->eec_rx = sfxge_ev_rx;
+	eecp->eec_tx = sfxge_ev_tx;
+	eecp->eec_exception = sfxge_ev_exception;
+	eecp->eec_rxq_flush_done = sfxge_ev_rxq_flush_done;
+	eecp->eec_rxq_flush_failed = sfxge_ev_rxq_flush_failed;
+	eecp->eec_txq_flush_done = sfxge_ev_txq_flush_done;
+	eecp->eec_software = sfxge_ev_software;
+	eecp->eec_sram = sfxge_ev_sram;
+	eecp->eec_wake_up = sfxge_ev_wake_up;
+	eecp->eec_timer = sfxge_ev_timer;
+	eecp->eec_link_change = sfxge_ev_link_change;
+	eecp->eec_monitor = sfxge_ev_monitor;
+
+	/* Create the event queue */
+	if ((rc = efx_ev_qcreate(enp, index, esmp, evq_size, sep->se_id,
+	    &(sep->se_eep))) != 0)
+		goto fail2;
+
+	/* Set the default moderation */
+	if ((rc = efx_ev_qmoderate(sep->se_eep, sp->s_ev_moderation)) != 0)
+		goto fail3;
+
+	/* Check that interrupts are enabled at the NIC */
+	if (sip->si_state != SFXGE_INTR_STARTED) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	sep->se_state = SFXGE_EVQ_STARTING;
+
+	/* Prime the event queue for interrupts */
+	if ((rc = efx_ev_qprime(sep->se_eep, sep->se_count)) != 0)
+		goto fail5;
+
+	/* Wait for the initialization event */
+	timeout = ddi_get_lbolt() + drv_usectohz(2000000);
+	while (sep->se_state != SFXGE_EVQ_STARTED) {
+		if (cv_timedwait(&(sep->se_init_kv), &(sep->se_lock),
+			timeout) < 0) {
+			/* Timeout waiting for initialization */
+			dev_info_t *dip = sp->s_dip;
+
+			DTRACE_PROBE(timeout);
+			cmn_err(CE_NOTE,
+			    SFXGE_CMN_ERR "[%s%d] ev qstart timeout",
+			    ddi_driver_name(dip), ddi_get_instance(dip));
+			rc = ETIMEDOUT;
+			goto fail6;
+		}
+	}
+
+	mutex_exit(&(sep->se_lock));
+	return (0);
+
+fail6:
+	DTRACE_PROBE(fail6);
+
+fail5:
+	DTRACE_PROBE(fail5);
+
+	sep->se_state = SFXGE_EVQ_INITIALIZED;
+
+fail4:
+	DTRACE_PROBE(fail4);
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	/* Destroy the event queue */
+	efx_ev_qdestroy(sep->se_eep);
+	sep->se_eep = NULL;
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Zero out the event handlers */
+	bzero(&(sep->se_eec), sizeof (efx_ev_callbacks_t));
+
+	/* Clear entries from the buffer table */
+	sfxge_sram_buf_tbl_clear(sp, sep->se_id, EFX_EVQ_NBUFS(evq_size));
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(sep->se_lock));
+
+	return (rc);
+}
+
+int
+sfxge_ev_qpoll(sfxge_t *sp, unsigned int index)
+{
+	sfxge_evq_t *sep = sp->s_sep[index];
+	processorid_t cpu_id;
+	int rc;
+	uint16_t evq_size = index ? sp->s_evqX_size : sp->s_evq0_size;
+
+	mutex_enter(&(sep->se_lock));
+
+	if (sep->se_state != SFXGE_EVQ_STARTING &&
+	    sep->se_state != SFXGE_EVQ_STARTED) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	/* Make sure the CPU information is up to date */
+	cpu_id = CPU->cpu_id;
+
+	if (cpu_id != sep->se_cpu_id) {
+#ifdef	_USE_CPU_PHYSID
+		cpu_physid_t *cpp = CPU->cpu_physid;
+#endif
+
+		sep->se_cpu_id = cpu_id;
+
+#ifdef	_USE_CPU_PHYSID
+		sep->se_core_id = cpp->cpu_coreid;
+		sep->se_cache_id = cpp->cpu_cacheid;
+		sep->se_chip_id = cpp->cpu_chipid;
+#endif
+
+		/* sfxge_evq_t->se_lock held */
+		(void) ddi_taskq_dispatch(sp->s_tqp, sfxge_rx_scale_update, sp,
+		    DDI_NOSLEEP);
+	}
+
+	/* Synchronize the DMA memory for reading */
+	(void) ddi_dma_sync(sep->se_mem.esm_dma_handle,
+	    0,
+	    EFX_EVQ_SIZE(evq_size),
+	    DDI_DMA_SYNC_FORKERNEL);
+
+	ASSERT3U(sep->se_rx, ==, 0);
+	ASSERT3U(sep->se_tx, ==, 0);
+	ASSERT3P(sep->se_stp, ==, NULL);
+	ASSERT3P(sep->se_stpp, ==, &(sep->se_stp));
+
+	/* Poll the queue */
+	efx_ev_qpoll(sep->se_eep, &(sep->se_count), &(sep->se_eec),
+	    sep);
+
+	sep->se_rx = 0;
+	sep->se_tx = 0;
+
+	/* Perform any pending completion processing */
+	sfxge_ev_qcomplete(sep, B_TRUE);
+
+	/* Re-prime the event queue for interrupts */
+	if ((rc = efx_ev_qprime(sep->se_eep, sep->se_count)) != 0)
+		goto fail2;
+
+	mutex_exit(&(sep->se_lock));
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(sep->se_lock));
+
+	return (rc);
+}
+
+int
+sfxge_ev_qprime(sfxge_t *sp, unsigned int index)
+{
+	sfxge_evq_t *sep = sp->s_sep[index];
+	int rc;
+
+	mutex_enter(&(sep->se_lock));
+
+	if (sep->se_state != SFXGE_EVQ_STARTING &&
+	    sep->se_state != SFXGE_EVQ_STARTED) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if ((rc = efx_ev_qprime(sep->se_eep, sep->se_count)) != 0)
+		goto fail2;
+
+	mutex_exit(&(sep->se_lock));
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(sep->se_lock));
+
+	return (rc);
+}
+
+
+int
+sfxge_ev_qmoderate(sfxge_t *sp, unsigned int index, unsigned int us)
+{
+	sfxge_evq_t *sep = sp->s_sep[index];
+	efx_evq_t *eep = sep->se_eep;
+
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
+
+	return (efx_ev_qmoderate(eep, us));
+}
+
+static void
+sfxge_ev_qstop(sfxge_t *sp, unsigned int index)
+{
+	sfxge_evq_t *sep = sp->s_sep[index];
+	uint16_t evq_size;
+
+	mutex_enter(&(sep->se_lock));
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
+	sep->se_state = SFXGE_EVQ_INITIALIZED;
+	evq_size = index ? sp->s_evqX_size : sp->s_evq0_size;
+
+	/* Clear the CPU information */
+#ifdef	_USE_CPU_PHYSID
+	sep->se_cache_id = 0;
+	sep->se_core_id = 0;
+	sep->se_chip_id = 0;
+#endif
+
+	sep->se_cpu_id = 0;
+
+	/* Clear the event count */
+	sep->se_count = 0;
+
+	/* Reset the exception flag */
+	sep->se_exception = B_FALSE;
+
+	/* Destroy the event queue */
+	efx_ev_qdestroy(sep->se_eep);
+	sep->se_eep = NULL;
+
+	mutex_exit(&(sep->se_lock));
+
+	/* Zero out the event handlers */
+	bzero(&(sep->se_eec), sizeof (efx_ev_callbacks_t));
+
+	/* Clear entries from the buffer table */
+	sfxge_sram_buf_tbl_clear(sp, sep->se_id, EFX_EVQ_NBUFS(evq_size));
+}
+
+static void
+sfxge_ev_qfini(sfxge_t *sp, unsigned int index)
+{
+	sfxge_evq_t *sep = sp->s_sep[index];
+
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_INITIALIZED);
+
+	sp->s_sep[index] = NULL;
+	sep->se_state = SFXGE_EVQ_UNINITIALIZED;
+
+	/* Tear down the statistics */
+	sfxge_ev_kstat_fini(sep);
+
+	cv_destroy(&(sep->se_init_kv));
+	mutex_destroy(&(sep->se_lock));
+
+	sep->se_index = 0;
+
+	kmem_cache_free(index ? sp->s_eqXc : sp->s_eq0c, sep);
+}
+
+
+static 	kmem_cache_t *
+sfxge_ev_kmem_cache_create(sfxge_t *sp, const char *qname,
+    int (*ctor)(void *, void *, int), void (*dtor)(void *, void *))
+{
+	char name[MAXNAMELEN];
+	kmem_cache_t *eqc;
+
+	(void) snprintf(name, MAXNAMELEN - 1, "%s%d_%s_cache",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip), qname);
+
+	eqc = kmem_cache_create(name, sizeof (sfxge_evq_t),
+	    SFXGE_CPU_CACHE_SIZE, ctor, dtor, NULL, sp, NULL, 0);
+	ASSERT(eqc != NULL);
+	return (eqc);
+}
+
+int
+sfxge_ev_init(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	unsigned int evq0_size;
+	unsigned int evqX_size;
+	unsigned int ev_batch;
+	int index;
+	int rc;
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
+
+	/*
+	 * Must account for RXQ, TXQ(s); MCDI not event completed at present
+	 * Note that common code does not completely fill descriptor queues
+	 */
+	evqX_size = sp->s_rxq_size + SFXGE_TX_NDESCS;
+	evq0_size = evqX_size + SFXGE_TX_NDESCS; /* only IP checksum TXQ */
+	evq0_size += SFXGE_TX_NDESCS; /* no checksums */
+
+	ASSERT3U(evqX_size, >=, EFX_EVQ_MINNEVS);
+	ASSERT3U(evq0_size, >, evqX_size);
+
+	if (evq0_size > EFX_EVQ_MAXNEVS) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	sp->s_evq0_size = pow2_ge(evq0_size);
+	sp->s_evqX_size = pow2_ge(evqX_size);
+
+	/* Read driver parameters */
+	sp->s_ev_moderation = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "intr_moderation", SFXGE_DEFAULT_MODERATION);
+
+	ev_batch = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "ev_batch", SFXGE_EV_BATCH);
+
+	/*
+	 * It is slightly peverse to have a cache for one item. But it allows
+	 * for simple alignment control without increasing the allocation size
+	 */
+	sp->s_eq0c = sfxge_ev_kmem_cache_create(sp, "evq0", sfxge_ev_q0ctor,
+	    sfxge_ev_q0dtor);
+	sp->s_eqXc = sfxge_ev_kmem_cache_create(sp, "evqX", sfxge_ev_qXctor,
+	    sfxge_ev_qXdtor);
+
+	/* Initialize the event queue(s) */
+	for (index = 0; index < sip->si_nalloc; index++) {
+		if ((rc = sfxge_ev_qinit(sp, index, ev_batch)) != 0)
+			goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	while (--index >= 0)
+		sfxge_ev_qfini(sp, index);
+	sp->s_ev_moderation = 0;
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	kmem_cache_destroy(sp->s_eqXc);
+	kmem_cache_destroy(sp->s_eq0c);
+	sp->s_eqXc = NULL;
+	sp->s_eq0c = NULL;
+
+	return (rc);
+}
+
+int
+sfxge_ev_start(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	efx_nic_t *enp = sp->s_enp;
+	int index;
+	int rc;
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_STARTED);
+
+	/* Initialize the event module */
+	if ((rc = efx_ev_init(enp)) != 0)
+		goto fail1;
+
+	/* Start the event queues */
+	for (index = 0; index < sip->si_nalloc; index++) {
+		if ((rc = sfxge_ev_qstart(sp, index)) != 0)
+			goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Stop the event queue(s) */
+	while (--index >= 0)
+		sfxge_ev_qstop(sp, index);
+
+	/* Tear down the event module */
+	efx_ev_fini(enp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_ev_moderation_get(sfxge_t *sp, unsigned int *usp)
+{
+	*usp = sp->s_ev_moderation;
+}
+
+int
+sfxge_ev_moderation_set(sfxge_t *sp, unsigned int us)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	int index;
+	int rc;
+
+	if (sip->si_state != SFXGE_INTR_STARTED)
+		return (ENODEV);
+
+	for (index = 0; index < sip->si_nalloc; index++) {
+		if ((rc = sfxge_ev_qmoderate(sp, index, us)) != 0)
+			goto fail1;
+	}
+
+	sp->s_ev_moderation = us;
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	/*  The only error path is if the value to set to is invalid. */
+	ASSERT3U(index, ==, 0);
+
+	return (rc);
+}
+
+void
+sfxge_ev_stop(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	efx_nic_t *enp = sp->s_enp;
+	int index;
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_STARTED);
+
+	/* Stop the event queue(s) */
+	index = sip->si_nalloc;
+	while (--index >= 0)
+		sfxge_ev_qstop(sp, index);
+
+	/* Tear down the event module */
+	efx_ev_fini(enp);
+}
+
+void
+sfxge_ev_fini(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	int index;
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
+
+	sp->s_ev_moderation = 0;
+
+	/* Tear down the event queue(s) */
+	index = sip->si_nalloc;
+	while (--index >= 0)
+		sfxge_ev_qfini(sp, index);
+
+	kmem_cache_destroy(sp->s_eqXc);
+	kmem_cache_destroy(sp->s_eq0c);
+	sp->s_eqXc = NULL;
+	sp->s_eq0c = NULL;
+}
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_gld_ndd.c	2013-08-22 18:57:33.730745855 -0400
@@ -0,0 +1,1122 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/gld.h>
+
+#include <inet/nd.h>
+#include <inet/mi.h>
+
+#include "sfxge.h"
+
+
+typedef enum sfxge_prop_e {
+	SFXGE_RX_COALESCE_MODE = 0,
+	SFXGE_RX_SCALE_COUNT,
+	SFXGE_FCNTL_RESPOND,
+	SFXGE_FCNTL_GENERATE,
+	SFXGE_INTR_MODERATION,
+	SFXGE_ADV_AUTONEG,
+	SFXGE_ADV_10GFDX,
+	SFXGE_ADV_1000FDX,
+	SFXGE_ADV_1000HDX,
+	SFXGE_ADV_100FDX,
+	SFXGE_ADV_100HDX,
+	SFXGE_ADV_10FDX,
+	SFXGE_ADV_10HDX,
+	SFXGE_ADV_PAUSE,
+	SFXGE_ADV_ASM_PAUSE,
+	SFXGE_LP_AUTONEG,
+	SFXGE_LP_10GFDX,
+	SFXGE_LP_1000FDX,
+	SFXGE_LP_1000HDX,
+	SFXGE_LP_100FDX,
+	SFXGE_LP_100HDX,
+	SFXGE_LP_10FDX,
+	SFXGE_LP_10HDX,
+	SFXGE_LP_PAUSE,
+	SFXGE_LP_ASM_PAUSE,
+	SFXGE_CAP_AUTONEG,
+	SFXGE_CAP_10GFDX,
+	SFXGE_CAP_1000FDX,
+	SFXGE_CAP_1000HDX,
+	SFXGE_CAP_100FDX,
+	SFXGE_CAP_100HDX,
+	SFXGE_CAP_10FDX,
+	SFXGE_CAP_10HDX,
+	SFXGE_CAP_PAUSE,
+	SFXGE_CAP_ASM_PAUSE,
+	SFXGE_NPROPS
+} sfxge_prop_t;
+
+
+static int
+sfxge_gld_nd_get(sfxge_t *sp, unsigned int id, uint32_t *valp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	unsigned int nprops;
+	int rc;
+
+	nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
+
+	if (sp->s_mac.sm_state != SFXGE_MAC_STARTED) {
+		rc = ENODEV;
+		goto fail1;
+	}
+
+	ASSERT3U(id, <, nprops + SFXGE_NPROPS);
+
+	if (id < nprops) {
+		if ((rc = efx_phy_prop_get(enp, id, 0, valp)) != 0)
+			goto fail2;
+	} else {
+		id -= nprops;
+
+		switch (id) {
+		case SFXGE_RX_COALESCE_MODE: {
+			sfxge_rx_coalesce_mode_t mode;
+
+			sfxge_rx_coalesce_mode_get(sp, &mode);
+
+			*valp = mode;
+			break;
+		}
+		case SFXGE_RX_SCALE_COUNT: {
+			unsigned int count;
+
+			if (sfxge_rx_scale_count_get(sp, &count) != 0)
+				count = 0;
+
+			*valp = count;
+			break;
+		}
+		case SFXGE_FCNTL_RESPOND: {
+			unsigned int fcntl;
+
+			sfxge_mac_fcntl_get(sp, &fcntl);
+
+			*valp = (fcntl & EFX_FCNTL_RESPOND) ? 1 : 0;
+			break;
+		}
+		case SFXGE_FCNTL_GENERATE: {
+			unsigned int fcntl;
+
+			sfxge_mac_fcntl_get(sp, &fcntl);
+
+			*valp = (fcntl & EFX_FCNTL_GENERATE) ? 1 : 0;
+			break;
+		}
+		case SFXGE_INTR_MODERATION: {
+			unsigned int us;
+
+			sfxge_ev_moderation_get(sp, &us);
+
+			*valp = (long)us;
+			break;
+		}
+		case SFXGE_ADV_AUTONEG: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_AN)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_ADV_10GFDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_10000FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_ADV_1000FDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_1000FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_ADV_1000HDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_1000HDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_ADV_100FDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_100FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_ADV_100HDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_100HDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_ADV_10FDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_10FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_ADV_10HDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_10HDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_ADV_PAUSE: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_PAUSE)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_ADV_ASM_PAUSE: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_ASYM)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_AUTONEG: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_AN)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_10GFDX: {
+			uint32_t mask;
+
+			efx_phy_lp_cap_get(enp, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_10000FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_1000FDX: {
+			uint32_t mask;
+
+			efx_phy_lp_cap_get(enp, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_1000FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_1000HDX: {
+			uint32_t mask;
+
+			efx_phy_lp_cap_get(enp, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_1000HDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_100FDX: {
+			uint32_t mask;
+
+			efx_phy_lp_cap_get(enp, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_100FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_100HDX: {
+			uint32_t mask;
+
+			efx_phy_lp_cap_get(enp, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_100HDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_10FDX: {
+			uint32_t mask;
+
+			efx_phy_lp_cap_get(enp, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_10FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_10HDX: {
+			uint32_t mask;
+
+			efx_phy_lp_cap_get(enp, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_10HDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_PAUSE: {
+			uint32_t mask;
+
+			efx_phy_lp_cap_get(enp, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_PAUSE)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_LP_ASM_PAUSE: {
+			uint32_t mask;
+
+			efx_phy_lp_cap_get(enp, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_ASYM)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_AUTONEG: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_AN)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_10GFDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_10000FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_1000FDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_1000FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_1000HDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_1000HDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_100FDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_100FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_100HDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_100HDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_10FDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_10FDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_10HDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_10HDX)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_PAUSE: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_PAUSE)) ? 1 : 0;
+			break;
+		}
+		case SFXGE_CAP_ASM_PAUSE: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &mask);
+
+			*valp = (mask & (1 << EFX_PHY_CAP_ASYM)) ? 1 : 0;
+			break;
+		}
+		default:
+			ASSERT(B_FALSE);
+			break;
+		}
+	}
+
+	return (0);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#ifdef _USE_NDD_PROPS
+static int
+sfxge_gld_nd_get_ioctl(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *credp)
+{
+	sfxge_ndd_param_t *snpp = (sfxge_ndd_param_t *)arg;
+	sfxge_t *sp = snpp->snp_sp;
+	unsigned int id = snpp->snp_id;
+	uint32_t val;
+	int rc;
+
+	_NOTE(ARGUNUSED(q, credp))
+
+	if ((rc = sfxge_gld_nd_get(sp, id, &val)) != 0)
+		goto fail1;
+
+	(void) mi_mpprintf(mp, "%d", val);
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#else
+static int
+sfxge_gld_nd_get_ioctl(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *credp)
+{
+	ASSERT(B_FALSE);
+	return (-ENODEV);
+}
+#endif
+
+
+static int
+sfxge_gld_nd_set(sfxge_t *sp, unsigned int id, uint32_t val)
+{
+	efx_nic_t *enp = sp->s_enp;
+	unsigned int nprops;
+	int rc;
+
+	nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
+
+	ASSERT3U(id, <, nprops + SFXGE_NPROPS);
+
+	if (id < nprops) {
+		if ((rc = efx_phy_prop_set(enp, id, val)) != 0)
+			goto fail1;
+	} else {
+		id -= nprops;
+
+		switch (id) {
+		case SFXGE_RX_COALESCE_MODE: {
+			sfxge_rx_coalesce_mode_t mode =
+			    (sfxge_rx_coalesce_mode_t)val;
+
+			if ((rc = sfxge_rx_coalesce_mode_set(sp, mode)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_RX_SCALE_COUNT: {
+			unsigned int count = (unsigned int)val;
+
+			if ((rc = sfxge_rx_scale_count_set(sp, count)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_FCNTL_RESPOND: {
+			unsigned int fcntl;
+
+			sfxge_mac_fcntl_get(sp, &fcntl);
+
+			if (val != 0)
+				fcntl |= EFX_FCNTL_RESPOND;
+			else
+				fcntl &= ~EFX_FCNTL_RESPOND;
+
+			if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_FCNTL_GENERATE: {
+			unsigned int fcntl;
+
+			sfxge_mac_fcntl_get(sp, &fcntl);
+
+			if (val != 0)
+				fcntl |= EFX_FCNTL_GENERATE;
+			else
+				fcntl &= ~EFX_FCNTL_GENERATE;
+
+			if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_INTR_MODERATION: {
+			unsigned int us = (unsigned int)val;
+
+			if ((rc = sfxge_ev_moderation_set(sp, us)) != 0)
+				goto fail1;
+			break;
+		}
+		case SFXGE_ADV_AUTONEG: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_AN);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_AN);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_ADV_10GFDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_10000FDX);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_10000FDX);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_ADV_1000FDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_1000FDX);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_1000FDX);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_ADV_1000HDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_1000HDX);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_1000HDX);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_ADV_100FDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_100FDX);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_100FDX);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_ADV_100HDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_100HDX);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_100HDX);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_ADV_10FDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_10FDX);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_10FDX);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_ADV_10HDX: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_10HDX);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_10HDX);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_ADV_PAUSE: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_PAUSE);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_PAUSE);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		case SFXGE_ADV_ASM_PAUSE: {
+			uint32_t mask;
+
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &mask);
+
+			if (val != 0)
+				mask |= (1 << EFX_PHY_CAP_ASYM);
+			else
+				mask &= ~(1 << EFX_PHY_CAP_ASYM);
+
+			if ((rc = efx_phy_adv_cap_set(enp, mask)) != 0)
+				goto fail1;
+
+			break;
+		}
+		/* Ignore other kstat writes. Might be for the link partner */
+		default:
+			DTRACE_PROBE1(ignore_kstat_write, int, id);
+		}
+	}
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+#ifdef _USE_NDD_PROPS
+static int
+sfxge_gld_nd_set_ioctl(queue_t *q, mblk_t *mp, char *valp, caddr_t arg,
+    cred_t *credp)
+{
+	sfxge_ndd_param_t *snpp = (sfxge_ndd_param_t *)arg;
+	sfxge_t *sp = snpp->snp_sp;
+	unsigned int id = snpp->snp_id;
+	long val;
+	int rc;
+
+	_NOTE(ARGUNUSED(q, mp, credp))
+
+	(void) ddi_strtol(valp, (char **)NULL, 0, &val);
+
+	if ((rc = sfxge_gld_nd_set(sp, id, (uint32_t)val)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#else
+static int
+sfxge_gld_nd_set_ioctl(queue_t *q, mblk_t *mp, char *valp, caddr_t arg,
+    cred_t *credp)
+{
+	ASSERT(B_FALSE);
+	return (-ENODEV);
+}
+#endif
+
+
+static int
+sfxge_gld_nd_update(kstat_t *ksp, int rw)
+{
+	sfxge_t *sp = ksp->ks_private;
+	efx_nic_t *enp = sp->s_enp;
+	unsigned int nprops;
+	unsigned int id;
+	int rc = 0;
+
+	nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
+
+	for (id = 0; id < nprops + SFXGE_NPROPS; id++) {
+		kstat_named_t *knp = &(sp->s_nd_stat[id]);
+
+		if (rw == KSTAT_READ)
+			rc = sfxge_gld_nd_get(sp, id, &(knp->value.ui32));
+		else if (rw == KSTAT_WRITE)
+			rc = sfxge_gld_nd_set(sp, id, knp->value.ui32);
+		else
+			rc = EACCES;
+
+		if (rc != 0)
+			goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	return (rc);
+}
+
+
+static sfxge_ndd_param_t	sfxge_ndd_param[] = {
+	{
+		NULL,
+		SFXGE_RX_COALESCE_MODE,
+		"rx_coalesce_mode",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_RX_SCALE_COUNT,
+		"rx_scale_count",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_FCNTL_RESPOND,
+		"fcntl_respond",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_FCNTL_GENERATE,
+		"fcntl_generate",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_INTR_MODERATION,
+		"intr_moderation",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_AUTONEG,
+		"adv_cap_autoneg",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_10GFDX,
+		"adv_cap_10gfdx",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_1000FDX,
+		"adv_cap_1000fdx",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_1000HDX,
+		"adv_cap_1000hdx",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_100FDX,
+		"adv_cap_100fdx",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_100HDX,
+		"adv_cap_100hdx",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_10FDX,
+		"adv_cap_10fdx",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_10HDX,
+		"adv_cap_10hdx",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_PAUSE,
+		"adv_cap_pause",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_ADV_ASM_PAUSE,
+		"adv_cap_asm_pause",
+		sfxge_gld_nd_get_ioctl,
+		sfxge_gld_nd_set_ioctl
+	},
+	{
+		NULL,
+		SFXGE_LP_AUTONEG,
+		"lp_cap_autoneg",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_LP_10GFDX,
+		"lp_cap_10gfdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_LP_1000FDX,
+		"lp_cap_1000fdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_LP_1000HDX,
+		"lp_cap_1000hdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_LP_100FDX,
+		"lp_cap_100fdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_LP_100HDX,
+		"lp_cap_100hdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_LP_10FDX,
+		"lp_cap_10fdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_LP_10HDX,
+		"lp_cap_10hdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_LP_PAUSE,
+		"lp_cap_pause",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_LP_ASM_PAUSE,
+		"lp_cap_asm_pause",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_AUTONEG,
+		"cap_autoneg",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_10GFDX,
+		"cap_10gfdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_1000FDX,
+		"cap_1000fdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_1000HDX,
+		"cap_1000hdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_100FDX,
+		"cap_100fdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_100HDX,
+		"cap_100hdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_10FDX,
+		"cap_10fdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_10HDX,
+		"cap_10hdx",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_PAUSE,
+		"cap_pause",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	},
+	{
+		NULL,
+		SFXGE_CAP_ASM_PAUSE,
+		"cap_asm_pause",
+		sfxge_gld_nd_get_ioctl,
+		NULL
+	}
+};
+
+
+int
+sfxge_gld_nd_register(sfxge_t *sp)
+{
+#ifdef _USE_NDD_PROPS
+	caddr_t *ndhp = &(sp->s_ndh);
+#endif
+	efx_nic_t *enp = sp->s_enp;
+	unsigned int nprops;
+	unsigned int id;
+	char name[MAXNAMELEN];
+	kstat_t *ksp;
+	int rc;
+
+	ASSERT3P(sp->s_ndh, ==, NULL);
+
+	nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
+
+#ifdef _USE_NDD_PROPS
+	/* Register with the NDD framework */
+	if ((sp->s_ndp = kmem_zalloc(sizeof (sfxge_ndd_param_t) *
+	    (nprops + SFXGE_NPROPS), KM_NOSLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	for (id = 0; id < nprops; id++) {
+		sfxge_ndd_param_t *snpp = &(sp->s_ndp[id]);
+
+		snpp->snp_sp = sp;
+		snpp->snp_id = id;
+		snpp->snp_name = efx_phy_prop_name(enp, id);
+		snpp->snp_get = sfxge_gld_nd_get_ioctl;
+		snpp->snp_set = sfxge_gld_nd_set_ioctl;
+
+		ASSERT(snpp->snp_name != NULL);
+
+		(void) nd_load(ndhp, (char *)(snpp->snp_name),
+		    snpp->snp_get, snpp->snp_set, (caddr_t)snpp);
+	}
+
+	for (id = 0; id < SFXGE_NPROPS; id++) {
+		sfxge_ndd_param_t *snpp = &(sp->s_ndp[id + nprops]);
+
+		*snpp = sfxge_ndd_param[id];
+		ASSERT3U(snpp->snp_id, ==, id);
+
+		snpp->snp_sp = sp;
+		snpp->snp_id += nprops;
+
+		(void) nd_load(ndhp, (char *)(snpp->snp_name),
+		    snpp->snp_get, snpp->snp_set, (caddr_t)snpp);
+	}
+#endif
+
+	/* Also create a kstat set */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_ndd",
+	    ddi_driver_name(sp->s_dip));
+
+	if ((ksp = kstat_create((char *)ddi_driver_name(sp->s_dip),
+	    ddi_get_instance(sp->s_dip), name, "ndd", KSTAT_TYPE_NAMED,
+	    (nprops + SFXGE_NPROPS), KSTAT_FLAG_WRITABLE)) == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	sp->s_nd_ksp = ksp;
+
+	ksp->ks_update = sfxge_gld_nd_update;
+	ksp->ks_private = sp;
+
+	sp->s_nd_stat = ksp->ks_data;
+
+	for (id = 0; id < nprops; id++) {
+		kstat_named_t *knp = &(sp->s_nd_stat[id]);
+
+		kstat_named_init(knp, (char *)efx_phy_prop_name(enp, id),
+		    KSTAT_DATA_UINT32);
+	}
+
+	for (id = 0; id < SFXGE_NPROPS; id++) {
+		kstat_named_t *knp = &(sp->s_nd_stat[id + nprops]);
+		sfxge_ndd_param_t *snpp = &sfxge_ndd_param[id];
+
+		kstat_named_init(knp, (char *)(snpp->snp_name),
+		    KSTAT_DATA_UINT32);
+	}
+
+	kstat_install(ksp);
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+#ifdef _USE_NDD_PROPS
+	nd_free(ndhp);
+	sp->s_ndh = NULL;
+
+	kmem_free(sp->s_ndp, sizeof (sfxge_ndd_param_t) *
+	    (nprops + SFXGE_NPROPS));
+	sp->s_ndp = NULL;
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+#endif
+
+	return (rc);
+}
+
+
+void
+sfxge_gld_nd_unregister(sfxge_t *sp)
+{
+#ifdef _USE_NDD_PROPS
+	caddr_t *ndhp = &(sp->s_ndh);
+#endif
+	efx_nic_t *enp = sp->s_enp;
+	unsigned int nprops;
+
+	nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
+
+	/* Destroy the kstat set */
+	kstat_delete(sp->s_nd_ksp);
+	sp->s_nd_ksp = NULL;
+	sp->s_nd_stat = NULL;
+
+	/* Unregister from the NDD framework */
+#ifdef _USE_NDD_PROPS
+	nd_free(ndhp);
+
+	sp->s_ndh = NULL;
+
+	kmem_free(sp->s_ndp, sizeof (sfxge_ndd_param_t) *
+	    (nprops + SFXGE_NPROPS));
+	sp->s_ndp = NULL;
+#endif
+}
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_gld_v2.c	2013-08-22 18:57:33.825006247 -0400
@@ -0,0 +1,439 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/gld.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/dlpi.h>
+#include <sys/pattr.h>
+#include <sys/ksynch.h>
+#include <sys/spl.h>
+
+#include <inet/nd.h>
+#include <inet/mi.h>
+
+#include "sfxge.h"
+
+#ifdef _USE_GLD_V2
+
+void
+sfxge_gld_link_update(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	int32_t link;
+
+	switch (smp->sm_link_mode) {
+	case EFX_LINK_UNKNOWN:
+		link = GLD_LINKSTATE_UNKNOWN;
+		break;
+	case EFX_LINK_DOWN:
+		link = GLD_LINKSTATE_DOWN;
+		break;
+	default:
+		link = GLD_LINKSTATE_UP;
+	}
+
+	gld_linkstate(sp->s_gmip, link);
+}
+
+void
+sfxge_gld_mtu_update(sfxge_t *sp)
+{
+}
+
+void
+sfxge_gld_rx_post(sfxge_t *sp, unsigned int index, mblk_t *mp)
+{
+	mblk_t **mpp;
+
+	_NOTE(ARGUNUSED(index))
+
+	mutex_enter(&(sp->s_rx_lock));
+	*(sp->s_mpp) = mp;
+
+	mpp = &mp;
+	while ((mp = *mpp) != NULL)
+		mpp = &(mp->b_next);
+
+	sp->s_mpp = mpp;
+	mutex_exit(&(sp->s_rx_lock));
+}
+
+void
+sfxge_gld_rx_push(sfxge_t *sp)
+{
+	mblk_t *mp;
+
+	mutex_enter(&(sp->s_rx_lock));
+	mp = sp->s_mp;
+	sp->s_mp = NULL;
+	sp->s_mpp = &(sp->s_mp);
+	mutex_exit(&(sp->s_rx_lock));
+
+	while (mp != NULL) {
+		mblk_t *next;
+
+		next = mp->b_next;
+		mp->b_next = NULL;
+
+		/* The stack behaves badly with multi-fragment messages */
+		if (mp->b_cont != NULL) {
+			uint16_t flags = DB_CKSUMFLAGS(mp);
+
+			(void) pullupmsg(mp, -1);
+
+			DB_CKSUMFLAGS(mp) = flags;
+		}
+
+		gld_recv(sp->s_gmip, mp);
+
+		mp = next;
+	}
+}
+
+static int
+sfxge_gld_get_stats(gld_mac_info_t *gmip, struct gld_stats *gsp)
+{
+	sfxge_t *sp = (sfxge_t *)(gmip->gldm_private);
+	unsigned int speed;
+	sfxge_link_duplex_t duplex;
+	uint64_t val;
+
+	sfxge_mac_stat_get(sp, EFX_MAC_TX_ERRORS, &val);
+	gsp->glds_errxmt = (uint32_t)val;
+
+	sfxge_mac_stat_get(sp, EFX_MAC_RX_ERRORS, &val);
+	gsp->glds_errrcv = (uint32_t)val;
+
+	sfxge_mac_stat_get(sp, EFX_MAC_RX_FCS_ERRORS, &val);
+	gsp->glds_crc = (uint32_t)val;
+
+	sfxge_mac_stat_get(sp, EFX_MAC_RX_DROP_EVENTS, &val);
+	gsp->glds_norcvbuf = (uint32_t)val;
+
+	sfxge_mac_link_speed_get(sp, &speed);
+	gsp->glds_speed = (uint64_t)speed * 1000000ull;
+
+	sfxge_mac_link_duplex_get(sp, &duplex);
+
+	switch (duplex) {
+	case SFXGE_LINK_DUPLEX_UNKNOWN:
+		gsp->glds_duplex = GLD_DUPLEX_UNKNOWN;
+		break;
+
+	case SFXGE_LINK_DUPLEX_HALF:
+		gsp->glds_duplex = GLD_DUPLEX_HALF;
+		break;
+
+	case SFXGE_LINK_DUPLEX_FULL:
+		gsp->glds_duplex = GLD_DUPLEX_FULL;
+		break;
+
+	default:
+		ASSERT(B_FALSE);
+		break;
+	}
+
+	return (GLD_SUCCESS);
+}
+
+static int
+sfxge_gld_reset(gld_mac_info_t *gmip)
+{
+	/*
+	 * The driver already has hardware resets at appropriate times
+	 * This is only ever called before gld_start()
+	 */
+	return (GLD_SUCCESS);
+}
+
+static int
+sfxge_gld_start(gld_mac_info_t *gmip)
+{
+	sfxge_t *sp = (sfxge_t *)(gmip->gldm_private);
+	int rc;
+
+	mutex_enter(&(sp->s_rx_lock));
+	sp->s_mpp = &(sp->s_mp);
+	mutex_exit(&(sp->s_rx_lock));
+
+	if ((rc = sfxge_start(sp, B_FALSE)) != 0)
+		goto fail1;
+
+	return (GLD_SUCCESS);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_enter(&(sp->s_rx_lock));
+	ASSERT3P(sp->s_mp, ==, NULL);
+	sp->s_mpp = NULL;
+	mutex_exit(&(sp->s_rx_lock));
+
+	return (GLD_FAILURE);
+}
+
+static int
+sfxge_gld_stop(gld_mac_info_t *gmip)
+{
+	sfxge_t *sp = (sfxge_t *)(gmip->gldm_private);
+
+	sfxge_stop(sp);
+
+	mutex_enter(&(sp->s_rx_lock));
+	ASSERT3P(sp->s_mp, ==, NULL);
+	sp->s_mpp = NULL;
+	mutex_exit(&(sp->s_rx_lock));
+
+	return (GLD_SUCCESS);
+}
+
+static int
+sfxge_gld_set_promiscuous(gld_mac_info_t *gmip, int flags)
+{
+	sfxge_t *sp = (sfxge_t *)(gmip->gldm_private);
+	int rc;
+
+	switch (flags) {
+	case GLD_MAC_PROMISC_NONE:
+		if ((rc = sfxge_mac_promisc_set(sp, SFXGE_PROMISC_OFF)) != 0)
+			goto fail1;
+		break;
+	case GLD_MAC_PROMISC_MULTI:
+		if ((rc = sfxge_mac_promisc_set(sp, SFXGE_PROMISC_ALL_MULTI))
+		    != 0)
+			goto fail2;
+		break;
+	default:
+		if ((rc = sfxge_mac_promisc_set(sp, SFXGE_PROMISC_ALL_PHYS))
+		    != 0)
+			goto fail3;
+		break;
+	}
+
+	return (GLD_SUCCESS);
+
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	return (GLD_FAILURE);
+}
+
+static int
+sfxge_gld_set_multicast(gld_mac_info_t *gmip, unsigned char *addr, int flag)
+{
+	sfxge_t *sp = (sfxge_t *)(gmip->gldm_private);
+	int rc;
+
+	switch (flag) {
+	case GLD_MULTI_ENABLE:
+		if ((rc = sfxge_mac_multicst_add(sp, addr)) != 0)
+			goto fail1;
+		break;
+	case GLD_MULTI_DISABLE:
+		if ((rc = sfxge_mac_multicst_remove(sp, addr)) != 0)
+			goto fail2;
+		break;
+	default:
+		ASSERT(B_FALSE);
+		break;
+	}
+
+	return (GLD_SUCCESS);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	return (GLD_FAILURE);
+}
+
+static int
+sfxge_gld_set_mac_addr(gld_mac_info_t *gmip, unsigned char *addr)
+{
+	sfxge_t *sp = (sfxge_t *)(gmip->gldm_private);
+	int rc;
+
+	if ((rc = sfxge_mac_unicst_set(sp, addr)) != 0)
+		goto fail1;
+
+	return (GLD_SUCCESS);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (GLD_BADARG);
+}
+
+int
+sfxge_gld_send(gld_mac_info_t *gmip, mblk_t *mp)
+{
+	sfxge_t *sp = (sfxge_t *)(gmip->gldm_private);
+
+	(void) sfxge_tx_packet_add(sp, mp);
+
+	/*
+	 * This gives no TX backpressure, which can cause unbounded TX DPL
+	 * size. See bug 18984. This feature is implemented for GLDv3
+	 */
+	return (GLD_SUCCESS);
+}
+
+int
+sfxge_gld_ioctl(gld_mac_info_t *gmip, queue_t *wq, mblk_t *mp)
+{
+	sfxge_t *sp = (sfxge_t *)(gmip->gldm_private);
+	struct iocblk *iocp;
+
+	iocp = (struct iocblk *)mp->b_rptr;
+
+	switch (iocp->ioc_cmd) {
+	case ND_GET:
+	case ND_SET:
+		if (!nd_getset(wq, sp->s_ndh, mp))
+			miocnak(wq, mp, 0, EINVAL);
+		else
+			qreply(wq, mp);
+		break;
+
+	default:
+		sfxge_ioctl(sp, wq, mp);
+		break;
+	}
+
+	return (GLD_SUCCESS);
+}
+
+
+int
+sfxge_gld_register(sfxge_t *sp)
+{
+	gld_mac_info_t *gmip;
+	unsigned int pri;
+	int rc;
+
+	mutex_init(&(sp->s_rx_lock), NULL, MUTEX_DRIVER,
+	    DDI_INTR_PRI(sp->s_intr.si_intr_pri));
+
+	if ((rc = sfxge_gld_nd_register(sp)) != 0)
+		goto fail1;
+
+	gmip = gld_mac_alloc(sp->s_dip);
+
+	gmip->gldm_private = (caddr_t)sp;
+
+	gmip->gldm_reset = sfxge_gld_reset;
+	gmip->gldm_start = sfxge_gld_start;
+	gmip->gldm_stop = sfxge_gld_stop;
+	gmip->gldm_set_mac_addr = sfxge_gld_set_mac_addr;
+	gmip->gldm_set_multicast = sfxge_gld_set_multicast;
+	gmip->gldm_set_promiscuous = sfxge_gld_set_promiscuous;
+	gmip->gldm_send = sfxge_gld_send;
+	gmip->gldm_get_stats = sfxge_gld_get_stats;
+	gmip->gldm_ioctl = sfxge_gld_ioctl;
+
+	gmip->gldm_ident = (char *)sfxge_ident;
+	gmip->gldm_type = DL_ETHER;
+	gmip->gldm_minpkt = 0;
+	gmip->gldm_maxpkt = sp->s_mtu;
+	gmip->gldm_addrlen = ETHERADDRL;
+	gmip->gldm_saplen = -2;
+	gmip->gldm_broadcast_addr = sfxge_brdcst;
+
+	gmip->gldm_vendor_addr = kmem_alloc(ETHERADDRL, KM_SLEEP);
+
+	if ((rc = sfxge_mac_unicst_get(sp, SFXGE_UNICST_BIA,
+	    gmip->gldm_vendor_addr)) != 0)
+		goto fail2;
+
+	gmip->gldm_devinfo = sp->s_dip;
+	gmip->gldm_ppa = ddi_get_instance(sp->s_dip);
+
+	gmip->gldm_cookie = spltoipl(0);
+
+	gmip->gldm_capabilities =
+	    GLD_CAP_LINKSTATE |
+	    GLD_CAP_CKSUM_IPHDR |
+	    GLD_CAP_CKSUM_FULL_V4 |
+	    GLD_CAP_ZEROCOPY;
+
+	if ((rc = gld_register(sp->s_dip, (char *)ddi_driver_name(sp->s_dip),
+	    gmip)) != 0)
+		goto fail3;
+
+	sp->s_gmip = gmip;
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+
+	kmem_free(gmip->gldm_vendor_addr, ETHERADDRL);
+	gld_mac_free(gmip);
+
+	sfxge_gld_nd_unregister(sp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	mutex_destroy(&(sp->s_rx_lock));
+
+	return (rc);
+}
+
+int
+sfxge_gld_unregister(sfxge_t *sp)
+{
+	gld_mac_info_t *gmip = sp->s_gmip;
+	int rc;
+
+	if ((rc = gld_unregister(gmip)) != 0)
+		goto fail1;
+
+	sp->s_gmip = NULL;
+
+	kmem_free(gmip->gldm_vendor_addr, ETHERADDRL);
+	gld_mac_free(gmip);
+
+	sfxge_gld_nd_unregister(sp);
+
+	mutex_destroy(&(sp->s_rx_lock));
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* _USE_GLD_V2 */
--- /dev/null	2013-08-22 18:57:33.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_gld_v3.c	2013-08-22 18:57:33.913033028 -0400
@@ -0,0 +1,1449 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifdef _USE_GLD_V3
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/dlpi.h>
+#ifndef _USE_GLD_V3_SOL10
+#include <sys/dld.h>
+#endif
+#include <sys/ksynch.h>
+#include <sys/cpuvar.h>
+#include <sys/cpu.h>
+
+#include <inet/tcp.h>
+
+#include "sfxge.h"
+
+#ifndef MAC_VERSION_V1
+/* GLDv3 interface version for sol10 (u8/u9) */
+#define	MAC_VERSION_V1 MAC_VERSION
+#endif
+
+/* A vlan tag is 4 bytes */
+#define	SFXGE_VLAN_TAGSZ 4
+
+void
+sfxge_gld_link_update(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	link_state_t link;
+
+	switch (smp->sm_link_mode) {
+	case EFX_LINK_UNKNOWN:
+		link = LINK_STATE_UNKNOWN;
+		break;
+	case EFX_LINK_DOWN:
+		link = LINK_STATE_DOWN;
+		break;
+	default:
+		link = LINK_STATE_UP;
+	}
+
+	mac_link_update(sp->s_mh, link);
+}
+
+void
+sfxge_gld_mtu_update(sfxge_t *sp)
+{
+#ifdef _USE_MTU_UPDATE
+	(void) mac_maxsdu_update(sp->s_mh, sp->s_mtu);
+#endif
+}
+
+void
+sfxge_gld_rx_post(sfxge_t *sp, unsigned int index, mblk_t *mp)
+{
+	_NOTE(ARGUNUSED(index))
+
+	mac_rx(sp->s_mh, NULL, mp);
+}
+
+
+void
+sfxge_gld_rx_push(sfxge_t *sp)
+{
+	_NOTE(ARGUNUSED(sp))
+}
+
+
+static uint64_t
+sfxge_phy_dfl_cap_test64(sfxge_t *sp, uint32_t field)
+{
+	return (sfxge_phy_cap_test(sp, EFX_PHY_CAP_DEFAULT, field, NULL) ?
+	    1ull : 0ull);
+}
+
+
+static uint64_t
+sfxge_phy_cur_cap_test64(sfxge_t *sp, uint32_t field)
+{
+	return (sfxge_phy_cap_test(sp, EFX_PHY_CAP_CURRENT, field, NULL) ?
+	    1ull : 0ull);
+}
+
+static uint64_t
+sfxge_phy_lp_cap_test64(sfxge_t *sp, uint32_t field)
+{
+	return (sfxge_phy_lp_cap_test(sp, field) ? 1ull : 0ull);
+}
+
+static int
+sfxge_gld_getstat(void *arg, unsigned int id, uint64_t *valp)
+{
+	sfxge_t *sp = arg;
+	efx_nic_t *enp = sp->s_enp;
+	int rc;
+
+	if (sp->s_mac.sm_state != SFXGE_MAC_STARTED) {
+		rc = ENODEV;
+		goto fail1;
+	}
+
+	switch (id) {
+	case MAC_STAT_IFSPEED: {
+		unsigned int speed;
+
+		sfxge_mac_link_speed_get(sp, &speed);
+
+		*valp = (uint64_t)speed * 1000000ull;
+		break;
+	}
+	case ETHER_STAT_LINK_DUPLEX: {
+		sfxge_link_duplex_t duplex;
+
+		sfxge_mac_link_duplex_get(sp, &duplex);
+
+		switch (duplex) {
+		case SFXGE_LINK_DUPLEX_UNKNOWN:
+			*valp = LINK_DUPLEX_UNKNOWN;
+			break;
+
+		case SFXGE_LINK_DUPLEX_HALF:
+			*valp = LINK_DUPLEX_HALF;
+			break;
+
+		case SFXGE_LINK_DUPLEX_FULL:
+			*valp = LINK_DUPLEX_FULL;
+			break;
+
+		default:
+			ASSERT(B_FALSE);
+			break;
+		}
+		break;
+	}
+
+#ifdef ETHER_STAT_CAP_10GFDX
+	case ETHER_STAT_CAP_10GFDX:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10000FDX);
+		break;
+#endif
+	case ETHER_STAT_CAP_1000FDX:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_1000FDX);
+		break;
+	case ETHER_STAT_CAP_1000HDX:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_1000HDX);
+		break;
+	case ETHER_STAT_CAP_100FDX:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_100FDX);
+		break;
+	case ETHER_STAT_CAP_100HDX:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_100HDX);
+		break;
+	case ETHER_STAT_CAP_10FDX:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10FDX);
+		break;
+	case ETHER_STAT_CAP_10HDX:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10HDX);
+		break;
+	case ETHER_STAT_CAP_ASMPAUSE:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_ASYM);
+		break;
+	case ETHER_STAT_CAP_PAUSE:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_PAUSE);
+		break;
+	case ETHER_STAT_CAP_AUTONEG:
+		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_AN);
+		break;
+
+#ifdef ETHER_STAT_ADV_CAP_10GFDX
+	case ETHER_STAT_ADV_CAP_10GFDX:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10000FDX);
+		break;
+#endif
+	case ETHER_STAT_ADV_CAP_1000FDX:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_1000FDX);
+		break;
+	case ETHER_STAT_ADV_CAP_1000HDX:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_1000HDX);
+		break;
+	case ETHER_STAT_ADV_CAP_100FDX:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_100FDX);
+		break;
+	case ETHER_STAT_ADV_CAP_100HDX:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_100HDX);
+		break;
+	case ETHER_STAT_ADV_CAP_10FDX:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10FDX);
+		break;
+	case ETHER_STAT_ADV_CAP_10HDX:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10HDX);
+		break;
+	case ETHER_STAT_ADV_CAP_ASMPAUSE:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_ASYM);
+		break;
+	case ETHER_STAT_ADV_CAP_PAUSE:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_PAUSE);
+		break;
+	case ETHER_STAT_ADV_CAP_AUTONEG:
+		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_AN);
+		break;
+
+#ifdef ETHER_STAT_LP_CAP_10GFDX
+	case ETHER_STAT_LP_CAP_10GFDX:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10000FDX);
+		break;
+#endif
+	case ETHER_STAT_LP_CAP_1000FDX:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_1000FDX);
+		break;
+	case ETHER_STAT_LP_CAP_1000HDX:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_1000HDX);
+		break;
+	case ETHER_STAT_LP_CAP_100FDX:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_100FDX);
+		break;
+	case ETHER_STAT_LP_CAP_100HDX:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_100HDX);
+		break;
+	case ETHER_STAT_LP_CAP_10FDX:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10FDX);
+		break;
+	case ETHER_STAT_LP_CAP_10HDX:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10HDX);
+		break;
+	case ETHER_STAT_LP_CAP_ASMPAUSE:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_ASYM);
+		break;
+	case ETHER_STAT_LP_CAP_PAUSE:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_PAUSE);
+		break;
+	case ETHER_STAT_LP_CAP_AUTONEG:
+		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_AN);
+		break;
+
+	case ETHER_STAT_XCVR_ADDR: {
+		const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+		*valp = encp->enc_port;
+		break;
+	}
+	case ETHER_STAT_XCVR_ID: {
+		uint32_t oui;
+
+		if ((rc = efx_phy_oui_get(sp->s_enp, &oui)) != 0)
+			goto fail2;
+		*valp = oui;
+		break;
+	}
+	case MAC_STAT_MULTIRCV:
+		sfxge_mac_stat_get(sp, EFX_MAC_RX_MULTICST_PKTS, valp);
+		break;
+
+	case MAC_STAT_BRDCSTRCV:
+		sfxge_mac_stat_get(sp, EFX_MAC_RX_BRDCST_PKTS, valp);
+		break;
+
+	case MAC_STAT_MULTIXMT:
+		sfxge_mac_stat_get(sp, EFX_MAC_TX_MULTICST_PKTS, valp);
+		break;
+
+	case MAC_STAT_BRDCSTXMT:
+		sfxge_mac_stat_get(sp, EFX_MAC_TX_BRDCST_PKTS, valp);
+		break;
+
+	case MAC_STAT_IERRORS:
+		sfxge_mac_stat_get(sp, EFX_MAC_RX_ERRORS, valp);
+		break;
+
+	case MAC_STAT_OERRORS:
+		sfxge_mac_stat_get(sp, EFX_MAC_TX_ERRORS, valp);
+		break;
+
+	case MAC_STAT_RBYTES:
+		sfxge_mac_stat_get(sp, EFX_MAC_RX_OCTETS, valp);
+		break;
+
+	case MAC_STAT_IPACKETS:
+		sfxge_mac_stat_get(sp, EFX_MAC_RX_PKTS, valp);
+		break;
+
+	case MAC_STAT_OBYTES:
+		sfxge_mac_stat_get(sp, EFX_MAC_TX_OCTETS, valp);
+		break;
+
+	case MAC_STAT_OPACKETS:
+		sfxge_mac_stat_get(sp, EFX_MAC_TX_PKTS, valp);
+		break;
+
+	case MAC_STAT_NORCVBUF:
+		sfxge_mac_stat_get(sp, EFX_MAC_RX_DROP_EVENTS, valp);
+		break;
+
+	case ETHER_STAT_FCS_ERRORS:
+		sfxge_mac_stat_get(sp, EFX_MAC_RX_FCS_ERRORS, valp);
+		break;
+
+	default:
+		rc = ENOTSUP;
+		goto fail3;
+	}
+
+	return (0);
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_gld_start(void *arg)
+{
+	sfxge_t *sp = arg;
+	int rc;
+
+	if ((rc = sfxge_start(sp, B_FALSE)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_gld_stop(void *arg)
+{
+	sfxge_t *sp = arg;
+
+	sfxge_stop(sp);
+}
+
+static int
+sfxge_gld_setpromisc(void *arg, boolean_t on)
+{
+	sfxge_t *sp = arg;
+
+	return sfxge_mac_promisc_set(sp,
+	    (on) ? SFXGE_PROMISC_ALL_PHYS : SFXGE_PROMISC_OFF);
+}
+
+static int
+sfxge_gld_multicst(void *arg, boolean_t add, const uint8_t *addr)
+{
+	sfxge_t *sp = arg;
+	int rc;
+
+	if (add) {
+		if ((rc = sfxge_mac_multicst_add(sp, (uint8_t *)addr)) != 0)
+			goto fail1;
+	} else {
+		if ((rc = sfxge_mac_multicst_remove(sp, (uint8_t *)addr)) != 0)
+			goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	return (rc);
+}
+
+static int
+sfxge_gld_unicst(void *arg, const uint8_t *addr)
+{
+	sfxge_t *sp = arg;
+	int rc;
+
+	if ((rc = sfxge_mac_unicst_set(sp, (uint8_t *)addr)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_gld_ioctl(void *arg, queue_t *wq, mblk_t *mp)
+{
+	sfxge_t *sp = arg;
+	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
+
+	switch (iocp->ioc_cmd) {
+#ifdef _USE_NDD_PROPS
+	case ND_GET:
+	case ND_SET:
+		if (!nd_getset(wq, sp->s_ndh, mp))
+			miocnak(wq, mp, 0, EINVAL);
+		else
+			qreply(wq, mp);
+		break;
+#endif
+
+	default:
+		sfxge_ioctl(sp, wq, mp);
+		break;
+	}
+}
+
+
+static mblk_t *
+sfxge_gld_tx(void *arg, mblk_t *mp)
+{
+	sfxge_t *sp = arg;
+	mblk_t *next;
+
+	/* Walk the packet chain */
+	do {
+		/* Break the packet out of the chain */
+		next = mp->b_next;
+		mp->b_next = NULL;
+
+		if (next != NULL)
+			prefetch_read_many(next);
+
+		/* Post the packet in the appropriate transmit queue */
+		if (sfxge_tx_packet_add(sp, mp) == ENOSPC) {
+			mp->b_next = next;
+			return (mp);
+		}
+
+		mp = next;
+	} while (mp != NULL);
+
+	return (NULL);
+}
+
+static boolean_t	sfxge_lso = B_TRUE;
+
+static boolean_t
+sfxge_gld_getcapab(void *arg, mac_capab_t cap, void *cap_arg)
+{
+	int rc;
+
+	_NOTE(ARGUNUSED(arg))
+
+	switch (cap) {
+	case MAC_CAPAB_LSO: {
+		mac_capab_lso_t *lsop = cap_arg;
+
+		/* Check whether LSO is disabled */
+		if (!sfxge_lso) {
+			rc = ENOTSUP;
+			goto fail1;
+		}
+
+		DTRACE_PROBE(lso);
+
+		lsop->lso_flags = LSO_TX_BASIC_TCP_IPV4;
+		lsop->lso_basic_tcp_ipv4.lso_max = TCP_MAX_LSO_LENGTH;
+		break;
+	}
+	case MAC_CAPAB_HCKSUM: {
+		uint32_t *hcksump = cap_arg;
+
+		DTRACE_PROBE(cksum);
+
+		*hcksump = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
+		break;
+	}
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	return (B_TRUE);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (B_FALSE);
+}
+
+#ifdef _USE_MAC_PRIV_PROP
+
+/*
+ * GLDv3 driver-private property names must be preceded by an underscore - see
+ * mc_getprop(9E).
+ */
+#define	SFXGE_PRIV_PROP_NAME(s) ("_" #s)
+
+/* Return the index of the named phy property. Return -1 if not found. */
+static int
+sfxge_gld_priv_prop_phy_find(sfxge_t *sp, const char *name)
+{
+	efx_nic_t *enp = sp->s_enp;
+	sfxge_mac_priv_prop_t *mac_priv_props;
+	unsigned int id;
+	unsigned int nprops;
+
+	mac_priv_props = sp->s_mac_priv_props;
+	nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
+
+	for (id = 0; id < nprops; id++) {
+		if (strncmp(name, *mac_priv_props, MAXLINKPROPNAME) == 0)
+			return (id);
+		mac_priv_props++;
+	}
+	return (-1);
+}
+
+#define	SFXGE_XSTR(s) SFXGE_STR(s)
+#define	SFXGE_STR(s) #s
+
+static void
+sfxge_gld_priv_prop_info(sfxge_t *sp, const char *name,
+mac_prop_info_handle_t handle)
+{
+	/*
+	 * Using mac_prop_info_set_default_str rather than the the corresponding
+	 * mac_prop_info_set_default_uint32 etc as it gives readable output in
+	 * "dladm show-linkprop" commands for private properties. Note this does
+	 * not break "dladm reset-linkprop" as might have been expected.
+	 */
+	/* Treat all the phy properties the same */
+	if (sfxge_gld_priv_prop_phy_find(sp, name) > 0) {
+		mac_prop_info_set_default_str(handle, "0");
+		mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
+		return;
+	}
+
+	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) {
+		mac_prop_info_set_default_str(handle,
+		    SFXGE_XSTR(SFXGE_RX_COALESCE_OFF));
+		mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
+		return;
+	}
+
+	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) {
+		mac_prop_info_set_default_str(handle,
+		    SFXGE_XSTR(SFXGE_RX_SCALE_MAX));
+		mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
+		return;
+	}
+
+	if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) {
+		mac_prop_info_set_default_str(handle,
+		    SFXGE_XSTR(SFXGE_DEFAULT_MODERATION));
+		mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
+		return;
+	}
+	DTRACE_PROBE(unknown_priv_prop);
+}
+
+
+static int
+sfxge_gld_priv_prop_get(sfxge_t *sp, const char *name,
+    unsigned int size, void *valp)
+{
+	int id;
+	long val;
+	int rc;
+
+	if ((id = sfxge_gld_priv_prop_phy_find(sp, name)) > 0) {
+		if ((rc = sfxge_phy_prop_get(sp, id, 0, (uint32_t *)&val)) != 0)
+			goto fail1;
+		goto done;
+	}
+
+	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) {
+		sfxge_rx_coalesce_mode_t mode;
+
+		sfxge_rx_coalesce_mode_get(sp, &mode);
+
+		val = (long)mode;
+		goto done;
+	}
+
+	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) {
+		unsigned int count;
+
+		if (sfxge_rx_scale_count_get(sp, &count) != 0)
+			count = 0;
+
+		val = (long)count;
+		goto done;
+	}
+
+	if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) {
+		unsigned int us;
+
+		sfxge_ev_moderation_get(sp, &us);
+
+		val = (long)us;
+		goto done;
+	}
+
+	rc = ENOTSUP;
+	goto fail2;
+
+done:
+	(void) snprintf(valp, size, "%ld", val);
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+static int
+sfxge_gld_priv_prop_set(sfxge_t *sp, const char *name, unsigned int size,
+    const void *valp)
+{
+	int id;
+	long val;
+	int rc = 0;
+
+	_NOTE(ARGUNUSED(size))
+
+	(void) ddi_strtol(valp, (char **)NULL, 0, &val);
+
+	if ((id = sfxge_gld_priv_prop_phy_find(sp, name)) > 0) {
+		if ((rc = sfxge_phy_prop_set(sp, id, (uint32_t)val)) != 0)
+			goto fail1;
+		goto done;
+	}
+
+
+	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) {
+		if ((rc = sfxge_rx_coalesce_mode_set(sp,
+			    (sfxge_rx_coalesce_mode_t)val)) != 0)
+			goto fail1;
+
+		goto done;
+	}
+
+	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) {
+		if ((rc = sfxge_rx_scale_count_set(sp, (unsigned int)val)) != 0)
+			goto fail1;
+
+		goto done;
+	}
+
+	if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) {
+		if ((rc = sfxge_ev_moderation_set(sp, (unsigned int) val) != 0))
+			goto fail1;
+
+		goto done;
+	}
+
+	rc = ENOTSUP;
+	goto fail1;
+
+done:
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+/*
+ * The renaming of properties is necessary as efx_phy_prop_name needs to be
+ * called after efx_port_init().  See bug 18074 and sfxge_phy.c for notes on the
+ * locking strategy.
+ */
+void
+sfxge_gld_priv_prop_rename(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	sfxge_mac_priv_prop_t *mac_priv_props = sp->s_mac_priv_props;
+	efx_nic_t *enp = sp->s_enp;
+	unsigned int nprops;
+	int id;
+
+	ASSERT(mutex_owned(&(smp->sm_lock)));
+
+	nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
+
+	for (id = 0; id < nprops; id++) {
+		(void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, "_%s",
+				efx_phy_prop_name(enp, id));
+		mac_priv_props++;
+	}
+}
+
+
+static void
+sfxge_gld_priv_prop_init(sfxge_t *sp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	sfxge_mac_priv_prop_t *mac_priv_props;
+	unsigned int nprops;
+	unsigned int id;
+	int nnamed_props = 3;
+
+	nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
+
+	/*
+	 * We have nprops phy properties, nnamed_props (3) named properties and
+	 * the structure must be finished by a NULL pointer.
+	 */
+	sp->s_mac_priv_props_alloc = nprops + nnamed_props + 1;
+	sp->s_mac_priv_props = kmem_zalloc(sizeof (sfxge_mac_priv_prop_t) *
+	    sp->s_mac_priv_props_alloc,
+	    KM_SLEEP);
+
+	/*
+	 * Driver-private property names start with an underscore - see
+	 * mc_getprop(9E).  Phy property names are only available later - see
+	 * bug 18074. Siena does not have these phy properties.
+	 */
+
+	mac_priv_props = sp->s_mac_priv_props;
+	for (id = 0; id < nprops; id++) {
+		*mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP);
+		(void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1,
+		    SFXGE_PRIV_PROP_NAME(phyprop%d), id);
+		mac_priv_props++;
+	}
+
+	*mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP);
+	(void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1,
+	    SFXGE_PRIV_PROP_NAME(rx_coalesce_mode));
+	mac_priv_props++;
+	nprops++;
+
+	*mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP);
+	(void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1,
+	    SFXGE_PRIV_PROP_NAME(rx_scale_count));
+	mac_priv_props++;
+	nprops++;
+
+	*mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP);
+	(void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1,
+	    SFXGE_PRIV_PROP_NAME(intr_moderation));
+	mac_priv_props++;
+	nprops++;
+
+	ASSERT3U((nprops + 1), ==, sp->s_mac_priv_props_alloc);
+
+	/* Terminated by a NULL pointer */
+	*mac_priv_props = NULL;
+}
+
+
+static void
+sfxge_gld_priv_prop_fini(sfxge_t *sp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	unsigned int nprops;
+	char **mac_priv_props;
+	unsigned int id;
+
+	nprops = efx_nic_cfg_get(enp)->enc_phy_nprops;
+	mac_priv_props = sp->s_mac_priv_props;
+
+	for (id = 0; id < nprops + 3; id++) {
+		kmem_free(*mac_priv_props, MAXLINKPROPNAME);
+		mac_priv_props++;
+	}
+
+	kmem_free(sp->s_mac_priv_props, sizeof (sfxge_mac_priv_prop_t) *
+	    sp->s_mac_priv_props_alloc);
+	sp->s_mac_priv_props = NULL;
+}
+#endif /* _USE_MAC_PRIV_PROP */
+
+
+#ifdef _USE_GLD_V3_PROPS
+static int
+sfxge_gld_getprop(void *arg, const char *name, mac_prop_id_t id,
+    unsigned int size, void *valp)
+{
+	sfxge_t *sp = arg;
+	uint32_t flag = EFX_PHY_CAP_CURRENT;
+	uint8_t *v8 = ((uint8_t *)valp);
+	int rc;
+
+	/* check size */
+	switch (id) {
+	case MAC_PROP_DUPLEX:
+		if (size < sizeof (link_duplex_t)) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+	case MAC_PROP_FLOWCTRL:
+		if (size < sizeof (link_flowctrl_t)) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+	case MAC_PROP_SPEED:
+	case MAC_PROP_STATUS:
+		if (size < sizeof (uint64_t)) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+	case MAC_PROP_MTU:
+		if (size < sizeof (uint32_t)) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+	case MAC_PROP_EN_AUTONEG:
+	case MAC_PROP_AUTONEG:
+	case MAC_PROP_EN_10GFDX_CAP:
+	case MAC_PROP_ADV_10GFDX_CAP:
+	case MAC_PROP_EN_1000FDX_CAP:
+	case MAC_PROP_ADV_1000FDX_CAP:
+	case MAC_PROP_EN_1000HDX_CAP:
+	case MAC_PROP_ADV_1000HDX_CAP:
+	case MAC_PROP_EN_100FDX_CAP:
+	case MAC_PROP_ADV_100FDX_CAP:
+	case MAC_PROP_EN_100HDX_CAP:
+	case MAC_PROP_ADV_100HDX_CAP:
+	case MAC_PROP_EN_10FDX_CAP:
+	case MAC_PROP_ADV_10FDX_CAP:
+	case MAC_PROP_EN_10HDX_CAP:
+	case MAC_PROP_ADV_10HDX_CAP:
+		if (size < sizeof (uint8_t)) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+#ifdef _USE_MAC_PRIV_PROP
+	case MAC_PROP_PRIVATE:
+		/* sfxge_gld_priv_prop_get should do any size checking */
+		break;
+#endif
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+		break;
+	}
+
+	switch (id) {
+	case MAC_PROP_DUPLEX: {
+		sfxge_link_duplex_t duplex;
+
+		sfxge_mac_link_duplex_get(sp, &duplex);
+
+		switch (duplex) {
+		case SFXGE_LINK_DUPLEX_UNKNOWN:
+			*((link_duplex_t *)valp) = LINK_DUPLEX_UNKNOWN;
+			break;
+
+		case SFXGE_LINK_DUPLEX_HALF:
+			*((link_duplex_t *)valp) = LINK_DUPLEX_HALF;
+			break;
+
+		case SFXGE_LINK_DUPLEX_FULL:
+			*((link_duplex_t *)valp) = LINK_DUPLEX_FULL;
+			break;
+
+		default:
+			ASSERT(B_FALSE);
+			break;
+		}
+
+		break;
+	}
+	case MAC_PROP_SPEED: {
+		unsigned int speed;
+
+		sfxge_mac_link_speed_get(sp, &speed);
+
+		*((uint64_t *)valp) = (uint64_t)speed * 1000000ull;
+
+		break;
+	}
+	case MAC_PROP_STATUS: {
+		boolean_t up;
+
+		sfxge_mac_link_check(sp, &up);
+
+		*((link_state_t *)valp) = (up) ?
+		    LINK_STATE_UP : LINK_STATE_DOWN;
+
+		break;
+	}
+	case MAC_PROP_EN_AUTONEG:
+	case MAC_PROP_AUTONEG:
+		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_AN, NULL);
+		break;
+	case MAC_PROP_EN_10GFDX_CAP:
+	case MAC_PROP_ADV_10GFDX_CAP:
+		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10000FDX, NULL);
+		break;
+	case MAC_PROP_EN_1000FDX_CAP:
+	case MAC_PROP_ADV_1000FDX_CAP:
+		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_1000FDX, NULL);
+		break;
+	case MAC_PROP_EN_1000HDX_CAP:
+	case MAC_PROP_ADV_1000HDX_CAP:
+		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_1000HDX, NULL);
+		break;
+	case MAC_PROP_EN_100FDX_CAP:
+	case MAC_PROP_ADV_100FDX_CAP:
+		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_100FDX, NULL);
+		break;
+	case MAC_PROP_EN_100HDX_CAP:
+	case MAC_PROP_ADV_100HDX_CAP:
+		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_100HDX, NULL);
+		break;
+	case MAC_PROP_EN_10FDX_CAP:
+	case MAC_PROP_ADV_10FDX_CAP:
+		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10FDX, NULL);
+		break;
+	case MAC_PROP_EN_10HDX_CAP:
+	case MAC_PROP_ADV_10HDX_CAP:
+		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10HDX, NULL);
+		break;
+	case MAC_PROP_MTU:
+		*((uint32_t *)valp) = (uint32_t)(sp->s_mtu);
+		break;
+
+	case MAC_PROP_FLOWCTRL: {
+		unsigned int fcntl;
+
+		sfxge_mac_fcntl_get(sp, &fcntl);
+
+		switch (fcntl) {
+		case 0:
+			*((link_flowctrl_t *)valp) = LINK_FLOWCTRL_NONE;
+			break;
+
+		case EFX_FCNTL_GENERATE:
+			*((link_flowctrl_t *)valp) = LINK_FLOWCTRL_RX;
+			break;
+
+		case EFX_FCNTL_RESPOND:
+			*((link_flowctrl_t *)valp) = LINK_FLOWCTRL_TX;
+			break;
+
+		case (EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND):
+			*((link_flowctrl_t *)valp) = LINK_FLOWCTRL_BI;
+			break;
+
+		default:
+			ASSERT(B_FALSE);
+			break;
+		}
+		break;
+	}
+#ifdef _USE_MAC_PRIV_PROP
+	case MAC_PROP_PRIVATE:
+		if ((rc = sfxge_gld_priv_prop_get(sp, name, size, valp)) != 0)
+			goto fail2;
+		break;
+#endif
+	default:
+		rc = ENOTSUP;
+		goto fail3;
+		break;
+	}
+
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+#ifdef _USE_MAC_PRIV_PROP
+fail2:
+	DTRACE_PROBE(fail2);
+#endif
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif
+
+
+#ifdef _USE_GLD_V3_PROPS
+static int
+sfxge_gld_setprop(void *arg, const char *name, mac_prop_id_t id,
+    unsigned int size, const void *valp)
+{
+	sfxge_t *sp = arg;
+	int v8 =  *(uint8_t *)valp;
+	int rc;
+
+	/* get size checks out fo the way */
+	switch (id) {
+	/*
+	 * On Sol11 (no updates) dladm seems to be using MAC_PROP_AUTONEG to set
+	 * the autoneg parameter. This does not match the scheme suggested in
+	 * mac(9E) but as they both map to the same think in the driver and in
+	 * dladm it doesn't matter.
+	 */
+	case MAC_PROP_AUTONEG:
+	case MAC_PROP_EN_AUTONEG:
+	case MAC_PROP_EN_10GFDX_CAP:
+	case MAC_PROP_EN_1000FDX_CAP:
+	case MAC_PROP_EN_1000HDX_CAP:
+	case MAC_PROP_EN_100FDX_CAP:
+	case MAC_PROP_EN_100HDX_CAP:
+	case MAC_PROP_EN_10FDX_CAP:
+	case MAC_PROP_EN_10HDX_CAP:
+		if (size < sizeof (uint8_t)) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+	case MAC_PROP_MTU:
+		if (size < sizeof (uint32_t)) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+	case MAC_PROP_FLOWCTRL:
+		if (size < sizeof (link_flowctrl_t)) {
+			rc = EINVAL;
+			goto fail1;
+		}
+		break;
+#ifdef _USE_MAC_PRIV_PROP
+	case MAC_PROP_PRIVATE:
+		/* sfxge_gld_priv_prop_set should do any size checking */
+		break;
+#endif
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+		break;
+	}
+
+	switch (id) {
+	/*
+	 * It is unclear which of MAC_PROP_AUTONEG and MAC_PROP_EN_AUTONEG is
+	 * used.  Try both.
+	 */
+	case MAC_PROP_AUTONEG:
+	case MAC_PROP_EN_AUTONEG:
+		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_AN, v8)) != 0)
+			goto fail2;
+		break;
+	case MAC_PROP_EN_10GFDX_CAP: {
+		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10000FDX, v8)) != 0)
+			goto fail2;
+		break;
+	}
+	case MAC_PROP_EN_1000FDX_CAP: {
+		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_1000FDX, v8)) != 0)
+			goto fail2;
+		break;
+	}
+	case MAC_PROP_EN_1000HDX_CAP: {
+		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_1000HDX, v8)) != 0)
+			goto fail2;
+		break;
+	}
+	case MAC_PROP_EN_100FDX_CAP: {
+		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_100FDX, v8)) != 0)
+			goto fail2;
+		break;
+	}
+	case MAC_PROP_EN_100HDX_CAP: {
+		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_100HDX, v8)) != 0)
+			goto fail2;
+		break;
+	}
+	case MAC_PROP_EN_10FDX_CAP: {
+		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10FDX, v8)) != 0)
+			goto fail2;
+		break;
+	}
+	case MAC_PROP_EN_10HDX_CAP: {
+		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10HDX, v8)) != 0)
+			goto fail2;
+		break;
+	}
+	case MAC_PROP_MTU: {
+		size_t mtu = (size_t)(*((uint32_t *)valp));
+
+		if (mtu > EFX_MAC_SDU_MAX) {
+			rc = EINVAL;
+			goto fail2;
+		}
+
+		sp->s_mtu = mtu;
+
+		DTRACE_PROBE(restart_mtu);
+		(void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_OK,
+		    "MTU changing", (uint32_t)mtu);
+
+		break;
+	}
+	case MAC_PROP_FLOWCTRL: {
+		unsigned int fcntl = 0;
+
+		switch (*((link_flowctrl_t *)valp)) {
+		case LINK_FLOWCTRL_NONE:
+			fcntl = 0;
+			break;
+
+		case LINK_FLOWCTRL_RX:
+			fcntl = EFX_FCNTL_GENERATE;
+			break;
+
+		case LINK_FLOWCTRL_TX:
+			fcntl = EFX_FCNTL_RESPOND;
+			break;
+
+		case LINK_FLOWCTRL_BI:
+			fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND;
+			break;
+
+		default:
+			rc = EINVAL;
+			goto fail2;
+			break;
+		}
+
+		if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0)
+			goto fail3;
+
+		break;
+	}
+#ifdef _USE_MAC_PRIV_PROP
+	case MAC_PROP_PRIVATE:
+		if ((rc = sfxge_gld_priv_prop_set(sp, name, size, valp)) != 0)
+			goto fail4;
+
+		break;
+#endif
+	default:
+		rc = ENOTSUP;
+		goto fail5;
+	}
+
+	return (0);
+
+fail5:
+	DTRACE_PROBE(fail5);
+
+#ifdef _USE_MAC_PRIV_PROP
+fail4:
+	DTRACE_PROBE(fail4);
+#endif
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif
+
+#ifdef _USE_GLD_V3_PROPS
+static void
+sfxge_gld_propinfo(void *arg, const char *name, mac_prop_id_t id,
+    mac_prop_info_handle_t handle)
+{
+	sfxge_t *sp = arg;
+	efx_phy_cap_type_t phy_cap = EFX_PHY_CAP_INVALID;
+	switch (id) {
+		case MAC_PROP_DUPLEX:
+			mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ);
+			return;
+		case MAC_PROP_FLOWCTRL:
+			mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
+			mac_prop_info_set_default_link_flowctrl(handle,
+			    LINK_FLOWCTRL_BI);
+			return;
+		case MAC_PROP_SPEED:
+			mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ);
+			return;
+		case MAC_PROP_STATUS:
+			mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ);
+			return;
+		case MAC_PROP_MTU: {
+			uint32_t mtu_default;
+			mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
+			mtu_default = ddi_prop_get_int(DDI_DEV_T_ANY,
+			    sp->s_dip, DDI_PROP_DONTPASS, "mtu", ETHERMTU);
+			mac_prop_info_set_default_uint32(handle, mtu_default);
+			return;
+			}
+#ifdef _USE_MAC_PRIV_PROP
+		case MAC_PROP_PRIVATE:
+			sfxge_gld_priv_prop_info(sp, name, handle);
+			return;
+#endif
+		case MAC_PROP_EN_AUTONEG:
+		case MAC_PROP_AUTONEG:
+			phy_cap = EFX_PHY_CAP_AN;
+			break;
+		case MAC_PROP_EN_10GFDX_CAP:
+		case MAC_PROP_ADV_10GFDX_CAP:
+			phy_cap = EFX_PHY_CAP_10000FDX;
+			break;
+		case MAC_PROP_EN_1000FDX_CAP:
+		case MAC_PROP_ADV_1000FDX_CAP:
+			phy_cap = EFX_PHY_CAP_1000FDX;
+			break;
+		case MAC_PROP_EN_1000HDX_CAP:
+		case MAC_PROP_ADV_1000HDX_CAP:
+			phy_cap = EFX_PHY_CAP_1000HDX;
+			break;
+		case MAC_PROP_EN_100FDX_CAP:
+		case MAC_PROP_ADV_100FDX_CAP:
+			phy_cap = EFX_PHY_CAP_100FDX;
+			break;
+		case MAC_PROP_EN_100HDX_CAP:
+		case MAC_PROP_ADV_100HDX_CAP:
+			phy_cap = EFX_PHY_CAP_100HDX;
+			break;
+		case MAC_PROP_EN_10FDX_CAP:
+		case MAC_PROP_ADV_10FDX_CAP:
+			phy_cap = EFX_PHY_CAP_10FDX;
+			break;
+		case MAC_PROP_EN_10HDX_CAP:
+		case MAC_PROP_ADV_10HDX_CAP:
+			phy_cap = EFX_PHY_CAP_10HDX;
+			break;
+		default:
+			DTRACE_PROBE(unknown_prop);
+			return;
+	}
+	if (phy_cap != EFX_PHY_CAP_INVALID) {
+		boolean_t rw;
+		uint8_t cap_default;
+		cap_default = sfxge_phy_cap_test(sp, EFX_PHY_CAP_DEFAULT,
+		    phy_cap, &rw);
+		if (rw == B_TRUE)
+			mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
+		else
+			mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ);
+		mac_prop_info_set_default_uint8(handle, cap_default);
+	}
+}
+#endif
+
+int
+sfxge_gld_register(sfxge_t *sp)
+{
+	mac_callbacks_t *mcp;
+	mac_register_t *mrp;
+	mac_handle_t mh;
+	int rc;
+
+#ifdef _USE_GLD_V3_SOL10
+	if ((rc = sfxge_gld_nd_register(sp)) != 0)
+		goto fail0;
+#endif
+
+	/*
+	 * NOTE: mac_register_t has additional fields in later kernels,
+	 * so the buffer returned by mac_alloc(9F) changes size. This
+	 * is not a problem for forward compatibility (a driver binary
+	 * built with older headers/libs running on a newer kernel).
+	 *
+	 * For Solaris 10, we build the sfxge driver on s10u9 to run on
+	 * s10u8, and later. This requries backward compatibility and
+	 * causes a problem. The mac_register_t in s10u8 is smaller than
+	 * the version in s10u9, so writing to the mc_margin field causes
+	 * a buffer overflow (and a hard-to-debug panic).
+	 *
+	 * Work around this problem by allocating mac_register_t using
+	 * kmem_alloc(9F) so it has the size expected by the driver. The
+	 * running kernel ignores the additional fields.
+	 *
+	 * Replace mac_alloc() with kmem_zalloc() and then set m_version.
+	 * Replace mac_free() with kmem_free().
+	 *
+	 * See bug 33189 and bug33213 for details.
+	 */
+	if ((mrp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+	mrp->m_version = MAC_VERSION;
+
+	mrp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+	mrp->m_driver = sp;
+	mrp->m_dip = sp->s_dip;
+
+	/* Set up the callbacks */
+	mcp = &(sp->s_mc);
+	bzero(mcp, sizeof (mac_callbacks_t));
+
+	mcp->mc_getstat = sfxge_gld_getstat;
+	mcp->mc_start = sfxge_gld_start;
+	mcp->mc_stop = sfxge_gld_stop;
+	mcp->mc_setpromisc = sfxge_gld_setpromisc;
+	mcp->mc_multicst = sfxge_gld_multicst;
+	mcp->mc_unicst = sfxge_gld_unicst;
+	mcp->mc_tx = sfxge_gld_tx;
+
+	mcp->mc_callbacks |= MC_IOCTL;
+	mcp->mc_ioctl = sfxge_gld_ioctl;
+
+	mcp->mc_callbacks |= MC_GETCAPAB;
+	mcp->mc_getcapab = sfxge_gld_getcapab;
+
+#ifdef _USE_GLD_V3_PROPS
+	/* NOTE: mc_setprop, mc_getprop, mc_propinfo added in s10u9 */
+	mcp->mc_callbacks |= MC_SETPROP;
+	mcp->mc_setprop = sfxge_gld_setprop;
+
+	mcp->mc_callbacks |= MC_GETPROP;
+	mcp->mc_getprop = sfxge_gld_getprop;
+
+	mcp->mc_callbacks |= MC_PROPINFO;
+	mcp->mc_propinfo = sfxge_gld_propinfo;
+#endif
+
+	mrp->m_callbacks = mcp;
+
+	mrp->m_src_addr = kmem_alloc(ETHERADDRL, KM_SLEEP);
+
+	if ((rc = sfxge_mac_unicst_get(sp, SFXGE_UNICST_BIA,
+	    mrp->m_src_addr)) != 0)
+		goto fail2;
+
+	mrp->m_min_sdu = 0;
+	mrp->m_max_sdu = sp->s_mtu;
+
+	/* NOTE: m_margin added in s10u9 */
+	mrp->m_margin = SFXGE_VLAN_TAGSZ;
+
+	/* Set up the private properties */
+#ifdef _USE_MAC_PRIV_PROP
+	/* NOTE: m_priv_props added in s10u9 */
+	mrp->m_priv_props = sp->s_mac_priv_props;
+	sfxge_gld_priv_prop_init(sp);
+#endif
+
+	/* NOTE: m_flags added in s11.0 */
+	/* NOTE: m_multicast_sdu added in s11.0 */
+
+	/* Register the interface */
+	if ((rc = mac_register(mrp, &mh)) != 0)
+		goto fail3;
+
+	kmem_free(mrp->m_src_addr, ETHERADDRL);
+
+	/* Free the stack registration object */
+	kmem_free(mrp, sizeof (mac_register_t));
+
+	sp->s_mh = mh;
+
+	return (0);
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+
+	kmem_free(mrp->m_src_addr, ETHERADDRL);
+
+	/* Free the stack registration object */
+	kmem_free(mrp, sizeof (mac_register_t));
+
+#ifdef _USE_MAC_PRIV_PROP
+	/* Tear down the private properties */
+	sfxge_gld_priv_prop_fini(sp);
+#endif
+
+	/* Clear the callbacks */
+	bzero(&(sp->s_mc), sizeof (mac_callbacks_t));
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+#ifdef _USE_GLD_V3_SOL10
+	sfxge_gld_nd_unregister(sp);
+
+fail0:
+	DTRACE_PROBE1(fail0, int, rc);
+#endif
+
+	return (rc);
+}
+
+int
+sfxge_gld_unregister(sfxge_t *sp)
+{
+	mac_handle_t mh = sp->s_mh;
+	int rc;
+
+	if ((rc = mac_unregister(mh)) != 0)
+		goto fail1;
+
+	sp->s_mh = NULL;
+
+#ifdef _USE_MAC_PRIV_PROP
+	/* Tear down the private properties */
+	sfxge_gld_priv_prop_fini(sp);
+#endif
+#ifdef _USE_GLD_V3_SOL10
+	sfxge_gld_nd_unregister(sp);
+#endif
+
+	/* Clear the callbacks */
+	bzero(&(sp->s_mc), sizeof (mac_callbacks_t));
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* _USE_GLD_V3 */
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_intr.c	2013-08-22 18:57:34.011725788 -0400
@@ -0,0 +1,826 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/atomic.h>
+#include <sys/modctl.h>
+#include <sys/conf.h>
+#include <sys/ethernet.h>
+#include <sys/pci.h>
+#include <sys/pcie.h>
+
+#include "sfxge.h"
+
+#include "efx.h"
+
+
+/* Interrupt table DMA attributes */
+static ddi_device_acc_attr_t sfxge_intr_devacc = {
+
+	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
+	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
+	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
+};
+
+static ddi_dma_attr_t sfxge_intr_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	EFX_INTR_SIZE,		/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	1,			/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+static unsigned int
+sfxge_intr_line(caddr_t arg1, caddr_t arg2)
+{
+	sfxge_t *sp = (void *)arg1;
+	efx_nic_t *enp = sp->s_enp;
+	sfxge_intr_t *sip = &(sp->s_intr);
+	unsigned int index;
+	boolean_t fatal;
+	uint32_t qmask;
+	int rc;
+
+	_NOTE(ARGUNUSED(arg2))
+
+	ASSERT3U(sip->si_type, ==, EFX_INTR_LINE);
+
+	if (sip->si_state != SFXGE_INTR_STARTED &&
+	    sip->si_state != SFXGE_INTR_TESTING) {
+		rc = DDI_INTR_UNCLAIMED;
+		goto done;
+	}
+
+	if (sip->si_state == SFXGE_INTR_TESTING) {
+		sip->si_mask |= 1;	/* only one interrupt */
+		rc = DDI_INTR_CLAIMED;
+		goto done;
+	}
+
+	efx_intr_status_line(enp, &fatal, &qmask);
+
+	if (fatal) {
+		sfxge_intr_fatal(sp);
+
+		rc = DDI_INTR_CLAIMED;
+		goto done;
+	}
+
+	if (qmask != 0) {
+		for (index = 0; index < EFX_INTR_NEVQS; index++) {
+			if (qmask & (1 << index))
+				(void) sfxge_ev_qpoll(sp, index);
+		}
+
+		sip->si_zero_count = 0;
+		sfxge_gld_rx_push(sp);
+		rc = DDI_INTR_CLAIMED;
+		goto done;
+	}
+
+	/*
+	 * bug15671/bug17203 workaround. Return CLAIMED for the first ISR=0
+	 * interrupt, and poll all evqs for work. For subsequent ISR=0
+	 * interrupts (the line must be shared in this case), just rearm the
+	 * event queues to ensure we don't miss an interrupt.
+	 */
+	if (sip->si_zero_count++ == 0) {
+		for (index = 0; index < EFX_INTR_NEVQS; index++) {
+			if (sp->s_sep[index] != NULL)
+				(void) sfxge_ev_qpoll(sp, index);
+		}
+
+		rc = DDI_INTR_CLAIMED;
+	} else {
+		for (index = 0; index < EFX_INTR_NEVQS; index++) {
+			if (sp->s_sep[index] != NULL)
+				(void) sfxge_ev_qprime(sp, index);
+		}
+
+		rc = DDI_INTR_UNCLAIMED;
+	}
+
+done:
+	return (rc);
+}
+
+static unsigned int
+sfxge_intr_message(caddr_t arg1, caddr_t arg2)
+{
+	sfxge_t *sp = (void *)arg1;
+	efx_nic_t *enp = sp->s_enp;
+	sfxge_intr_t *sip = &(sp->s_intr);
+	unsigned int index = (unsigned int)(uintptr_t)arg2;
+	boolean_t fatal;
+	int rc;
+
+	ASSERT3U(sip->si_type, ==, EFX_INTR_MESSAGE);
+
+	if (sip->si_state != SFXGE_INTR_STARTED &&
+	    sip->si_state != SFXGE_INTR_TESTING) {
+		rc = DDI_INTR_UNCLAIMED;
+		goto done;
+	}
+
+	if (sip->si_state == SFXGE_INTR_TESTING) {
+		uint64_t mask;
+
+		do {
+			mask = sip->si_mask;
+		} while (atomic_cas_64(&(sip->si_mask), mask,
+		    mask | (1 << index)) != mask);
+
+		rc = DDI_INTR_CLAIMED;
+		goto done;
+	}
+
+	efx_intr_status_message(enp, index, &fatal);
+
+	if (fatal) {
+		sfxge_intr_fatal(sp);
+
+		rc = DDI_INTR_CLAIMED;
+		goto done;
+	}
+
+	(void) sfxge_ev_qpoll(sp, index);
+
+	sfxge_gld_rx_push(sp);
+	rc = DDI_INTR_CLAIMED;
+
+done:
+	return (rc);
+}
+
+static int
+sfxge_intr_bus_enable(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	ddi_intr_handler_t *handler;
+	int add_index;
+	int en_index;
+	int err;
+	int rc;
+
+	/* Serialise all instances to avoid problems seen in bug31184. */
+	mutex_enter(&sfxge_global_lock);
+
+	switch (sip->si_type) {
+	case EFX_INTR_MESSAGE:
+		handler = sfxge_intr_message;
+		break;
+
+	case EFX_INTR_LINE:
+		handler = sfxge_intr_line;
+		break;
+
+	default:
+		cmn_err(CE_WARN, SFXGE_CMN_ERR
+		    "[%s%d] bus_enable: unknown intr type"
+		    " (si_type=%d nalloc=%d)\n",
+		    ddi_driver_name(sp->s_dip),
+		    ddi_get_instance(sp->s_dip),
+		    sip->si_type, sip->si_nalloc);
+		ASSERT(B_FALSE);
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	/* Try to add the handlers */
+	for (add_index = 0; add_index < sip->si_nalloc; add_index++) {
+		unsigned int pri;
+
+		(void) ddi_intr_get_pri(sip->si_table[add_index], &pri);
+		DTRACE_PROBE2(pri, unsigned int, add_index, unsigned int, pri);
+
+		err = ddi_intr_add_handler(sip->si_table[add_index], handler,
+		    (caddr_t)sp, (caddr_t)(uintptr_t)add_index);
+		if (err != DDI_SUCCESS) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] bus_enable: ddi_intr_add_handler failed"
+			    " err=%d (h=%p idx=%d nalloc=%d)\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip),
+			    err, sip->si_table[add_index], add_index,
+			    sip->si_nalloc);
+
+			rc = (err == DDI_EINVAL) ? EINVAL : EFAULT;
+			goto fail2;
+		}
+	}
+
+	/* Get interrupt capabilities */
+	err = ddi_intr_get_cap(sip->si_table[0], &(sip->si_cap));
+	if (err != DDI_SUCCESS) {
+		cmn_err(CE_WARN, SFXGE_CMN_ERR
+		    "[%s%d] bus_enable: ddi_intr_get_cap failed"
+		    " err=%d (h=%p idx=%d nalloc=%d)\n",
+		    ddi_driver_name(sp->s_dip),
+		    ddi_get_instance(sp->s_dip),
+		    err, sip->si_table[0], 0, sip->si_nalloc);
+
+		if (err == DDI_EINVAL)
+			rc = EINVAL;
+		else if (err == DDI_ENOTSUP)
+			rc = ENOTSUP;
+		else
+			rc = EFAULT;
+
+		goto fail3;
+	}
+
+	/* Enable interrupts at the bus  */
+	if (sip->si_cap & DDI_INTR_FLAG_BLOCK) {
+		en_index = 0; /* Silence gcc */
+		err = ddi_intr_block_enable(sip->si_table, sip->si_nalloc);
+		if (err != DDI_SUCCESS) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] bus_enable: ddi_intr_block_enable failed"
+			    " err=%d (table=%p nalloc=%d)\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip),
+			    err, sip->si_table, sip->si_nalloc);
+
+			rc = (err == DDI_EINVAL) ? EINVAL : EFAULT;
+			goto fail4;
+		}
+	} else {
+		for (en_index = 0; en_index < sip->si_nalloc; en_index++) {
+			err = ddi_intr_enable(sip->si_table[en_index]);
+			if (err != DDI_SUCCESS) {
+				cmn_err(CE_WARN, SFXGE_CMN_ERR
+				    "[%s%d] bus_enable: ddi_intr_enable failed"
+				    " err=%d (h=%p idx=%d nalloc=%d)\n",
+				    ddi_driver_name(sp->s_dip),
+				    ddi_get_instance(sp->s_dip),
+				    err, sip->si_table[en_index], en_index,
+				    sip->si_nalloc);
+
+				rc = (err == DDI_EINVAL) ? EINVAL : EFAULT;
+				goto fail4;
+			}
+		}
+	}
+
+	mutex_exit(&sfxge_global_lock);
+	return (0);
+
+fail4:
+	DTRACE_PROBE(fail4);
+
+	/* Disable the enabled handlers */
+	if (!(sip->si_cap & DDI_INTR_FLAG_BLOCK)) {
+		while (--en_index >= 0) {
+			err = ddi_intr_disable(sip->si_table[en_index]);
+			if (err != DDI_SUCCESS) {
+				cmn_err(CE_WARN, SFXGE_CMN_ERR
+				    "[%s%d] bus_enable: ddi_intr_disable"
+				    " failed err=%d (h=%p idx=%d nalloc=%d)\n",
+				    ddi_driver_name(sp->s_dip),
+				    ddi_get_instance(sp->s_dip),
+				    err, sip->si_table[en_index], en_index,
+				    sip->si_nalloc);
+			}
+		}
+	}
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	/* Remove all handlers */
+	add_index = sip->si_nalloc;
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Remove remaining handlers */
+	while (--add_index >= 0) {
+		err = ddi_intr_remove_handler(sip->si_table[add_index]);
+		if (err != DDI_SUCCESS) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] bus_enable: ddi_intr_remove_handler"
+			    " failed err=%d (h=%p idx=%d nalloc=%d)\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip),
+			    err, sip->si_table[add_index], add_index,
+			    sip->si_nalloc);
+		}
+	}
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&sfxge_global_lock);
+	return (rc);
+}
+
+static void
+sfxge_intr_bus_disable(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	int index;
+	int err;
+
+	/* Serialise all instances to avoid problems seen in bug31184. */
+	mutex_enter(&sfxge_global_lock);
+
+	/* Disable interrupts at the bus */
+	if (sip->si_cap & DDI_INTR_FLAG_BLOCK) {
+		err = ddi_intr_block_disable(sip->si_table, sip->si_nalloc);
+		if (err != DDI_SUCCESS) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] bus_disable: ddi_intr_block_disable"
+			    " failed err=%d (table=%p nalloc=%d)\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip),
+			    err, sip->si_table, sip->si_nalloc);
+		}
+	} else {
+		index = sip->si_nalloc;
+		while (--index >= 0) {
+			err = ddi_intr_disable(sip->si_table[index]);
+			if (err != DDI_SUCCESS) {
+				cmn_err(CE_WARN, SFXGE_CMN_ERR
+				    "[%s%d] bus_disable: ddi_intr_disable"
+				    " failed err=%d (h=%p idx=%d nalloc=%d)\n",
+				    ddi_driver_name(sp->s_dip),
+				    ddi_get_instance(sp->s_dip),
+				    err, sip->si_table[index], index,
+				    sip->si_nalloc);
+			}
+		}
+	}
+
+	sip->si_cap = 0;
+
+	/* Remove all handlers */
+	index = sip->si_nalloc;
+	while (--index >= 0) {
+		err = ddi_intr_remove_handler(sip->si_table[index]);
+		if (err != DDI_SUCCESS) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] bus_disable: ddi_intr_remove_handler"
+			    " failed err=%d (h=%p idx=%d nalloc=%d)\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip),
+			    err, sip->si_table[index], index,
+			    sip->si_nalloc);
+		}
+	}
+
+	mutex_exit(&sfxge_global_lock);
+}
+
+static int
+sfxge_intr_nic_enable(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	efsys_mem_t *esmp = &(sip->si_mem);
+	efx_nic_t *enp = sp->s_enp;
+	unsigned int index;
+	uint64_t mask;
+	unsigned int count;
+	int rc;
+
+	/* Zero the memory */
+	(void) memset(esmp->esm_base, 0, EFX_INTR_SIZE);
+
+	/* Enable interrupts at the NIC */
+	if ((rc = efx_intr_init(enp, sip->si_type, esmp)) != 0)
+		goto fail1;
+
+	efx_intr_enable(enp);
+
+	/* Test the interrupts */
+	mask = 0;
+	for (index = 0; index < sip->si_nalloc; index++) {
+		mask |= (1 << index);
+
+		rc = efx_intr_trigger(enp, index);
+		ASSERT3U(rc, ==, 0);
+	}
+
+	/* Wait for the tests to complete */
+	count = 0;
+	do {
+		DTRACE_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 1 ms */
+		drv_usecwait(1000);
+
+		/*
+		 * Check to see that all the test interrupts have been
+		 * processed.
+		 */
+		if ((mask & sip->si_mask) == mask)
+			goto done;
+
+	} while (++count < 20);
+
+	rc = ETIMEDOUT;
+	goto fail2;
+
+done:
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	cmn_err(CE_WARN, SFXGE_CMN_ERR
+	    "[%s%d] Interrupt test failed (mask=%"PRIx64" got=%"
+	    PRIx64"). NIC is disabled\n",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip),
+	    mask, sip->si_mask);
+
+	DTRACE_PROBE2(int_test_fail, uint64_t, mask, uint64_t, sip->si_mask);
+
+	sip->si_mask = 0;
+
+	/* Disable interrupts at the NIC */
+	efx_intr_disable(enp);
+	efx_intr_fini(enp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_intr_nic_disable(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	efx_nic_t *enp = sp->s_enp;
+
+	sip->si_mask = 0;
+
+	/* Disable interrupts at the NIC */
+	efx_intr_disable(enp);
+	efx_intr_fini(enp);
+}
+
+inline unsigned pow2_le(unsigned long n) {
+	unsigned int order = 1;
+	ASSERT3U(n, >, 0);
+	while ((1ul << order) <= n) ++order;
+	return (1ul << (order - 1));
+}
+
+int
+sfxge_intr_init(sfxge_t *sp)
+{
+	dev_info_t *dip = sp->s_dip;
+	sfxge_intr_t *sip = &(sp->s_intr);
+	efsys_mem_t *esmp = &(sip->si_mem);
+	sfxge_dma_buffer_attr_t dma_attr;
+	int err;
+	int rc;
+	int types;
+	int type;
+	int index;
+	unsigned int nalloc;
+	int navail;
+
+	SFXGE_OBJ_CHECK(sip, sfxge_intr_t);
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_UNINITIALIZED);
+
+#ifdef __sparc
+	/* PSARC 2007/453 */
+	(void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
+	    "#msix-request", NULL, 0);
+#endif
+
+	/* Get the map of supported interrupt types */
+	err = ddi_intr_get_supported_types(dip, &types);
+	if (err != DDI_SUCCESS) {
+		cmn_err(CE_WARN, SFXGE_CMN_ERR
+		    "[%s%d] intr_init: ddi_intr_get_supported_types"
+		    " failed err=%d\n",
+		    ddi_driver_name(sp->s_dip),
+		    ddi_get_instance(sp->s_dip),
+		    err);
+
+		if (err == DDI_EINVAL)
+			rc = EINVAL;
+		else if (err == DDI_INTR_NOTFOUND)
+			rc = ENOENT;
+		else
+			rc = EFAULT;
+
+		goto fail1;
+	}
+
+	/* Choose most favourable type */
+	if (types & DDI_INTR_TYPE_MSIX) {
+		DTRACE_PROBE(msix);
+
+		type = DDI_INTR_TYPE_MSIX;
+		sip->si_type = EFX_INTR_MESSAGE;
+	} else {
+		DTRACE_PROBE(fixed);
+
+		ASSERT(types & DDI_INTR_TYPE_FIXED);
+
+		type = DDI_INTR_TYPE_FIXED;
+		sip->si_type = EFX_INTR_LINE;
+	}
+
+	/* Get the number of available interrupts */
+	navail = 0;
+	err = ddi_intr_get_navail(dip, type, &navail);
+	if (err != DDI_SUCCESS) {
+		cmn_err(CE_WARN, SFXGE_CMN_ERR
+		    "[%s%d] intr_init: ddi_intr_get_navail failed err=%d\n",
+		    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip),
+		    err);
+
+		if (err == DDI_EINVAL)
+			rc = EINVAL;
+		else if (err == DDI_INTR_NOTFOUND)
+			rc = ENOENT;
+		else
+			rc = EFAULT;
+
+		goto fail2;
+	}
+
+	/* Double-check */
+	if (navail == 0) {
+		rc = ENOENT;
+		goto fail2;
+	}
+
+	/*
+	 * Allow greater number of MSI-X interrupts than CPUs.
+	 * This can be useful to prevent RX no desc drops; See task 32179.
+	 * Limit non MSI-X interrupts to a single instance.
+	 */
+	if (type != DDI_INTR_TYPE_MSIX)
+		navail = 1;
+	else
+		navail = min(navail, sfxge_rx_scale_prop_get(sp));
+
+	DTRACE_PROBE1(navail, unsigned int, navail);
+
+	/* Allocate a handle table */
+	sip->si_table_size = navail * sizeof (ddi_intr_handle_t);
+	sip->si_table = kmem_zalloc(sip->si_table_size, KM_SLEEP);
+
+	/*
+	 * Allocate interrupt handles.
+	 * Serialise all device instances to avoid problems seen in bug31184.
+	 */
+	mutex_enter(&sfxge_global_lock);
+
+	err = ddi_intr_alloc(dip, sip->si_table, type, 0,
+	    navail, &(sip->si_nalloc), DDI_INTR_ALLOC_NORMAL);
+
+	mutex_exit(&sfxge_global_lock);
+
+	if (err != DDI_SUCCESS) {
+		cmn_err(CE_WARN, SFXGE_CMN_ERR
+		    "[%s%d] intr_init: ddi_intr_alloc failed err=%d"
+		    " (navail=%d nalloc=%d)\n",
+		    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip),
+		    err, navail, sip->si_nalloc);
+
+		if (err == DDI_EINVAL)
+			rc = EINVAL;
+		else if (err == DDI_EAGAIN)
+			rc = EAGAIN;
+		else if (err == DDI_INTR_NOTFOUND)
+			rc = ENOENT;
+		else
+			rc = EFAULT;
+
+		goto fail3;
+	}
+
+	/* Double-check */
+	if (sip->si_nalloc == 0) {
+		rc = ENOENT;
+		goto fail3;
+	}
+
+	/* Round down to a power of 2 */
+	nalloc = pow2_le(sip->si_nalloc);
+
+	/* Free off any excess handles */
+	mutex_enter(&sfxge_global_lock);
+
+	index = sip->si_nalloc;
+	while (--index >= nalloc) {
+		(void) ddi_intr_free(sip->si_table[index]);
+		sip->si_table[index] = NULL;
+	}
+
+	mutex_exit(&sfxge_global_lock);
+
+	sip->si_nalloc = nalloc;
+	DTRACE_PROBE1(nalloc, unsigned int, sip->si_nalloc);
+
+	dma_attr.sdba_dip	 = sp->s_dip;
+	dma_attr.sdba_dattrp	 = &sfxge_intr_dma_attr;
+	dma_attr.sdba_callback	 = DDI_DMA_SLEEP;
+	dma_attr.sdba_length	 = EFX_INTR_SIZE;
+	dma_attr.sdba_memflags	 = DDI_DMA_CONSISTENT;
+	dma_attr.sdba_devaccp	 = &sfxge_intr_devacc;
+	dma_attr.sdba_bindflags	 = DDI_DMA_RDWR | DDI_DMA_CONSISTENT;
+	dma_attr.sdba_maxcookies = 1;
+	dma_attr.sdba_zeroinit	 = B_TRUE;
+
+	if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
+		goto fail4;
+
+	/* Store the highest priority for convenience */
+	sip->si_intr_pri = 0;
+	for (index = 0; index < sip->si_nalloc; index++) {
+		int pri;
+		if ((rc = ddi_intr_get_pri(sip->si_table[index], &pri)) !=  0)
+			goto fail5;
+		if (pri > sip->si_intr_pri)
+			sip->si_intr_pri = pri;
+	}
+
+	sip->si_state = SFXGE_INTR_INITIALIZED;
+	return (0);
+
+fail5:
+	DTRACE_PROBE(fail5);
+
+fail4:
+	DTRACE_PROBE(fail4);
+
+	/* Free interrupt handles */
+	mutex_exit(&sfxge_global_lock);
+
+	index = sip->si_nalloc;
+	while (--index >= 0) {
+		err = ddi_intr_free(sip->si_table[index]);
+		if (err != DDI_SUCCESS) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] intr_init: ddi_intr_free failed err=%d"
+			    " (h=%p idx=%d nalloc=%d)\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip),
+			    err, sip->si_table[index], index, sip->si_nalloc);
+		}
+		sip->si_table[index] = NULL;
+	}
+	sip->si_nalloc = 0;
+
+	mutex_exit(&sfxge_global_lock);
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	/* Free the handle table */
+	kmem_free(sip->si_table, sip->si_table_size);
+	sip->si_table = NULL;
+	sip->si_table_size = 0;
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Clear the interrupt type */
+	sip->si_type = EFX_INTR_INVALID;
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	SFXGE_OBJ_CHECK(sip, sfxge_intr_t);
+
+	return (rc);
+}
+
+int
+sfxge_intr_start(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	int rc;
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
+
+	/* Enable interrupts at the bus */
+	if ((rc = sfxge_intr_bus_enable(sp)) != 0)
+		goto fail1;
+
+	sip->si_state = SFXGE_INTR_TESTING;
+
+	/* Enable interrupts at the NIC */
+	if ((rc = sfxge_intr_nic_enable(sp)) != 0)
+		goto fail2;
+
+	sip->si_state = SFXGE_INTR_STARTED;
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Disable interrupts at the bus */
+	sfxge_intr_bus_disable(sp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	sip->si_state = SFXGE_INTR_INITIALIZED;
+
+	return (rc);
+}
+
+void
+sfxge_intr_stop(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_STARTED);
+
+	sip->si_state = SFXGE_INTR_INITIALIZED;
+
+	/* Disable interrupts at the NIC */
+	sfxge_intr_nic_disable(sp);
+
+	/* Disable interrupts at the bus */
+	sfxge_intr_bus_disable(sp);
+}
+
+void
+sfxge_intr_fini(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	efsys_mem_t *esmp = &(sip->si_mem);
+	int index;
+	int err;
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
+
+	sip->si_state = SFXGE_INTR_UNINITIALIZED;
+
+	/* Tear down dma setup */
+	sfxge_dma_buffer_destroy(esmp);
+
+
+	/* Free interrupt handles */
+	mutex_enter(&sfxge_global_lock);
+
+	index = sip->si_nalloc;
+	while (--index >= 0) {
+		err = ddi_intr_free(sip->si_table[index]);
+		if (err != DDI_SUCCESS) {
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] intr_fini: ddi_intr_free failed err=%d"
+			    " (h=%p idx=%d nalloc=%d)\n",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip),
+			    err, sip->si_table[index], index, sip->si_nalloc);
+		}
+		sip->si_table[index] = NULL;
+	}
+	sip->si_nalloc = 0;
+
+	mutex_exit(&sfxge_global_lock);
+
+	/* Free the handle table */
+	kmem_free(sip->si_table, sip->si_table_size);
+	sip->si_table = NULL;
+	sip->si_table_size = 0;
+
+	/* Clear the interrupt type */
+	sip->si_type = EFX_INTR_INVALID;
+
+	SFXGE_OBJ_CHECK(sip, sfxge_intr_t);
+}
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_ioc.h	2013-08-22 18:57:34.104129260 -0400
@@ -0,0 +1,228 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_SYS_SFXGE_IOC_H
+#define	_SYS_SFXGE_IOC_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+/* Ensure no ambiguity over structure layouts */
+#pragma pack(1)
+
+#define	SFXGE_IOC	('S' << 24 | 'F' << 16 | 'C' << 8)
+
+#define	SFXGE_STOP_IOC	(SFXGE_IOC | 0x01)
+#define	SFXGE_START_IOC	(SFXGE_IOC | 0x02)
+
+/* MDIO was SFXGE_IOC 0x03 */
+
+/* I2C was SFXGE_IOC 0x04 */
+
+/* SPI was SFXGE_IOC 0x05 */
+
+/* BAR */
+
+#define	SFXGE_BAR_IOC	(SFXGE_IOC | 0x06)
+
+typedef	struct sfxge_bar_ioc_s {
+	uint32_t	sbi_op;
+	uint32_t	sbi_addr;
+	uint32_t	sbi_data[4];
+} sfxge_bar_ioc_t;
+
+#define	SFXGE_BAR_OP_READ	0x00000001
+#define	SFXGE_BAR_OP_WRITE	0x00000002
+
+/* PCI */
+
+#define	SFXGE_PCI_IOC	(SFXGE_IOC | 0x07)
+
+typedef	struct sfxge_pci_ioc_s {
+	uint32_t	spi_op;
+	uint8_t		spi_addr;
+	uint8_t		spi_data;
+} sfxge_pci_ioc_t;
+
+#define	SFXGE_PCI_OP_READ	0x00000001
+#define	SFXGE_PCI_OP_WRITE	0x00000002
+
+/* MAC */
+
+#define	SFXGE_MAC_IOC	(SFXGE_IOC | 0x08)
+
+typedef	struct sfxge_mac_ioc_s {
+	uint32_t	smi_op;
+	uint32_t	smi_data;
+} sfxge_mac_ioc_t;
+
+#define	SFXGE_MAC_OP_LOOPBACK	0x00000001
+
+/* PHY */
+
+#define	SFXGE_PHY_IOC	(SFXGE_IOC | 0x09)
+
+typedef	struct sfxge_phy_ioc_s {
+	uint32_t	spi_op;
+	uint32_t	spi_data;
+} sfxge_phy_ioc_t;
+
+#define	SFXGE_PHY_OP_LOOPBACK	0x00000001
+#define	SFXGE_PHY_OP_LINK	0x00000002
+#define	SFXGE_PHY_OP_LED	0x00000003
+
+/* SRAM */
+
+#define	SFXGE_SRAM_IOC	(SFXGE_IOC | 0x0a)
+
+typedef	struct sfxge_sram_ioc_s {
+	uint32_t	ssi_op;
+	uint32_t	ssi_data;
+} sfxge_sram_ioc_t;
+
+#define	SFXGE_SRAM_OP_TEST	0x00000001
+
+/* TX */
+
+#define	SFXGE_TX_IOC	(SFXGE_IOC | 0x0b)
+
+typedef	struct sfxge_tx_ioc_s {
+	uint32_t	sti_op;
+	uint32_t	sti_data;
+} sfxge_tx_ioc_t;
+
+#define	SFXGE_TX_OP_LOOPBACK	0x00000001
+
+/* RX */
+
+#define	SFXGE_RX_IOC	(SFXGE_IOC | 0x0c)
+
+typedef	struct sfxge_rx_ioc_s {
+	uint32_t	sri_op;
+	uint32_t	sri_data;
+} sfxge_rx_ioc_t;
+
+#define	SFXGE_RX_OP_LOOPBACK	0x00000001
+
+/* NVRAM */
+
+#define	SFXGE_NVRAM_IOC	(SFXGE_IOC | 0x0d)
+
+typedef	struct sfxge_nvram_ioc_s {
+	uint32_t	sni_op;
+	uint32_t	sni_type;
+	uint32_t	sni_offset;
+	uint32_t	sni_size;
+	uint32_t	sni_subtype;
+	uint16_t	sni_version[4];		/* get/set_ver */
+	/*
+	 * Streams STRMSGSZ limit (default 64kb)
+	 * See write(2) and I_STR in streamio(7i)
+	 */
+	uint8_t		sni_data[32*1024];	/* read/write */
+} sfxge_nvram_ioc_t;
+
+#define	SFXGE_NVRAM_OP_SIZE		0x00000001
+#define	SFXGE_NVRAM_OP_READ		0x00000002
+#define	SFXGE_NVRAM_OP_WRITE		0x00000003
+#define	SFXGE_NVRAM_OP_ERASE		0x00000004
+#define	SFXGE_NVRAM_OP_GET_VER		0x00000005
+#define	SFXGE_NVRAM_OP_SET_VER		0x00000006
+
+#define	SFXGE_NVRAM_TYPE_BOOTROM	0x00000001
+#define	SFXGE_NVRAM_TYPE_BOOTROM_CFG	0x00000002
+#define	SFXGE_NVRAM_TYPE_MC		0x00000003
+#define	SFXGE_NVRAM_TYPE_MC_GOLDEN	0x00000004
+#define	SFXGE_NVRAM_TYPE_PHY		0x00000005
+#define	SFXGE_NVRAM_TYPE_NULL_PHY	0x00000006
+#define	SFXGE_NVRAM_TYPE_FPGA		0x00000007
+
+/* PHY BIST */
+
+#define	SFXGE_PHY_BIST_IOC	(SFXGE_IOC | 0x0e)
+
+typedef	struct sfxge_phy_bist_ioc_s {
+	boolean_t	spbi_break_link;
+	uint8_t		spbi_status_a;
+	uint8_t		spbi_status_b;
+	uint8_t		spbi_status_c;
+	uint8_t		spbi_status_d;
+	uint16_t	spbi_length_ind_a;
+	uint16_t	spbi_length_ind_b;
+	uint16_t	spbi_length_ind_c;
+	uint16_t	spbi_length_ind_d;
+} sfxge_phy_bist_ioc_t;
+
+#define	SFXGE_PHY_BIST_CABLE_OK			0
+#define	SFXGE_PHY_BIST_CABLE_INVALID		1
+#define	SFXGE_PHY_BIST_CABLE_OPEN		2
+#define	SFXGE_PHY_BIST_CABLE_INTRAPAIRSHORT	3
+#define	SFXGE_PHY_BIST_CABLE_INTERPAIRSHORT	4
+#define	SFXGE_PHY_BIST_CABLE_BUSY		5
+#define	SFXGE_PHY_BIST_CABLE_UNKNOWN		6
+
+/* MCDI */
+
+#define	SFXGE_MCDI_IOC	(SFXGE_IOC | 0x0f)
+
+typedef	struct sfxge_mcdi_ioc_s {
+	uint8_t		smi_payload[256];
+	uint8_t		smi_cmd;
+	uint8_t		smi_len; /* In and out */
+	uint8_t		smi_rc;
+} sfxge_mcdi_ioc_t;
+
+/* Reset the NIC */
+
+#define	SFXGE_NIC_RESET_IOC	(SFXGE_IOC | 0x10)
+
+/* VPD */
+
+#define	SFXGE_VPD_IOC	(SFXGE_IOC | 0x11)
+
+#define	SFXGE_VPD_MAX_PAYLOAD 0x100
+
+typedef	struct sfxge_vpd_ioc_s {
+	uint8_t		svi_op;
+	uint8_t		svi_tag;
+	uint16_t	svi_keyword;
+	uint8_t		svi_len; /* In or out */
+	uint8_t		svi_payload[SFXGE_VPD_MAX_PAYLOAD]; /* In or out */
+} sfxge_vpd_ioc_t;
+
+#define	SFXGE_VPD_OP_GET_KEYWORD	0x00000001
+#define	SFXGE_VPD_OP_SET_KEYWORD	0x00000002
+
+#pragma pack()
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_SFXGE_IOC_H */
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_mac.c	2013-08-22 18:57:34.191867266 -0400
@@ -0,0 +1,1119 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * All efx_mac_*() must be after efx_port_init()
+ * LOCKING STRATEGY: Aquire sm_lock and test sm_state==SFXGE_MAC_STARTED
+ * to serialise against sfxge_restart()
+ */
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+
+#include "sfxge.h"
+#include "efx.h"
+
+#define	SFXGE_MAC_POLL_PERIOD_MS 1000
+
+static void sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode);
+
+
+/* MAC DMA attributes */
+static ddi_device_acc_attr_t sfxge_mac_devacc = {
+
+	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
+	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
+	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
+};
+
+static ddi_dma_attr_t sfxge_mac_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	0x1000,			/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	1,			/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+
+static void
+_sfxge_mac_stat_update(sfxge_mac_t *smp, int tries, int delay_usec)
+{
+	sfxge_t *sp = smp->sm_sp;
+	efsys_mem_t *esmp = &(smp->sm_mem);
+	int rc, i;
+
+	ASSERT(mutex_owned(&(smp->sm_lock)));
+	ASSERT3U(smp->sm_state, !=, SFXGE_MAC_UNINITIALIZED);
+
+	/* if no stats pending then they are already freshly updated */
+	if (smp->sm_mac_stats_timer_reqd && !smp->sm_mac_stats_pend)
+		return;
+
+	for (i = 0; i < tries; i++) {
+		/* Synchronize the DMA memory for reading */
+		(void) ddi_dma_sync(smp->sm_mem.esm_dma_handle,
+		    0,
+		    EFX_MAC_STATS_SIZE,
+		    DDI_DMA_SYNC_FORKERNEL);
+
+		/* Try to update the cached counters */
+		if ((rc = efx_mac_stats_update(sp->s_enp, esmp, smp->sm_stat,
+		    NULL)) != EAGAIN)
+			goto done;
+
+		drv_usecwait(delay_usec);
+	}
+
+	DTRACE_PROBE(mac_stat_timeout);
+	cmn_err(CE_NOTE, SFXGE_CMN_ERR "[%s%d] MAC stats timeout",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
+	return;
+
+done:
+	smp->sm_mac_stats_pend = B_FALSE;
+	smp->sm_lbolt = ddi_get_lbolt();
+}
+
+static void
+sfxge_mac_stat_update_quick(sfxge_mac_t *smp)
+{
+	/*
+	 * Update the statistics from the most recent DMA. This might race
+	 * with an inflight dma, so retry once. Otherwise get mac stat
+	 * values from the last mac_poll() or MC periodic stats.
+	 */
+	_sfxge_mac_stat_update(smp, 2, 50);
+}
+
+static void
+sfxge_mac_stat_update_wait(sfxge_mac_t *smp)
+{
+	/* Wait a max of 20 * 500us = 10ms */
+	_sfxge_mac_stat_update(smp, 20, 500);
+}
+
+static int
+sfxge_mac_kstat_update(kstat_t *ksp, int rw)
+{
+	sfxge_mac_t *smp = ksp->ks_private;
+	kstat_named_t *knp;
+	int rc;
+
+	if (rw != KSTAT_READ) {
+		rc = EACCES;
+		goto fail1;
+	}
+
+	ASSERT(mutex_owned(&(smp->sm_lock)));
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	sfxge_mac_stat_update_quick(smp);
+
+	knp = smp->sm_stat;
+	knp += EFX_MAC_NSTATS;
+
+	knp->value.ui64 = (smp->sm_link_up) ? 1 : 0;
+	knp++;
+
+	knp->value.ui64 = smp->sm_link_speed;
+	knp++;
+
+	knp->value.ui64 = smp->sm_link_duplex;
+	knp++;
+
+done:
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_mac_kstat_init(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	dev_info_t *dip = sp->s_dip;
+	char name[MAXNAMELEN];
+	kstat_t *ksp;
+	kstat_named_t *knp;
+	unsigned int id;
+	int rc;
+
+	/* Create the set */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_mac", ddi_driver_name(dip));
+
+	if ((ksp = kstat_create((char *)ddi_driver_name(dip),
+	    ddi_get_instance(dip), name, "mac", KSTAT_TYPE_NAMED,
+	    EFX_MAC_NSTATS + 4, 0)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	smp->sm_ksp = ksp;
+
+	ksp->ks_update = sfxge_mac_kstat_update;
+	ksp->ks_private = smp;
+	ksp->ks_lock = &(smp->sm_lock);
+
+	/* Initialise the named stats */
+	smp->sm_stat = knp = ksp->ks_data;
+	for (id = 0; id < EFX_MAC_NSTATS; id++) {
+		kstat_named_init(knp, (char *)efx_mac_stat_name(sp->s_enp, id),
+		    KSTAT_DATA_UINT64);
+		knp++;
+	}
+
+	kstat_named_init(knp++, "link_up", KSTAT_DATA_UINT64);
+	kstat_named_init(knp++, "link_speed", KSTAT_DATA_UINT64);
+	kstat_named_init(knp++, "link_duplex", KSTAT_DATA_UINT64);
+
+	kstat_install(ksp);
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_mac_kstat_fini(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+
+	/* Destroy the set */
+	kstat_delete(smp->sm_ksp);
+	smp->sm_ksp = NULL;
+	smp->sm_stat = NULL;
+}
+
+void
+sfxge_mac_stat_get(sfxge_t *sp, unsigned int id, uint64_t *valp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+
+	/* Make sure the cached counter values are recent */
+	mutex_enter(&(smp->sm_lock));
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	sfxge_mac_stat_update_quick(smp);
+
+	*valp = smp->sm_stat[id].value.ui64;
+
+done:
+	mutex_exit(&(smp->sm_lock));
+}
+
+static void
+sfxge_mac_poll(void *arg)
+{
+	sfxge_t *sp = arg;
+	efx_nic_t *enp = sp->s_enp;
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efsys_mem_t *esmp = &(smp->sm_mem);
+	efx_link_mode_t mode;
+	clock_t timeout;
+
+	mutex_enter(&(smp->sm_lock));
+	while (smp->sm_state == SFXGE_MAC_STARTED) {
+
+		/* clears smp->sm_mac_stats_pend if appropriate */
+		if (smp->sm_mac_stats_pend)
+			sfxge_mac_stat_update_wait(smp);
+
+		/* This may sleep waiting for MCDI completion */
+		mode = EFX_LINK_UNKNOWN;
+		if (efx_port_poll(enp, &mode) == 0)
+			sfxge_mac_link_update_locked(sp, mode);
+
+		if ((smp->sm_link_poll_reqd == B_FALSE) &&
+		    (smp->sm_mac_stats_timer_reqd == B_FALSE))
+			goto done;
+
+		/* Zero the memory */
+		(void) memset(esmp->esm_base, 0, EFX_MAC_STATS_SIZE);
+
+		/* Trigger upload the MAC statistics counters */
+		if (smp->sm_link_up &&
+		    efx_mac_stats_upload(sp->s_enp, esmp) == 0)
+			smp->sm_mac_stats_pend = B_TRUE;
+
+		/* Wait for timeout or end of polling */
+		timeout = ddi_get_lbolt() + drv_usectohz(1000 *
+		    SFXGE_MAC_POLL_PERIOD_MS);
+		while (smp->sm_state == SFXGE_MAC_STARTED) {
+			if (cv_timedwait(&(smp->sm_link_poll_kv),
+				&(smp->sm_lock), timeout) < 0) {
+				/* Timeout - poll if polling still enabled */
+				break;
+			}
+		}
+	}
+done:
+	mutex_exit(&(smp->sm_lock));
+
+}
+
+static void
+sfxge_mac_poll_start(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+
+	ASSERT(mutex_owned(&(smp->sm_lock)));
+	ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
+
+	/* Schedule a poll */
+	(void) ddi_taskq_dispatch(smp->sm_tqp, sfxge_mac_poll, sp, DDI_SLEEP);
+}
+
+static void
+sfxge_mac_poll_stop(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+
+	ASSERT(mutex_owned(&(smp->sm_lock)));
+	ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
+
+	cv_broadcast(&(smp->sm_link_poll_kv));
+
+	/* Wait for link polling to cease */
+	mutex_exit(&(smp->sm_lock));
+	ddi_taskq_wait(smp->sm_tqp);
+	mutex_enter(&(smp->sm_lock));
+
+	/* Wait for any pending DMAed stats to complete */
+	sfxge_mac_stat_update_wait(smp);
+}
+
+int
+sfxge_mac_init(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efsys_mem_t *esmp = &(smp->sm_mem);
+	dev_info_t *dip = sp->s_dip;
+	sfxge_dma_buffer_attr_t dma_attr;
+	const efx_nic_cfg_t *encp;
+	unsigned char *bytes;
+	char buf[8];	/* sufficient for "true" or "false" plus NULL */
+	char name[MAXNAMELEN];
+	int *ints;
+	unsigned int n;
+	int err, rc;
+
+	SFXGE_OBJ_CHECK(smp, sfxge_mac_t);
+
+	ASSERT3U(smp->sm_state, ==, SFXGE_MAC_UNINITIALIZED);
+
+	smp->sm_sp = sp;
+	encp = efx_nic_cfg_get(sp->s_enp);
+	smp->sm_link_poll_reqd = (~encp->enc_features &
+				    EFX_FEATURE_LINK_EVENTS);
+	smp->sm_mac_stats_timer_reqd = (~encp->enc_features &
+				    EFX_FEATURE_PERIODIC_MAC_STATS);
+
+	mutex_init(&(smp->sm_lock), NULL, MUTEX_DRIVER,
+	    DDI_INTR_PRI(sp->s_intr.si_intr_pri));
+	cv_init(&(smp->sm_link_poll_kv), NULL, CV_DRIVER, NULL);
+
+	/* Create link poll taskq */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_mac_tq",
+	    ddi_driver_name(dip));
+	smp->sm_tqp = ddi_taskq_create(dip, name, 1, TASKQ_DEFAULTPRI,
+	    DDI_SLEEP);
+	if (smp->sm_tqp == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	if ((rc = sfxge_phy_init(sp)) != 0)
+		goto fail2;
+
+	dma_attr.sdba_dip	 = dip;
+	dma_attr.sdba_dattrp	 = &sfxge_mac_dma_attr;
+	dma_attr.sdba_callback	 = DDI_DMA_SLEEP;
+	dma_attr.sdba_length	 = EFX_MAC_STATS_SIZE;
+	dma_attr.sdba_memflags	 = DDI_DMA_CONSISTENT;
+	dma_attr.sdba_devaccp	 = &sfxge_mac_devacc;
+	dma_attr.sdba_bindflags	 = DDI_DMA_READ | DDI_DMA_CONSISTENT;
+	dma_attr.sdba_maxcookies = 1;
+	dma_attr.sdba_zeroinit	 = B_TRUE;
+
+	if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
+		goto fail3;
+
+	/*
+	 * Set the initial group hash to allow reception of only broadcast
+	 * packets.
+	 */
+	smp->sm_bucket[0xff] = 1;
+
+	/* Set the initial flow control values */
+	smp->sm_fcntl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
+
+	/*
+	 * Determine the 'burnt-in' MAC address:
+	 *
+	 * A: if the "mac-address" property is set on our device node use that.
+	 * B: otherwise, if the system property "local-mac-address?" is set to
+	 *    "false" then we use the system MAC address.
+	 * C: otherwise, if the "local-mac-address" property is set on our
+	 *    device node use that.
+	 * D: otherwise, use the value from NVRAM.
+	 */
+
+	/* A */
+	err = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+	    "mac-address", &bytes, &n);
+	switch (err) {
+	case DDI_PROP_SUCCESS:
+		if (n == ETHERADDRL) {
+			bcopy(bytes, smp->sm_bia, ETHERADDRL);
+			goto done;
+		}
+
+		ddi_prop_free(bytes);
+		break;
+
+	default:
+		break;
+	}
+
+	/* B */
+	n = sizeof (buf);
+	bzero(buf, n--);
+	(void) ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_CANSLEEP,
+	    "local-mac-address?", buf, (int *)&n);
+
+	if (strcmp(buf, "false") == 0) {
+		struct ether_addr addr;
+
+		if (localetheraddr(NULL, &addr) != 0) {
+			bcopy((uint8_t *)&addr, smp->sm_bia, ETHERADDRL);
+			goto done;
+		}
+	}
+
+	/*
+	 * C
+	 *
+	 * NOTE: "local-mac_address" maybe coded as an integer or byte array.
+	 */
+	err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+	    "local-mac-address", &ints, &n);
+	switch (err) {
+	case DDI_PROP_SUCCESS:
+		if (n == ETHERADDRL) {
+			while (n-- != 0)
+				smp->sm_bia[n] = ints[n] & 0xff;
+
+			goto done;
+		}
+
+		ddi_prop_free(ints);
+		break;
+
+	default:
+		break;
+	}
+
+	err = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+	    "local-mac-address", &bytes, &n);
+	switch (err) {
+	case DDI_PROP_SUCCESS:
+		if (n == ETHERADDRL) {
+			bcopy(bytes, smp->sm_bia, ETHERADDRL);
+			goto done;
+		}
+
+		ddi_prop_free(bytes);
+		break;
+
+	default:
+		break;
+	}
+
+	/* D */
+	bcopy(encp->enc_mac_addr, smp->sm_bia, ETHERADDRL);
+
+done:
+	/* Initialize the statistics */
+	if ((rc = sfxge_mac_kstat_init(sp)) != 0)
+		goto fail4;
+
+	if ((rc = sfxge_phy_kstat_init(sp)) != 0)
+		goto fail5;
+
+	smp->sm_state = SFXGE_MAC_INITIALIZED;
+
+	return (0);
+
+fail5:
+	DTRACE_PROBE(fail5);
+
+	sfxge_mac_kstat_fini(sp);
+fail4:
+	DTRACE_PROBE(fail4);
+
+	/* Tear down DMA setup */
+	sfxge_dma_buffer_destroy(esmp);
+fail3:
+	DTRACE_PROBE(fail3);
+
+	sfxge_phy_fini(sp);
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Destroy the link poll taskq */
+	ddi_taskq_destroy(smp->sm_tqp);
+	smp->sm_tqp = NULL;
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	cv_destroy(&(smp->sm_link_poll_kv));
+
+	mutex_destroy(&(smp->sm_lock));
+
+	smp->sm_sp = NULL;
+
+	SFXGE_OBJ_CHECK(smp, sfxge_mac_t);
+
+	return (rc);
+}
+
+int
+sfxge_mac_start(sfxge_t *sp, boolean_t restart)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efsys_mem_t *esmp = &(smp->sm_mem);
+	efx_nic_t *enp = sp->s_enp;
+	size_t pdu;
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+
+	ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
+
+	if ((rc = efx_port_init(enp)) != 0)
+		goto fail1;
+
+	/*
+	 * Set up the advertised capabilities that may have been asked for
+	 * before the call to efx_port_init().
+	 */
+	if ((rc = sfxge_phy_cap_apply(sp, !restart)) != 0)
+		goto fail2;
+
+	/* Set the SDU */
+	pdu = EFX_MAC_PDU(sp->s_mtu);
+	if ((rc = efx_mac_pdu_set(enp, pdu)) != 0)
+		goto fail3;
+
+	if ((rc = efx_mac_fcntl_set(enp, smp->sm_fcntl, B_TRUE)) != 0)
+		goto fail4;
+
+	/* Set the unicast address */
+	if ((rc = efx_mac_addr_set(enp, (smp->sm_laa_valid) ?
+	    smp->sm_laa : smp->sm_bia)) != 0)
+		goto fail5;
+
+	/* Set the unicast filter */
+	if ((rc = efx_mac_filter_set(enp,
+	    (smp->sm_promisc == SFXGE_PROMISC_ALL_PHYS), B_TRUE)) != 0) {
+		goto fail6;
+	};
+
+	/* Set the group hash */
+	if (smp->sm_promisc >= SFXGE_PROMISC_ALL_MULTI) {
+		unsigned int bucket[EFX_MAC_HASH_BITS];
+		unsigned int index;
+
+		for (index = 0; index < EFX_MAC_HASH_BITS; index++)
+			bucket[index] = 1;
+
+		if ((rc = efx_mac_hash_set(enp, bucket)) != 0)
+			goto fail7;
+	} else {
+		if ((rc = efx_mac_hash_set(enp, smp->sm_bucket)) != 0)
+			goto fail8;
+	}
+
+	if (!smp->sm_mac_stats_timer_reqd) {
+		if ((rc = efx_mac_stats_periodic(enp, esmp,
+		    SFXGE_MAC_POLL_PERIOD_MS, B_FALSE)) != 0)
+			goto fail9;
+	}
+
+	if ((rc = efx_mac_drain(enp, B_FALSE)) != 0)
+		goto fail10;
+
+	smp->sm_state = SFXGE_MAC_STARTED;
+
+#ifdef _USE_MAC_PRIV_PROP
+	sfxge_gld_priv_prop_rename(sp);
+#endif
+
+	/*
+	 * Start link state polling. For hardware that reports link change
+	 * events we still poll once to update the initial link state.
+	 */
+	sfxge_mac_poll_start(sp);
+
+	mutex_exit(&(smp->sm_lock));
+	return (0);
+
+fail10:
+	DTRACE_PROBE(fail10);
+	(void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE);
+fail9:
+	DTRACE_PROBE(fail9);
+fail8:
+	DTRACE_PROBE(fail8);
+fail7:
+	DTRACE_PROBE(fail7);
+fail6:
+	DTRACE_PROBE(fail6);
+fail5:
+	DTRACE_PROBE(fail5);
+fail4:
+	DTRACE_PROBE(fail4);
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+	efx_port_fini(enp);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+
+static void
+sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	const char *change, *duplex;
+	char info[sizeof (": now 10000Mbps FULL duplex")];
+
+	ASSERT(mutex_owned(&(smp->sm_lock)));
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		return;
+
+	if (smp->sm_link_mode == mode)
+		return;
+
+	smp->sm_link_mode = mode;
+	smp->sm_link_up = B_TRUE;
+
+	switch (smp->sm_link_mode) {
+	case EFX_LINK_UNKNOWN:
+	case EFX_LINK_DOWN:
+		smp->sm_link_speed = 0;
+		smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN;
+		smp->sm_link_up = B_FALSE;
+		break;
+
+	case EFX_LINK_10HDX:
+	case EFX_LINK_10FDX:
+		smp->sm_link_speed = 10;
+		smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_10HDX) ?
+		    SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
+		break;
+
+	case EFX_LINK_100HDX:
+	case EFX_LINK_100FDX:
+		smp->sm_link_speed = 100;
+		smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_100HDX) ?
+		    SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
+		break;
+
+	case EFX_LINK_1000HDX:
+	case EFX_LINK_1000FDX:
+		smp->sm_link_speed = 1000;
+		smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_1000HDX) ?
+		    SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
+		break;
+
+	case EFX_LINK_10000FDX:
+		smp->sm_link_speed = 10000;
+		smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL;
+		break;
+
+	default:
+		ASSERT(B_FALSE);
+		break;
+	}
+
+	duplex = (smp->sm_link_duplex == SFXGE_LINK_DUPLEX_FULL) ?
+	    "full" : "half";
+	change = (smp->sm_link_up) ? "UP" : "DOWN";
+	snprintf(info, sizeof (info), ": now %dMbps %s duplex",
+	    smp->sm_link_speed, duplex);
+
+	cmn_err(CE_NOTE, SFXGE_CMN_ERR "[%s%d] Link %s%s",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip),
+	    change, smp->sm_link_up ? info : "");
+
+	/* Push link state update to the OS */
+	sfxge_gld_link_update(sp);
+}
+
+void
+sfxge_mac_link_update(sfxge_t *sp, efx_link_mode_t mode)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+
+	mutex_enter(&(smp->sm_lock));
+	sfxge_mac_link_update_locked(sp, mode);
+	mutex_exit(&(smp->sm_lock));
+}
+
+void
+sfxge_mac_link_check(sfxge_t *sp, boolean_t *upp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+
+	mutex_enter(&(smp->sm_lock));
+	*upp = smp->sm_link_up;
+	mutex_exit(&(smp->sm_lock));
+}
+
+void
+sfxge_mac_link_speed_get(sfxge_t *sp, unsigned int *speedp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+
+	mutex_enter(&(smp->sm_lock));
+	*speedp = smp->sm_link_speed;
+	mutex_exit(&(smp->sm_lock));
+}
+
+void
+sfxge_mac_link_duplex_get(sfxge_t *sp, sfxge_link_duplex_t *duplexp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+
+	mutex_enter(&(smp->sm_lock));
+	*duplexp = smp->sm_link_duplex;
+	mutex_exit(&(smp->sm_lock));
+}
+
+void
+sfxge_mac_fcntl_get(sfxge_t *sp, unsigned int *fcntlp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+
+	mutex_enter(&(smp->sm_lock));
+	*fcntlp = smp->sm_fcntl;
+	mutex_exit(&(smp->sm_lock));
+}
+
+int
+sfxge_mac_fcntl_set(sfxge_t *sp, unsigned int fcntl)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+
+	if (smp->sm_fcntl == fcntl)
+		goto done;
+
+	smp->sm_fcntl = fcntl;
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	if ((rc = efx_mac_fcntl_set(sp->s_enp, smp->sm_fcntl, B_TRUE)) != 0)
+		goto fail1;
+
+done:
+	mutex_exit(&(smp->sm_lock));
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+int
+sfxge_mac_unicst_get(sfxge_t *sp, sfxge_unicst_type_t type, uint8_t *addr)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	int rc;
+
+	if (type >= SFXGE_UNICST_NTYPES) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	mutex_enter(&(smp->sm_lock));
+
+	if (smp->sm_state != SFXGE_MAC_INITIALIZED &&
+	    smp->sm_state != SFXGE_MAC_STARTED) {
+		rc = EFAULT;
+		goto fail2;
+	}
+
+	switch (type) {
+	case SFXGE_UNICST_BIA:
+		bcopy(smp->sm_bia, addr, ETHERADDRL);
+		break;
+
+	case SFXGE_UNICST_LAA:
+		if (!(smp->sm_laa_valid)) {
+			rc = ENOENT;
+			goto fail3;
+		}
+
+		bcopy(smp->sm_laa, addr, ETHERADDRL);
+		break;
+
+	default:
+		ASSERT(B_FALSE);
+		break;
+	}
+
+	mutex_exit(&(smp->sm_lock));
+
+	return (0);
+
+
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+
+	mutex_exit(&(smp->sm_lock));
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+int
+sfxge_mac_unicst_set(sfxge_t *sp, uint8_t *addr)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp = sp->s_enp;
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+
+	bcopy(addr, smp->sm_laa, ETHERADDRL);
+	smp->sm_laa_valid = B_TRUE;
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	if ((rc = efx_mac_addr_set(enp, smp->sm_laa)) != 0)
+		goto fail1;
+
+done:
+	mutex_exit(&(smp->sm_lock));
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+int
+sfxge_mac_promisc_set(sfxge_t *sp, sfxge_promisc_type_t promisc)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp = sp->s_enp;
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+
+	if (smp->sm_promisc == promisc)
+		goto done;
+
+	smp->sm_promisc = promisc;
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	if ((rc = efx_mac_filter_set(enp, (promisc == SFXGE_PROMISC_ALL_PHYS),
+	    B_TRUE)) != 0)
+		goto fail1;
+
+	if (promisc >= SFXGE_PROMISC_ALL_MULTI) {
+		unsigned int bucket[EFX_MAC_HASH_BITS];
+		unsigned int index;
+
+		for (index = 0; index < EFX_MAC_HASH_BITS; index++)
+			bucket[index] = 1;
+
+		if ((rc = efx_mac_hash_set(enp, bucket)) != 0)
+			goto fail2;
+	} else {
+		if ((rc = efx_mac_hash_set(enp, smp->sm_bucket)) != 0)
+			goto fail3;
+	}
+
+done:
+	mutex_exit(&(smp->sm_lock));
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+int
+sfxge_mac_multicst_add(sfxge_t *sp, uint8_t *addr)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp = sp->s_enp;
+	uint32_t crc;
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+
+	CRC32(crc, addr, ETHERADDRL, 0xffffffff, crc32_table);
+	smp->sm_bucket[crc % EFX_MAC_HASH_BITS]++;
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	if (smp->sm_promisc >= SFXGE_PROMISC_ALL_MULTI)
+		goto done;
+
+	if ((rc = efx_mac_hash_set(enp, smp->sm_bucket)) != 0)
+		goto fail1;
+
+done:
+	mutex_exit(&(smp->sm_lock));
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+int
+sfxge_mac_multicst_remove(sfxge_t *sp, uint8_t *addr)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp = sp->s_enp;
+	uint32_t crc;
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+
+	CRC32(crc, addr, ETHERADDRL, 0xffffffff, crc32_table);
+	ASSERT(smp->sm_bucket[crc % EFX_MAC_HASH_BITS] != 0);
+	smp->sm_bucket[crc % EFX_MAC_HASH_BITS]--;
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	if (smp->sm_promisc >= SFXGE_PROMISC_ALL_MULTI)
+		goto done;
+
+	if ((rc = efx_mac_hash_set(enp, smp->sm_bucket)) != 0)
+		goto fail1;
+
+done:
+	mutex_exit(&(smp->sm_lock));
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+static int
+sfxge_mac_loopback_set(sfxge_t *sp, efx_loopback_type_t type)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp = sp->s_enp;
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+	ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
+
+	if ((rc = efx_port_loopback_set(enp, EFX_LINK_UNKNOWN, type)) != 0)
+		goto fail1;
+
+	mutex_exit(&(smp->sm_lock));
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+int
+sfxge_mac_ioctl(sfxge_t *sp, sfxge_mac_ioc_t *smip)
+{
+	int rc;
+
+	switch (smip->smi_op) {
+	case SFXGE_MAC_OP_LOOPBACK: {
+		efx_loopback_type_t type = smip->smi_data;
+
+		if ((rc = sfxge_mac_loopback_set(sp, type)) != 0)
+			goto fail1;
+
+		break;
+	}
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_mac_stop(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp = sp->s_enp;
+	efsys_mem_t *esmp = &(smp->sm_mem);
+
+	mutex_enter(&(smp->sm_lock));
+
+	ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
+	ASSERT3P(smp->sm_sp, ==, sp);
+	smp->sm_state = SFXGE_MAC_INITIALIZED;
+
+	/* If stopping in response to an MC reboot this may fail */
+	if (!smp->sm_mac_stats_timer_reqd)
+		(void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE);
+
+	sfxge_mac_poll_stop(sp);
+
+	smp->sm_lbolt = 0;
+
+	smp->sm_link_up = B_FALSE;
+	smp->sm_link_speed = 0;
+	smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN;
+
+	/* This may call MCDI */
+	(void) efx_mac_drain(enp, B_TRUE);
+
+	smp->sm_link_mode = EFX_LINK_UNKNOWN;
+
+
+	efx_port_fini(enp);
+
+	mutex_exit(&(smp->sm_lock));
+}
+
+void
+sfxge_mac_fini(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efsys_mem_t *esmp = &(smp->sm_mem);
+	unsigned int index;
+
+	ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
+	ASSERT3P(smp->sm_sp, ==, sp);
+
+	/* Tear down the statistics */
+	sfxge_phy_kstat_fini(sp);
+	sfxge_mac_kstat_fini(sp);
+
+	smp->sm_state = SFXGE_MAC_UNINITIALIZED;
+	smp->sm_link_mode = EFX_LINK_UNKNOWN;
+	smp->sm_promisc = SFXGE_PROMISC_OFF;
+
+	/* Clear the group hash */
+	for (index = 0; index < EFX_MAC_HASH_BITS; index++)
+		smp->sm_bucket[index] = 0;
+
+	bzero(smp->sm_laa, ETHERADDRL);
+	smp->sm_laa_valid = B_FALSE;
+
+	bzero(smp->sm_bia, ETHERADDRL);
+
+	smp->sm_fcntl = 0;
+
+	/* Finish with PHY DMA memory */
+	sfxge_phy_fini(sp);
+
+	/* Teardown the DMA */
+	sfxge_dma_buffer_destroy(esmp);
+
+	/* Destroy the link poll taskq */
+	ddi_taskq_destroy(smp->sm_tqp);
+	smp->sm_tqp = NULL;
+
+	mutex_destroy(&(smp->sm_lock));
+
+	smp->sm_sp = NULL;
+
+	SFXGE_OBJ_CHECK(smp, sfxge_mac_t);
+}
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_mcdi.c	2013-08-22 18:57:34.286338732 -0400
@@ -0,0 +1,314 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stream.h>
+#include <sys/dlpi.h>
+
+#include "sfxge.h"
+#include "efsys.h"
+#include "efx.h"
+#include "efx_mcdi.h"
+#include "efx_regs_mcdi.h"
+
+
+/*
+ * Notes on MCDI operation:
+ * ------------------------
+ * MCDI requests can be made in arbitrary thread context, and as a synchronous
+ * API must therefore block until the response is available from the MC, or
+ * a watchdog timeout occurs.
+ *
+ * This interacts badly with the limited number of worker threads (2 per CPU)
+ * used by the Solaris callout subsystem to invoke timeout handlers. If both
+ * worker threads are blocked (e.g. waiting for a condvar or mutex) then timeout
+ * processing is deadlocked on that CPU, causing system failure.
+ *
+ * For this reason the driver does not use event based MCDI completion, as this
+ * leads to numerous paths involving timeouts and reentrant GLDv3 entrypoints
+ * that result in a deadlocked system.
+ */
+#define	SFXGE_MCDI_POLL_INTERVAL	10		/* 10us in 1us units */
+#define	SFXGE_MCDI_WATCHDOG_INTERVAL	10000000	/* 10s in 1us units */
+
+
+/* Acquire exclusive access to MCDI for the duration of a request */
+static void
+sfxge_mcdi_acquire(sfxge_mcdi_t *smp)
+{
+	mutex_enter(&(smp->sm_lock));
+	ASSERT3U(smp->sm_state, !=, SFXGE_MCDI_UNINITIALIZED);
+
+	while (smp->sm_state != SFXGE_MCDI_INITIALIZED) {
+		(void) cv_wait_sig(&(smp->sm_kv), &(smp->sm_lock));
+	}
+	smp->sm_state = SFXGE_MCDI_BUSY;
+
+	mutex_exit(&(smp->sm_lock));
+}
+
+
+/* Release ownership of MCDI on request completion */
+static void
+sfxge_mcdi_release(sfxge_mcdi_t *smp)
+{
+	mutex_enter(&(smp->sm_lock));
+	ASSERT((smp->sm_state == SFXGE_MCDI_BUSY) ||
+	    (smp->sm_state == SFXGE_MCDI_COMPLETED));
+
+	smp->sm_state = SFXGE_MCDI_INITIALIZED;
+	cv_broadcast(&(smp->sm_kv));
+
+	mutex_exit(&(smp->sm_lock));
+}
+
+
+static void
+sfxge_mcdi_timeout(sfxge_t *sp)
+{
+	dev_info_t *dip = sp->s_dip;
+
+	cmn_err(CE_WARN, SFXGE_CMN_ERR "[%s%d] MC_TIMEOUT",
+	    ddi_driver_name(dip), ddi_get_instance(dip));
+
+	DTRACE_PROBE(mcdi_timeout);
+	(void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_ERR,
+	    "MCDI timeout", 0);
+}
+
+
+static void
+sfxge_mcdi_poll(sfxge_t *sp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	clock_t timeout;
+	boolean_t aborted;
+
+	/* Poll until request completes or timeout */
+	timeout = ddi_get_lbolt() + drv_usectohz(SFXGE_MCDI_WATCHDOG_INTERVAL);
+	while (efx_mcdi_request_poll(enp) == B_FALSE) {
+
+		/* No response received yet */
+		if (ddi_get_lbolt() > timeout) {
+			/* Timeout expired */
+			goto fail;
+		}
+
+		/* Short delay to avoid excessive PCIe traffic */
+		drv_usecwait(SFXGE_MCDI_POLL_INTERVAL);
+	}
+
+	/* Request completed (or polling failed) */
+	return;
+
+fail:
+	/* Timeout before request completion */
+	DTRACE_PROBE(fail);
+	aborted = efx_mcdi_request_abort(enp);
+	ASSERT(aborted);
+	sfxge_mcdi_timeout(sp);
+}
+
+
+static void
+sfxge_mcdi_execute(void *arg, efx_mcdi_req_t *emrp)
+{
+	sfxge_t *sp = (sfxge_t *)arg;
+	sfxge_mcdi_t *smp = &(sp->s_mcdi);
+
+	sfxge_mcdi_acquire(smp);
+
+	/* Issue request and poll for completion */
+	efx_mcdi_request_start(sp->s_enp, emrp, B_FALSE);
+	sfxge_mcdi_poll(sp);
+
+	sfxge_mcdi_release(smp);
+}
+
+
+static void
+sfxge_mcdi_ev_cpl(void *arg)
+{
+	sfxge_t *sp = (sfxge_t *)arg;
+	sfxge_mcdi_t *smp = &(sp->s_mcdi);
+
+	mutex_enter(&(smp->sm_lock));
+	ASSERT(smp->sm_state == SFXGE_MCDI_BUSY);
+	smp->sm_state = SFXGE_MCDI_COMPLETED;
+	cv_broadcast(&(smp->sm_kv));
+	mutex_exit(&(smp->sm_lock));
+}
+
+
+static void
+sfxge_mcdi_exception(void *arg, efx_mcdi_exception_t eme)
+{
+	sfxge_t *sp = (sfxge_t *)arg;
+	const char *reason;
+
+	if (eme == EFX_MCDI_EXCEPTION_MC_REBOOT)
+		reason = "MC_REBOOT";
+	else if (eme == EFX_MCDI_EXCEPTION_MC_BADASSERT)
+		reason = "MC_BADASSERT";
+	else
+		reason = "MC_UNKNOWN";
+
+	DTRACE_PROBE(mcdi_exception);
+	/* sfxge_evq_t->se_lock held */
+	(void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_ERR, reason, 0);
+}
+
+
+int
+sfxge_mcdi_init(sfxge_t *sp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	sfxge_mcdi_t *smp = &(sp->s_mcdi);
+	efx_mcdi_transport_t *emtp = &(smp->sm_emt);
+	int rc;
+
+	ASSERT3U(smp->sm_state, ==, SFXGE_MCDI_UNINITIALIZED);
+
+	mutex_init(&(smp->sm_lock), NULL, MUTEX_DRIVER, NULL);
+
+	smp->sm_state = SFXGE_MCDI_INITIALIZED;
+
+	emtp->emt_context = sp;
+	emtp->emt_execute = sfxge_mcdi_execute;
+	emtp->emt_ev_cpl = sfxge_mcdi_ev_cpl;
+	emtp->emt_exception = sfxge_mcdi_exception;
+
+	cv_init(&(smp->sm_kv), NULL, CV_DRIVER, NULL);
+
+	if ((rc = efx_mcdi_init(enp, emtp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	cv_destroy(&(smp->sm_kv));
+	mutex_destroy(&(smp->sm_lock));
+
+	smp->sm_state = SFXGE_MCDI_UNINITIALIZED;
+	smp->sm_sp = NULL;
+	SFXGE_OBJ_CHECK(smp, sfxge_mcdi_t);
+
+	return (rc);
+}
+
+
+void
+sfxge_mcdi_fini(sfxge_t *sp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	sfxge_mcdi_t *smp = &(sp->s_mcdi);
+	efx_mcdi_transport_t *emtp;
+
+	mutex_enter(&(smp->sm_lock));
+	ASSERT3U(smp->sm_state, ==, SFXGE_MCDI_INITIALIZED);
+
+	efx_mcdi_fini(enp);
+	emtp = &(smp->sm_emt);
+	bzero(emtp, sizeof (*emtp));
+
+	smp->sm_sp = NULL;
+
+	cv_destroy(&(smp->sm_kv));
+	mutex_exit(&(smp->sm_lock));
+
+	mutex_destroy(&(smp->sm_lock));
+
+	smp->sm_state = SFXGE_MCDI_UNINITIALIZED;
+	SFXGE_OBJ_CHECK(smp, sfxge_mcdi_t);
+}
+
+
+int
+sfxge_mcdi_ioctl(sfxge_t *sp, sfxge_mcdi_ioc_t *smip)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sp->s_enp);
+	sfxge_mcdi_t *smp = &(sp->s_mcdi);
+	efx_mcdi_req_t emr;
+	uint8_t *out;
+	int rc;
+
+	if (smp->sm_state == SFXGE_MCDI_UNINITIALIZED) {
+		rc = ENODEV;
+		goto fail1;
+	}
+
+	if (!(encp->enc_features & EFX_FEATURE_MCDI)) {
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if ((out = kmem_zalloc(sizeof (smip->smi_payload), KM_SLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail3;
+	}
+
+	emr.emr_cmd = smip->smi_cmd;
+	emr.emr_in_buf = smip->smi_payload;
+	emr.emr_in_length = smip->smi_len;
+
+	emr.emr_out_buf = out;
+	emr.emr_out_length = sizeof (smip->smi_payload);
+
+	sfxge_mcdi_execute(sp, &emr);
+
+	smip->smi_rc = (uint8_t)emr.emr_rc;
+	smip->smi_cmd = (uint8_t)emr.emr_cmd;
+	smip->smi_len = (uint8_t)emr.emr_out_length_used;
+	memcpy(smip->smi_payload, out, smip->smi_len);
+
+	/*
+	 * Helpfully trigger a device reset in response to an MCDI_CMD_REBOOT
+	 * Both ports will see ->emt_exception callbacks on the next MCDI poll
+	 */
+	if (smip->smi_cmd == MC_CMD_REBOOT) {
+
+		DTRACE_PROBE(mcdi_ioctl_mc_reboot);
+		/* sfxge_t->s_state_lock held */
+		(void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_OK,
+		    "MC_REBOOT triggering restart", 0);
+	}
+
+	kmem_free(out, sizeof (smip->smi_payload));
+
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	return (rc);
+}
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_mon.c	2013-08-22 18:57:34.373211404 -0400
@@ -0,0 +1,310 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/cyclic.h>
+
+#include "sfxge.h"
+
+#include "efx.h"
+
+/* Monitor DMA attributes */
+static ddi_device_acc_attr_t sfxge_mon_devacc = {
+
+	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
+	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
+	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
+};
+
+static ddi_dma_attr_t sfxge_mon_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	0x1000,			/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	1,			/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+
+static int
+sfxge_mon_kstat_update(kstat_t *ksp, int rw)
+{
+	sfxge_t *sp = ksp->ks_private;
+	sfxge_mon_t *smp = &(sp->s_mon);
+	efsys_mem_t *esmp = &(smp->sm_mem);
+	efx_nic_t *enp = sp->s_enp;
+	kstat_named_t *knp;
+	int rc, sn;
+
+	if (rw != KSTAT_READ) {
+		rc = EACCES;
+		goto fail1;
+	}
+
+	ASSERT(mutex_owned(&(smp->sm_lock)));
+
+	if (smp->sm_state != SFXGE_MON_STARTED)
+		goto done;
+
+	/* Synchronize the DMA memory for reading */
+	(void) ddi_dma_sync(smp->sm_mem.esm_dma_handle,
+	    0,
+	    EFX_MON_STATS_SIZE,
+	    DDI_DMA_SYNC_FORKERNEL);
+
+	if ((rc = efx_mon_stats_update(enp, esmp, smp->sm_statbuf)) != 0)
+		goto fail2;
+
+	knp = smp->sm_stat;
+	for (sn = 0; sn < EFX_MON_NSTATS; sn++) {
+		knp->value.ui64 = smp->sm_statbuf[sn].emsv_value;
+		knp++;
+	}
+
+	knp->value.ui32 = sp->s_num_restarts;
+	knp++;
+	knp->value.ui32 = sp->s_num_restarts_hw_err;
+	knp++;
+
+done:
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_mon_kstat_init(sfxge_t *sp)
+{
+	sfxge_mon_t *smp = &(sp->s_mon);
+	dev_info_t *dip = sp->s_dip;
+	efx_nic_t *enp = sp->s_enp;
+	kstat_t *ksp;
+	kstat_named_t *knp;
+	char name[MAXNAMELEN];
+	unsigned int id;
+	int rc;
+
+	if ((smp->sm_statbuf = kmem_zalloc(sizeof (uint32_t) * EFX_MON_NSTATS,
+	    KM_NOSLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_%s", ddi_driver_name(dip),
+	    efx_mon_name(enp));
+
+	/* Create the set */
+	if ((ksp = kstat_create((char *)ddi_driver_name(dip),
+	    ddi_get_instance(dip), name, "mon", KSTAT_TYPE_NAMED,
+	    EFX_MON_NSTATS+2, 0)) == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	smp->sm_ksp = ksp;
+
+	ksp->ks_update = sfxge_mon_kstat_update;
+	ksp->ks_private = sp;
+	ksp->ks_lock = &(smp->sm_lock);
+
+	/* Initialise the named stats */
+	smp->sm_stat = knp = ksp->ks_data;
+	for (id = 0; id < EFX_MON_NSTATS; id++) {
+		kstat_named_init(knp, (char *)efx_mon_stat_name(enp, id),
+		    KSTAT_DATA_UINT64);
+		knp++;
+	}
+	kstat_named_init(knp, "num_restarts", KSTAT_DATA_UINT32);
+	knp++;
+	kstat_named_init(knp, "num_restarts_hw_err", KSTAT_DATA_UINT32);
+	knp++;
+
+	kstat_install(ksp);
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+	kmem_free(smp->sm_statbuf, sizeof (uint32_t) * EFX_MON_NSTATS);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_mon_kstat_fini(sfxge_t *sp)
+{
+	sfxge_mon_t *smp = &(sp->s_mon);
+
+	/* Destroy the set */
+	kstat_delete(smp->sm_ksp);
+	smp->sm_ksp = NULL;
+	smp->sm_stat = NULL;
+
+	kmem_free(smp->sm_statbuf, sizeof (uint32_t) * EFX_MON_NSTATS);
+}
+
+int
+sfxge_mon_init(sfxge_t *sp)
+{
+	sfxge_mon_t *smp = &(sp->s_mon);
+	efx_nic_t *enp = sp->s_enp;
+	efsys_mem_t *esmp = &(smp->sm_mem);
+	sfxge_dma_buffer_attr_t dma_attr;
+	const efx_nic_cfg_t *encp;
+	int rc;
+
+	SFXGE_OBJ_CHECK(smp, sfxge_mon_t);
+
+	ASSERT3U(smp->sm_state, ==, SFXGE_MON_UNINITIALIZED);
+
+	smp->sm_sp = sp;
+
+	mutex_init(&(smp->sm_lock), NULL, MUTEX_DRIVER, NULL);
+
+	dma_attr.sdba_dip	 = sp->s_dip;
+	dma_attr.sdba_dattrp	 = &sfxge_mon_dma_attr;
+	dma_attr.sdba_callback	 = DDI_DMA_SLEEP;
+	dma_attr.sdba_length	 = EFX_MON_STATS_SIZE;
+	dma_attr.sdba_memflags	 = DDI_DMA_CONSISTENT;
+	dma_attr.sdba_devaccp	 = &sfxge_mon_devacc;
+	dma_attr.sdba_bindflags	 = DDI_DMA_READ | DDI_DMA_CONSISTENT;
+	dma_attr.sdba_maxcookies = 1;
+	dma_attr.sdba_zeroinit	 = B_TRUE;
+
+	if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
+		goto fail1;
+
+	encp = efx_nic_cfg_get(enp);
+	smp->sm_type = encp->enc_mon_type;
+
+	DTRACE_PROBE1(mon, efx_mon_type_t, smp->sm_type);
+
+	smp->sm_state = SFXGE_MON_INITIALIZED;
+
+	/* Initialize the statistics */
+	if ((rc = sfxge_mon_kstat_init(sp)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Tear down DMA setup */
+	sfxge_dma_buffer_destroy(esmp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	mutex_destroy(&(smp->sm_lock));
+
+	smp->sm_sp = NULL;
+
+	SFXGE_OBJ_CHECK(smp, sfxge_mac_t);
+
+	return (rc);
+}
+
+int
+sfxge_mon_start(sfxge_t *sp)
+{
+	sfxge_mon_t *smp = &(sp->s_mon);
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+	ASSERT3U(smp->sm_state, ==, SFXGE_MON_INITIALIZED);
+
+	/* Initialize the MON module */
+	if ((rc = efx_mon_init(sp->s_enp)) != 0)
+		goto fail1;
+
+	smp->sm_state = SFXGE_MON_STARTED;
+
+	mutex_exit(&(smp->sm_lock));
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+void
+sfxge_mon_stop(sfxge_t *sp)
+{
+	sfxge_mon_t *smp = &(sp->s_mon);
+
+	mutex_enter(&(smp->sm_lock));
+
+	ASSERT3U(smp->sm_state, ==, SFXGE_MON_STARTED);
+	smp->sm_state = SFXGE_MON_INITIALIZED;
+
+	/* Tear down the MON module */
+	efx_mon_fini(sp->s_enp);
+
+	mutex_exit(&(smp->sm_lock));
+}
+
+void
+sfxge_mon_fini(sfxge_t *sp)
+{
+	sfxge_mon_t *smp = &(sp->s_mon);
+	efsys_mem_t *esmp = &(smp->sm_mem);
+
+	ASSERT3U(smp->sm_state, ==, SFXGE_MON_INITIALIZED);
+
+	/* Tear down the statistics */
+	sfxge_mon_kstat_fini(sp);
+
+	smp->sm_state = SFXGE_MON_UNINITIALIZED;
+	mutex_destroy(&(smp->sm_lock));
+
+	smp->sm_sp = NULL;
+	smp->sm_type = EFX_MON_INVALID;
+
+	/* Tear down DMA setup */
+	sfxge_dma_buffer_destroy(esmp);
+
+	SFXGE_OBJ_CHECK(smp, sfxge_mon_t);
+}
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_nvram.c	2013-08-22 18:57:34.462366156 -0400
@@ -0,0 +1,193 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stream.h>
+#include <sys/dlpi.h>
+
+#include "sfxge.h"
+
+int
+sfxge_nvram_rw(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type,
+    boolean_t write)
+{
+	int (*op)(efx_nic_t *, efx_nvram_type_t, unsigned int, caddr_t, size_t);
+	efx_nic_t *enp = sp->s_enp;
+	size_t chunk_size;
+	off_t off;
+	int rc;
+
+	op = (write) ? efx_nvram_write_chunk : efx_nvram_read_chunk;
+
+	if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
+		goto fail1;
+
+	off = 0;
+	while (snip->sni_size) {
+		size_t len = MIN(chunk_size, snip->sni_size);
+		caddr_t buf = (caddr_t)(&snip->sni_data[off]);
+
+		if ((rc = op(enp, type, snip->sni_offset + off, buf, len)) != 0)
+			goto fail2;
+
+		snip->sni_size -= len;
+		off += len;
+	}
+
+	efx_nvram_rw_finish(enp, type);
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+	efx_nvram_rw_finish(enp, type);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	return (rc);
+}
+
+
+int
+sfxge_nvram_erase(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type)
+{
+	efx_nic_t *enp = sp->s_enp;
+	size_t chunk_size;
+	int rc;
+
+	if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
+		goto fail1;
+
+	if ((rc = efx_nvram_erase(enp, type)) != 0)
+		goto fail2;
+
+	efx_nvram_rw_finish(enp, type);
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+	efx_nvram_rw_finish(enp, type);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	return (rc);
+}
+
+int
+sfxge_nvram_ioctl(sfxge_t *sp, sfxge_nvram_ioc_t *snip)
+{
+	efx_nic_t *enp = sp->s_enp;
+	efx_nvram_type_t type;
+	int rc;
+
+	if (snip->sni_type == SFXGE_NVRAM_TYPE_MC_GOLDEN &&
+	    (snip->sni_op == SFXGE_NVRAM_OP_WRITE ||
+	    snip->sni_op == SFXGE_NVRAM_OP_ERASE ||
+	    snip->sni_op == SFXGE_NVRAM_OP_SET_VER)) {
+		rc = ENOTSUP;
+		goto fail4;
+	}
+
+	switch (snip->sni_type) {
+	case SFXGE_NVRAM_TYPE_BOOTROM:
+		type = EFX_NVRAM_BOOTROM;
+		break;
+	case SFXGE_NVRAM_TYPE_BOOTROM_CFG:
+		type = EFX_NVRAM_BOOTROM_CFG;
+		break;
+	case SFXGE_NVRAM_TYPE_MC:
+		type = EFX_NVRAM_MC_FIRMWARE;
+		break;
+	case SFXGE_NVRAM_TYPE_MC_GOLDEN:
+		type = EFX_NVRAM_MC_GOLDEN;
+		break;
+	case SFXGE_NVRAM_TYPE_PHY:
+		type = EFX_NVRAM_PHY;
+		break;
+	case SFXGE_NVRAM_TYPE_NULL_PHY:
+		type = EFX_NVRAM_NULLPHY;
+		break;
+	case SFXGE_NVRAM_TYPE_FPGA: /* PTP timestamping FPGA */
+		type = EFX_NVRAM_FPGA;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (snip->sni_size > sizeof (snip->sni_data)) {
+		rc = ENOSPC;
+		goto fail2;
+	}
+
+	switch (snip->sni_op) {
+	case SFXGE_NVRAM_OP_SIZE:
+	{
+		size_t size;
+		if ((rc = efx_nvram_size(enp, type, &size)) != 0)
+			goto fail3;
+		snip->sni_size = size;
+		break;
+	}
+	case SFXGE_NVRAM_OP_READ:
+		if ((rc = sfxge_nvram_rw(sp, snip, type, B_FALSE)) != 0)
+			goto fail3;
+		break;
+	case SFXGE_NVRAM_OP_WRITE:
+		if ((rc = sfxge_nvram_rw(sp, snip, type, B_TRUE)) != 0)
+			goto fail3;
+		break;
+	case SFXGE_NVRAM_OP_ERASE:
+		if ((rc = sfxge_nvram_erase(sp, snip, type)) != 0)
+			goto fail3;
+		break;
+	case SFXGE_NVRAM_OP_GET_VER:
+		if ((rc = efx_nvram_get_version(enp, type, &snip->sni_subtype,
+		    &snip->sni_version[0])) != 0)
+			goto fail3;
+		break;
+	case SFXGE_NVRAM_OP_SET_VER:
+		if ((rc = efx_nvram_set_version(enp, type,
+		    &snip->sni_version[0])) != 0)
+			goto fail3;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail4;
+	}
+
+	return (0);
+
+fail4:
+	DTRACE_PROBE(fail4);
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_pci.c	2013-08-22 18:57:34.548467830 -0400
@@ -0,0 +1,232 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/pci.h>
+#include <sys/pcie.h>
+
+/* PCIe 2.0 link speeds */
+#ifndef PCIE_LINKCAP_MAX_SPEED_5_0
+#define	PCIE_LINKCAP_MAX_SPEED_5_0	0x2
+#endif
+#ifndef PCIE_LINKSTS_SPEED_5_0
+#define	PCIE_LINKSTS_SPEED_5_0		0x2
+#endif
+
+#include "sfxge.h"
+
+int
+sfxge_pci_cap_find(sfxge_t *sp, uint8_t cap_id, off_t *offp)
+{
+	off_t off;
+	uint16_t stat;
+	int rc;
+
+	stat = pci_config_get16(sp->s_pci_handle, PCI_CONF_STAT);
+
+	if (!(stat & PCI_STAT_CAP)) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	for (off = pci_config_get8(sp->s_pci_handle, PCI_CONF_CAP_PTR);
+	    off != PCI_CAP_NEXT_PTR_NULL;
+	    off = pci_config_get8(sp->s_pci_handle, off + PCI_CAP_NEXT_PTR)) {
+		if (cap_id == pci_config_get8(sp->s_pci_handle,
+		    off + PCI_CAP_ID))
+			goto done;
+	}
+
+	rc = ENOENT;
+	goto fail2;
+
+done:
+	*offp = off;
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+int
+sfxge_pci_init(sfxge_t *sp)
+{
+	off_t off;
+	uint16_t pciecap;
+	uint16_t devctl;
+	uint16_t linksts;
+	uint16_t max_payload_size;
+	uint16_t max_read_request;
+	int rc;
+
+	if (pci_config_setup(sp->s_dip, &(sp->s_pci_handle)) != DDI_SUCCESS) {
+		rc = ENODEV;
+		goto fail1;
+	}
+
+	sp->s_pci_venid = pci_config_get16(sp->s_pci_handle, PCI_CONF_VENID);
+	sp->s_pci_devid = pci_config_get16(sp->s_pci_handle, PCI_CONF_DEVID);
+	if ((rc = efx_family(sp->s_pci_venid, sp->s_pci_devid,
+	    &sp->s_family)) != 0)
+		goto fail2;
+
+	if ((rc = sfxge_pci_cap_find(sp, PCI_CAP_ID_PCI_E, &off)) != 0)
+		goto fail3;
+
+	pciecap = pci_config_get16(sp->s_pci_handle, off + PCIE_PCIECAP);
+	ASSERT3U((pciecap & PCIE_PCIECAP_VER_MASK), >=, PCIE_PCIECAP_VER_1_0);
+
+	linksts = pci_config_get16(sp->s_pci_handle, off + PCIE_LINKSTS);
+	switch (linksts & PCIE_LINKSTS_NEG_WIDTH_MASK) {
+	case PCIE_LINKSTS_NEG_WIDTH_X1:
+		sp->s_pcie_nlanes = 1;
+		break;
+
+	case PCIE_LINKSTS_NEG_WIDTH_X2:
+		sp->s_pcie_nlanes = 2;
+		break;
+
+	case PCIE_LINKSTS_NEG_WIDTH_X4:
+		sp->s_pcie_nlanes = 4;
+		break;
+
+	case PCIE_LINKSTS_NEG_WIDTH_X8:
+		sp->s_pcie_nlanes = 8;
+		break;
+
+	default:
+		ASSERT(B_FALSE);
+		break;
+	}
+
+	switch (linksts & PCIE_LINKSTS_SPEED_MASK) {
+	case PCIE_LINKSTS_SPEED_2_5:
+		sp->s_pcie_linkspeed = 1;
+		break;
+
+	case PCIE_LINKSTS_SPEED_5_0:
+		sp->s_pcie_linkspeed = 2;
+		break;
+
+	default:
+		ASSERT(B_FALSE);
+		break;
+	}
+
+	devctl = pci_config_get16(sp->s_pci_handle, off + PCIE_DEVCTL);
+
+	max_payload_size = (devctl & PCIE_DEVCTL_MAX_PAYLOAD_MASK)
+	    >> PCIE_DEVCTL_MAX_PAYLOAD_SHIFT;
+
+	max_read_request = (devctl & PCIE_DEVCTL_MAX_READ_REQ_MASK)
+	    >> PCIE_DEVCTL_MAX_READ_REQ_SHIFT;
+
+	cmn_err(CE_NOTE,
+	    SFXGE_CMN_ERR "PCIe MRR: %d TLP: %d Link: %s Lanes: x%d",
+	    128 << max_read_request,
+	    128 << max_payload_size,
+	    (sp->s_pcie_linkspeed == 1) ? "2.5G" :
+	    (sp->s_pcie_linkspeed == 2) ? "5.0G" :
+	    "UNKNOWN",
+	    sp->s_pcie_nlanes);
+
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+
+	pci_config_teardown(&(sp->s_pci_handle));
+	sp->s_pci_handle = NULL;
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_pcie_check_link(sfxge_t *sp, unsigned int full_nlanes,
+	unsigned int full_speed)
+{
+	if ((sp->s_pcie_linkspeed < full_speed) ||
+	    (sp->s_pcie_nlanes    < full_nlanes))
+		cmn_err(CE_NOTE,
+		    SFXGE_CMN_ERR "The %s%d device requires %d PCIe lanes "
+		    "at %s link speed to reach full bandwidth.",
+		    ddi_driver_name(sp->s_dip),
+		    ddi_get_instance(sp->s_dip),
+		    full_nlanes,
+		    (full_speed == 1) ? "2.5G" :
+		    (full_speed == 2) ? "5.0G" :
+		    "UNKNOWN");
+}
+
+int
+sfxge_pci_ioctl(sfxge_t *sp, sfxge_pci_ioc_t *spip)
+{
+	int rc;
+
+	switch (spip->spi_op) {
+	case SFXGE_PCI_OP_READ:
+		spip->spi_data = pci_config_get8(sp->s_pci_handle,
+		    spip->spi_addr);
+		break;
+
+	case SFXGE_PCI_OP_WRITE:
+		pci_config_put8(sp->s_pci_handle,
+		    spip->spi_addr, spip->spi_data);
+		break;
+
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (0);
+}
+
+void
+sfxge_pci_fini(sfxge_t *sp)
+{
+	sp->s_pcie_nlanes = 0;
+	sp->s_pcie_linkspeed = 0;
+
+	pci_config_teardown(&(sp->s_pci_handle));
+	sp->s_pci_handle = NULL;
+}
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_phy.c	2013-08-22 18:57:34.634792687 -0400
@@ -0,0 +1,626 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/cyclic.h>
+
+#include "sfxge.h"
+#include "efx.h"
+
+/*
+ * All efx_phy_*() must be after efx_port_init()
+ *
+ * LOCKING STRATEGY: Aquire sm_lock and test sm_state==SFXGE_MAC_STARTED
+ * to serialise against sfxge_restart()
+ *
+ * Note that there is no seperate PHY lock
+ * Everything is driven from MAC code and the MAC lock is used
+ */
+
+/* PHY DMA attributes */
+static ddi_device_acc_attr_t sfxge_phy_devacc = {
+
+	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
+	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
+	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
+};
+
+static ddi_dma_attr_t sfxge_phy_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	0x1000,			/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	1,			/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+
+/* The common code requires the loader *without* the REFLASH_HEADER */
+#if EFSYS_OPT_FALCON && EFSYS_OPT_NVRAM_SFT9001
+static const uint8_t SFT9001_FULL_LOADER[] = {
+#include "firmware/image.h"
+#include "firmware/SFT9001A_LOADER.c"
+};
+const uint8_t * const sft9001_loader = SFT9001_FULL_LOADER +
+    sizeof (image_header_t);
+const size_t sft9001_loader_size = sizeof (SFT9001_FULL_LOADER) -
+    sizeof (image_header_t);
+#endif
+
+#if EFSYS_OPT_FALCON && EFSYS_OPT_NVRAM_SFX7101
+static const uint8_t SFX7101_FULL_LOADER[] = {
+#include "firmware/image.h"
+#include "firmware/SFX7101B_LOADER.c"
+};
+const uint8_t * const sfx7101_loader = SFX7101_FULL_LOADER +
+    sizeof (image_header_t);
+const size_t sfx7101_loader_size = sizeof (SFX7101_FULL_LOADER) -
+    sizeof (image_header_t);
+#endif
+
+
+static int
+sfxge_phy_kstat_update(kstat_t *ksp, int rw)
+{
+	sfxge_t *sp = ksp->ks_private;
+	sfxge_mac_t *smp = &(sp->s_mac);
+	sfxge_phy_t *spp = &(smp->sm_phy);
+	efx_nic_t *enp = sp->s_enp;
+	kstat_named_t *knp;
+	const efx_nic_cfg_t *encp;
+	int rc, sn;
+
+	if (rw != KSTAT_READ) {
+		rc = EACCES;
+		goto fail1;
+	}
+
+	ASSERT(mutex_owned(&(smp->sm_lock)));
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	/* Synchronize the DMA memory for reading */
+	(void) ddi_dma_sync(spp->sp_mem.esm_dma_handle,
+	    0,
+	    EFX_PHY_STATS_SIZE,
+	    DDI_DMA_SYNC_FORKERNEL);
+
+	if ((rc = efx_phy_stats_update(enp, &spp->sp_mem, spp->sp_statbuf))
+	    != 0)
+		goto fail2;
+
+	knp = spp->sp_stat;
+	for (sn = 0; sn < EFX_PHY_NSTATS; sn++) {
+		knp->value.ui64 = spp->sp_statbuf[sn];
+		knp++;
+	}
+
+	encp = efx_nic_cfg_get(enp);
+	knp->value.ui64 = encp->enc_port;
+
+done:
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+int
+sfxge_phy_kstat_init(sfxge_t *sp)
+{
+	dev_info_t *dip = sp->s_dip;
+	sfxge_phy_t *spp = &(sp->s_mac.sm_phy);
+	efx_nic_t *enp = sp->s_enp;
+	kstat_t *ksp;
+	kstat_named_t *knp;
+	const efx_nic_cfg_t *encp;
+	unsigned int id;
+	char name[MAXNAMELEN];
+	int rc;
+
+	if ((spp->sp_statbuf = kmem_zalloc(sizeof (uint32_t) * EFX_PHY_NSTATS,
+	    KM_NOSLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	encp = efx_nic_cfg_get(enp);
+
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_%s", ddi_driver_name(dip),
+	    encp->enc_phy_name);
+
+	/* Create the set */
+	if ((ksp = kstat_create((char *)ddi_driver_name(dip),
+	    ddi_get_instance(dip), name, "phy", KSTAT_TYPE_NAMED,
+	    EFX_PHY_NSTATS + 1, 0)) == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	spp->sp_ksp = ksp;
+
+	ksp->ks_update = sfxge_phy_kstat_update;
+	ksp->ks_private = sp;
+	ksp->ks_lock = &(sp->s_mac.sm_lock);
+
+	/* Initialise the named stats */
+	spp->sp_stat = knp = ksp->ks_data;
+	for (id = 0; id < EFX_PHY_NSTATS; id++) {
+		kstat_named_init(knp, (char *)efx_phy_stat_name(enp, id),
+		    KSTAT_DATA_UINT64);
+		knp++;
+	}
+
+	kstat_named_init(knp, "port", KSTAT_DATA_UINT64);
+	kstat_install(ksp);
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2)
+	kmem_free(spp->sp_statbuf, sizeof (uint32_t) * EFX_PHY_NSTATS);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_phy_kstat_fini(sfxge_t *sp)
+{
+	sfxge_phy_t *spp = &(sp->s_mac.sm_phy);
+
+	/* Destroy the set */
+	kstat_delete(spp->sp_ksp);
+	spp->sp_ksp = NULL;
+	spp->sp_stat = NULL;
+
+	kmem_free(spp->sp_statbuf, sizeof (uint32_t) * EFX_PHY_NSTATS);
+}
+
+
+int
+sfxge_phy_init(sfxge_t *sp)
+{
+	sfxge_phy_t *spp = &(sp->s_mac.sm_phy);
+	efsys_mem_t *esmp = &(spp->sp_mem);
+	sfxge_dma_buffer_attr_t dma_attr;
+	int rc;
+
+	dma_attr.sdba_dip	 = sp->s_dip;
+	dma_attr.sdba_dattrp	 = &sfxge_phy_dma_attr;
+	dma_attr.sdba_callback	 = DDI_DMA_SLEEP;
+	dma_attr.sdba_length	 = EFX_PHY_STATS_SIZE;
+	dma_attr.sdba_memflags	 = DDI_DMA_CONSISTENT;
+	dma_attr.sdba_devaccp	 = &sfxge_phy_devacc;
+	dma_attr.sdba_bindflags	 = DDI_DMA_READ | DDI_DMA_CONSISTENT;
+	dma_attr.sdba_maxcookies = 1;
+	dma_attr.sdba_zeroinit	 = B_TRUE;
+
+	if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	SFXGE_OBJ_CHECK(spp, sfxge_phy_t);
+
+	return (rc);
+}
+
+static int
+sfxge_phy_led_mode_set(sfxge_t *sp, efx_phy_led_mode_t mode)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	int rc;
+
+	ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
+
+	if (mode >= EFX_PHY_LED_NMODES) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	mutex_enter(&(smp->sm_lock));
+
+	if ((rc = efx_phy_led_set(sp->s_enp, mode)) != 0)
+		goto fail2;
+
+	mutex_exit(&(smp->sm_lock));
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	mutex_exit(&(smp->sm_lock));
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+int
+sfxge_phy_ioctl(sfxge_t *sp, sfxge_phy_ioc_t *spip)
+{
+	int rc;
+
+	switch (spip->spi_op) {
+	case SFXGE_PHY_OP_LINK: {
+		break;
+	}
+	case SFXGE_PHY_OP_LED: {
+		efx_phy_led_mode_t mode = spip->spi_data;
+
+		if ((rc = sfxge_phy_led_mode_set(sp, mode)) != 0)
+			goto fail1;
+
+		break;
+	}
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+static uint8_t
+bist_status(unsigned long value)
+{
+	uint8_t ret;
+
+	efx_phy_cable_status_t status = (efx_phy_cable_status_t)value;
+	switch (status) {
+	case EFX_PHY_CABLE_STATUS_OK:
+		ret = SFXGE_PHY_BIST_CABLE_OK;
+		break;
+	case EFX_PHY_CABLE_STATUS_INVALID:
+		ret =  SFXGE_PHY_BIST_CABLE_INVALID;
+		break;
+	case EFX_PHY_CABLE_STATUS_OPEN:
+		ret = SFXGE_PHY_BIST_CABLE_OPEN;
+		break;
+	case EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT:
+		ret = SFXGE_PHY_BIST_CABLE_INTRAPAIRSHORT;
+		break;
+	case EFX_PHY_CABLE_STATUS_INTERPAIRSHORT:
+		ret = SFXGE_PHY_BIST_CABLE_INTERPAIRSHORT;
+		break;
+	case EFX_PHY_CABLE_STATUS_BUSY:
+		ret = SFXGE_PHY_BIST_CABLE_BUSY;
+		break;
+	default:
+		ret = SFXGE_PHY_BIST_CABLE_UNKNOWN;
+	}
+
+	return (ret);
+}
+
+
+int
+sfxge_phy_bist_ioctl(sfxge_t *sp, sfxge_phy_bist_ioc_t *spbip)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_phy_bist_type_t bist_type;
+	efx_nic_t *enp;
+	const efx_nic_cfg_t *encp;
+	efx_phy_bist_result_t result;
+	unsigned long values[EFX_PHY_BIST_NVALUES];
+	uint32_t mask;
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+	enp = sp->s_enp;
+	encp = efx_nic_cfg_get(enp);
+
+	bist_type = spbip->spbi_break_link ? EFX_PHY_BIST_TYPE_CABLE_LONG :
+	    EFX_PHY_BIST_TYPE_CABLE_SHORT;
+
+	if (~encp->enc_bist_mask & (1 << bist_type)) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = efx_phy_bist_start(enp, bist_type)) != 0)
+		goto fail2;
+
+	do {
+		/* Spin for 1 ms */
+		drv_usecwait(1000);
+
+		if ((rc = efx_phy_bist_poll(enp, bist_type, &result, &mask,
+		    values, sizeof (values) / sizeof (values[0]))) != 0)
+			goto fail3;
+
+		ASSERT3U(result, !=, EFX_PHY_BIST_RESULT_UNKNOWN);
+
+	} while (result == EFX_PHY_BIST_RESULT_RUNNING);
+
+	ASSERT3U(mask, ==, ((1 << EFX_PHY_BIST_CABLE_LENGTH_A) |
+			    (1 << EFX_PHY_BIST_CABLE_LENGTH_B) |
+			    (1 << EFX_PHY_BIST_CABLE_LENGTH_C) |
+			    (1 << EFX_PHY_BIST_CABLE_LENGTH_D) |
+			    (1 << EFX_PHY_BIST_CABLE_STATUS_A) |
+			    (1 << EFX_PHY_BIST_CABLE_STATUS_B) |
+			    (1 << EFX_PHY_BIST_CABLE_STATUS_C) |
+			    (1 << EFX_PHY_BIST_CABLE_STATUS_D)));
+
+	spbip->spbi_status_a = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_A]);
+	spbip->spbi_status_b = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_B]);
+	spbip->spbi_status_c = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_C]);
+	spbip->spbi_status_d = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_D]);
+
+	spbip->spbi_length_ind_a =
+	    (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_A];
+	spbip->spbi_length_ind_b =
+	    (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_B];
+	spbip->spbi_length_ind_c =
+	    (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_C];
+	spbip->spbi_length_ind_d =
+	    (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_D];
+
+	/* Bring the PHY back to life */
+	efx_phy_bist_stop(enp, bist_type);
+
+	mutex_exit(&(smp->sm_lock));
+
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+	efx_phy_bist_stop(enp, bist_type);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	mutex_exit(&(smp->sm_lock));
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+uint8_t
+sfxge_phy_lp_cap_test(sfxge_t *sp, uint32_t field)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	uint32_t cap = 0;
+
+	mutex_enter(&(smp->sm_lock));
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	efx_phy_lp_cap_get(sp->s_enp, &cap);
+
+done:
+	mutex_exit(&(smp->sm_lock));
+
+	return (cap & (1 << field));
+}
+
+/*
+ * Set up the advertised capabilities that may have been asked for
+ * when the mac was not in the state SFXGE_MAC_STARTED.
+ * Must be called after efx_port_init().
+ */
+int
+sfxge_phy_cap_apply(sfxge_t *sp, boolean_t use_default)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp;
+	uint32_t adv_cap;
+	int rc;
+	int err;
+
+	ASSERT(mutex_owned(&(smp->sm_lock)));
+
+	enp = sp->s_enp;
+
+	if (use_default)
+		efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &adv_cap);
+	else
+		efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &adv_cap);
+
+	adv_cap |= smp->sm_phy_cap_to_set;
+	smp->sm_phy_cap_to_set = 0;
+	adv_cap &= ~(smp->sm_phy_cap_to_unset);
+	smp->sm_phy_cap_to_unset = 0;
+	if ((err = efx_phy_adv_cap_set(enp, adv_cap)) != 0) {
+		if (err == EINVAL) {
+			/*
+			 * The configuation wasn't accepted, so set to
+			 * defaults.
+			 */
+			uint32_t requested = adv_cap;
+			uint32_t supported;
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_PERM, &supported);
+			efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &adv_cap);
+			if ((rc = efx_phy_adv_cap_set(enp, adv_cap)) != 0)
+				goto fail1;
+			cmn_err(CE_WARN, SFXGE_CMN_ERR
+			    "[%s%d] Setting of advertised link "
+			    "capabilities failed. "
+			    "Using default settings. "
+			    "(Requested 0x%x Given 0x%x Supported 0x%x)",
+			    ddi_driver_name(sp->s_dip),
+			    ddi_get_instance(sp->s_dip),
+			    requested,
+			    adv_cap,
+			    supported);
+		} else {
+			rc = err;
+			goto fail2;
+		}
+	}
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+uint8_t
+sfxge_phy_cap_test(sfxge_t *sp, uint32_t flag, uint32_t field,
+	boolean_t *mutablep)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp;
+	uint32_t cap = 0;
+	uint32_t perm = 0;
+
+	mutex_enter(&(smp->sm_lock));
+	enp = sp->s_enp;
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	efx_phy_adv_cap_get(enp, flag, &cap);
+	efx_phy_adv_cap_get(enp, EFX_PHY_CAP_PERM, &perm);
+
+done:
+	mutex_exit(&(smp->sm_lock));
+
+	if (mutablep)
+		*mutablep = (perm & (1 << field)) ? B_TRUE : B_FALSE;
+
+	return ((cap & (1 << field)) ? 1 : 0);
+}
+
+
+int
+sfxge_phy_cap_set(sfxge_t *sp, uint32_t field, int set)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp = sp->s_enp;
+	uint32_t cap;
+	int rc = 0;
+
+	mutex_enter(&(smp->sm_lock));
+
+	if (smp->sm_state != SFXGE_MAC_STARTED) {
+		/* Store the request for when the mac is started */
+		if (set)
+			smp->sm_phy_cap_to_set |= (1 << field);
+		else
+			smp->sm_phy_cap_to_unset |= (1 << field);
+		goto done;
+	}
+
+	efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &cap);
+
+	if (set)
+		cap |= (1 << field);
+	else
+		cap &= ~(1 << field);
+
+	rc = efx_phy_adv_cap_set(enp, cap);
+done:
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+
+int
+sfxge_phy_prop_get(sfxge_t *sp, unsigned int id, uint32_t flags, uint32_t *valp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp = sp->s_enp;
+	int rc = 0;
+
+	mutex_enter(&(smp->sm_lock));
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	rc = efx_phy_prop_get(enp, id, flags, valp);
+
+done:
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+
+int
+sfxge_phy_prop_set(sfxge_t *sp, unsigned int id, uint32_t val)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	efx_nic_t *enp = sp->s_enp;
+	int rc = 0;
+
+	mutex_enter(&(smp->sm_lock));
+
+	if (smp->sm_state != SFXGE_MAC_STARTED)
+		goto done;
+
+	rc = efx_phy_prop_set(enp, id, val);
+
+done:
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+
+void
+sfxge_phy_fini(sfxge_t *sp)
+{
+	sfxge_phy_t *spp = &(sp->s_mac.sm_phy);
+	efsys_mem_t *esmp = &(spp->sp_mem);
+
+	sfxge_dma_buffer_destroy(esmp);
+}
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_rx.c	2013-08-22 18:57:34.726123847 -0400
@@ -0,0 +1,2965 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/atomic.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/strft.h>
+#include <sys/ksynch.h>
+#include <sys/ethernet.h>
+#include <sys/crc32.h>
+#include <sys/pattr.h>
+#include <sys/cpu.h>
+
+#include <sys/ethernet.h>
+#include <inet/ip.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include "sfxge.h"
+
+#include "efx.h"
+
+/* RXQ flush response timeout (in microseconds) */
+#define	SFXGE_RX_QFLUSH_USEC	(2000000)
+
+/* RXQ default packet buffer preallocation (number of packet buffers) */
+#define	SFXGE_RX_QPREALLOC	(0)
+
+/* Receive packet DMA attributes */
+static ddi_device_acc_attr_t sfxge_rx_packet_devacc = {
+
+	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
+	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
+	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
+};
+
+static ddi_dma_attr_t sfxge_rx_packet_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	SFXGE_CPU_CACHE_SIZE,	/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	1,			/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+/* Receive queue DMA attributes */
+static ddi_device_acc_attr_t sfxge_rxq_devacc = {
+
+	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
+	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
+	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
+};
+
+static ddi_dma_attr_t sfxge_rxq_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	EFX_BUF_SIZE,		/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	1,			/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+/* Forward declaration */
+static int
+sfxge_rx_qpreallocate(sfxge_rxq_t *srp, int nprealloc);
+
+static int
+sfxge_rx_packet_ctor(void *buf, void *arg, int kmflags)
+{
+	sfxge_rx_packet_t *srpp = buf;
+	sfxge_t *sp = arg;
+	dev_info_t *dip = sp->s_dip;
+	int err;
+
+	ASSERT3U(sizeof (srpp->__srp_u1.__srp_s1), <=,
+	    sizeof (srpp->__srp_u1.__srp_pad));
+	ASSERT3U(sizeof (srpp->__srp_u2.__srp_s2), <=,
+	    sizeof (srpp->__srp_u2.__srp_pad));
+
+	bzero(buf, sizeof (sfxge_rx_packet_t));
+
+	/* Allocate a DMA handle */
+	err = ddi_dma_alloc_handle(dip, &sfxge_rx_packet_dma_attr,
+	    (kmflags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
+	    NULL, &(srpp->srp_dma_handle));
+	if (err != DDI_SUCCESS)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, err);
+
+	SFXGE_OBJ_CHECK(srpp, sfxge_rx_packet_t);
+
+	return (-1);
+}
+
+static void
+sfxge_rx_packet_dtor(void *buf, void *arg)
+{
+	sfxge_rx_packet_t *srpp = buf;
+
+	_NOTE(ARGUNUSED(arg))
+
+	/* Free the DMA handle */
+	ddi_dma_free_handle(&(srpp->srp_dma_handle));
+	srpp->srp_dma_handle = NULL;
+
+	SFXGE_OBJ_CHECK(srpp, sfxge_rx_packet_t);
+}
+
+static int
+sfxge_rx_qctor(void *buf, void *arg, int kmflags)
+{
+	sfxge_rxq_t *srp = buf;
+	efsys_mem_t *esmp = &(srp->sr_mem);
+	sfxge_t *sp = arg;
+	sfxge_dma_buffer_attr_t dma_attr;
+	sfxge_rx_fpp_t *srfppp;
+	int nprealloc;
+	unsigned int id;
+	int rc;
+
+	/* Compile-time structure layout checks */
+	EFX_STATIC_ASSERT(sizeof (srp->__sr_u1.__sr_s1) <=
+	    sizeof (srp->__sr_u1.__sr_pad));
+	EFX_STATIC_ASSERT(sizeof (srp->__sr_u2.__sr_s2) <=
+	    sizeof (srp->__sr_u2.__sr_pad));
+	EFX_STATIC_ASSERT(sizeof (srp->__sr_u3.__sr_s3) <=
+	    sizeof (srp->__sr_u3.__sr_pad));
+
+	bzero(buf, sizeof (sfxge_rxq_t));
+
+	srp->sr_sp = sp;
+
+	dma_attr.sdba_dip	 = sp->s_dip;
+	dma_attr.sdba_dattrp	 = &sfxge_rxq_dma_attr;
+	dma_attr.sdba_callback	 = DDI_DMA_SLEEP;
+	dma_attr.sdba_length	 = EFX_RXQ_SIZE(sp->s_rxq_size);
+	dma_attr.sdba_memflags	 = DDI_DMA_CONSISTENT;
+	dma_attr.sdba_devaccp	 = &sfxge_rxq_devacc;
+	dma_attr.sdba_bindflags	 = DDI_DMA_READ | DDI_DMA_CONSISTENT;
+	dma_attr.sdba_maxcookies = 1;
+	dma_attr.sdba_zeroinit	 = B_FALSE;
+
+	if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
+		goto fail1;
+
+	/* Allocate some buffer table entries */
+	if ((rc = sfxge_sram_buf_tbl_alloc(sp, EFX_RXQ_NBUFS(sp->s_rxq_size),
+	    &(srp->sr_id))) != 0)
+		goto fail2;
+
+	/* Allocate the context array */
+	if ((srp->sr_srpp = kmem_zalloc(sizeof (sfxge_rx_packet_t *) *
+	    sp->s_rxq_size, kmflags)) == NULL) {
+		rc = ENOMEM;
+		goto fail3;
+	}
+
+	/* Allocate the flow table */
+	if ((srp->sr_flow = kmem_zalloc(sizeof (sfxge_rx_flow_t) *
+	    SFXGE_MAX_FLOW, kmflags)) == NULL) {
+		rc = ENOMEM;
+		goto fail4;
+	}
+
+	srp->sr_srfpp = &(srp->sr_srfp);
+	srp->sr_rto = drv_usectohz(200000);
+
+	srp->sr_mpp = &(srp->sr_mp);
+
+	/* Initialize the free packet pool */
+	srfppp = &(srp->sr_fpp);
+	if ((srfppp->srfpp_putp = kmem_zalloc(SFXGE_CPU_CACHE_SIZE *
+		SFXGE_RX_FPP_NSLOTS, kmflags)) == NULL) {
+		rc = ENOMEM;
+		goto fail5;
+	}
+	for (id = 0; id < SFXGE_RX_FPP_NSLOTS; id++) {
+		sfxge_rx_fpp_putlist_t *putp;
+		size_t off;
+
+		off = id * SFXGE_CPU_CACHE_SIZE;
+		putp = (void *)(srfppp->srfpp_putp + off);
+
+		putp->srfpl_putp = NULL;
+		putp->srfpl_putpp = &(putp->srfpl_putp);
+		mutex_init(&(putp->srfpl_lock), NULL, MUTEX_DRIVER,
+		    DDI_INTR_PRI(sp->s_intr.si_intr_pri));
+	}
+
+	cv_init(&(srp->sr_flush_kv), NULL, CV_DRIVER, NULL);
+
+	/* Preallocate some packets on the free packet pool */
+	nprealloc = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "rx_prealloc_pkt_buffers", SFXGE_RX_QPREALLOC);
+	sfxge_rx_qpreallocate(srp, nprealloc);
+
+
+	return (0);
+
+fail5:
+	DTRACE_PROBE(fail5);
+
+	srp->sr_mpp = NULL;
+
+	srp->sr_rto = 0;
+	srp->sr_srfpp = NULL;
+
+	/* Free the flow table */
+	kmem_free(srp->sr_flow, sizeof (sfxge_rx_flow_t) *
+	    SFXGE_MAX_FLOW);
+	srp->sr_flow = NULL;
+
+fail4:
+	DTRACE_PROBE(fail4);
+
+	/* Free the context array */
+	kmem_free(srp->sr_srpp, sizeof (sfxge_rx_packet_t *) *
+	    sp->s_rxq_size);
+	srp->sr_srpp = NULL;
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	/* Free the buffer table entries */
+	sfxge_sram_buf_tbl_free(sp, srp->sr_id,
+	    EFX_RXQ_NBUFS(sp->s_rxq_size));
+	srp->sr_id = 0;
+
+fail2:
+	DTRACE_PROBE(fail2);
+	/* Remove dma setup */
+	sfxge_dma_buffer_destroy(esmp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	srp->sr_sp = NULL;
+
+	SFXGE_OBJ_CHECK(srp, sfxge_rxq_t);
+
+	return (-1);
+}
+
+static void
+sfxge_rx_qdtor(void *buf, void *arg)
+{
+	sfxge_rxq_t *srp = buf;
+	efsys_mem_t *esmp = &(srp->sr_mem);
+	sfxge_t *sp = srp->sr_sp;
+	sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
+	unsigned int id;
+
+	_NOTE(ARGUNUSED(arg))
+
+	cv_destroy(&(srp->sr_flush_kv));
+
+	/* Tear down the free packet pool */
+	for (id = 0; id < SFXGE_RX_FPP_NSLOTS; id++) {
+		sfxge_rx_fpp_putlist_t *putp;
+		size_t off;
+
+		off = id * SFXGE_CPU_CACHE_SIZE;
+		putp = (void *)(srfppp->srfpp_putp + off);
+
+		putp->srfpl_putpp = NULL;
+		mutex_destroy(&(putp->srfpl_lock));
+
+		SFXGE_OBJ_CHECK(putp, sfxge_rx_fpp_putlist_t);
+	}
+	kmem_free(srfppp->srfpp_putp, SFXGE_CPU_CACHE_SIZE *
+	    SFXGE_RX_FPP_NSLOTS);
+	srfppp->srfpp_putp = NULL;
+
+	srp->sr_mpp = NULL;
+
+	srp->sr_rto = 0;
+	srp->sr_srfpp = NULL;
+
+	/* Free the flow table */
+	kmem_free(srp->sr_flow, sizeof (sfxge_rx_flow_t) *
+	    SFXGE_MAX_FLOW);
+	srp->sr_flow = NULL;
+
+	/* Free the context array */
+	kmem_free(srp->sr_srpp, sizeof (sfxge_rx_packet_t *) *
+	    sp->s_rxq_size);
+	srp->sr_srpp = NULL;
+
+	/* Free the buffer table entries */
+	sfxge_sram_buf_tbl_free(sp, srp->sr_id,
+	    EFX_RXQ_NBUFS(sp->s_rxq_size));
+	srp->sr_id = 0;
+
+	/* Tear down dma setup */
+	sfxge_dma_buffer_destroy(esmp);
+
+	SFXGE_OBJ_CHECK(srp, sfxge_rxq_t);
+}
+
+/* Note: This function takes ownership of *srpp. */
+static inline void
+sfxge_rx_qfpp_put(sfxge_rxq_t *srp, sfxge_rx_packet_t *srpp)
+{
+	sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
+	mblk_t *mp = srpp->srp_mp;
+	unsigned int id;
+	size_t off;
+	sfxge_rx_fpp_putlist_t *putp;
+
+	ASSERT3P(mp->b_next, ==, NULL);
+	ASSERT3P(mp->b_prev, ==, NULL);
+
+	id = CPU->cpu_seqid & SFXGE_RX_FPP_MASK;
+	off = id * SFXGE_CPU_CACHE_SIZE;
+
+	ASSERT3P(srpp->srp_putp, ==, srfppp->srfpp_putp);
+	putp = (void *)(srpp->srp_putp + off);
+
+	mutex_enter(&(putp->srfpl_lock));
+	putp->srfpl_count++;
+	*putp->srfpl_putpp = mp;
+	putp->srfpl_putpp = &(mp->b_next);
+	mutex_exit(&(putp->srfpl_lock));
+}
+
+static unsigned int
+sfxge_rx_qfpp_swizzle(sfxge_rxq_t *srp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
+	unsigned int start;
+	unsigned int id;
+	mblk_t *p;
+	mblk_t **pp;
+	unsigned int count;
+	unsigned int loaned;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	/* We want to access the put list for the current CPU last */
+	id = start = (CPU->cpu_seqid + 1) & SFXGE_RX_FPP_MASK;
+
+	do {
+		sfxge_rx_fpp_putlist_t *putp;
+		size_t off;
+
+		off = id * SFXGE_CPU_CACHE_SIZE;
+		id  = (id + 1) & SFXGE_RX_FPP_MASK;
+
+		putp = (void *)(srfppp->srfpp_putp + off);
+
+		/* Acquire the put list */
+		mutex_enter(&(putp->srfpl_lock));
+
+		p = putp->srfpl_putp;
+		pp = putp->srfpl_putpp;
+		count = putp->srfpl_count;
+
+		putp->srfpl_putp = NULL;
+		putp->srfpl_putpp = &(putp->srfpl_putp);
+		putp->srfpl_count = 0;
+
+		mutex_exit(&(putp->srfpl_lock));
+
+		if (p == NULL)
+			continue;
+
+		/* Add the list to the head of the get list */
+		*pp = srfppp->srfpp_get;
+		srfppp->srfpp_get = p;
+
+		/* Adjust the counters */
+		ASSERT3U(srfppp->srfpp_loaned, >=, count);
+		srfppp->srfpp_loaned -= count;
+		srfppp->srfpp_count += count;
+
+#if 0
+		/* NOTE: this probe is disabled because it is expensive!! */
+		DTRACE_PROBE2(count,
+		    unsigned int, (id - 1) & SFXGE_RX_FPP_MASK,
+		    unsigned int, count);
+#endif
+
+	} while (id != start);
+
+	/* Return the number of packets yet to appear in the put list */
+	loaned = srfppp->srfpp_loaned;
+
+
+	return (loaned);
+}
+
+
+#define	DB_FRTNP(mp)	((mp)->b_datap->db_frtnp)
+
+static void
+sfxge_rx_qfpp_empty(sfxge_rxq_t *srp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	sfxge_rx_fpp_t *srfppp;
+	mblk_t *mp;
+
+	mutex_enter(&(sep->se_lock));
+	srfppp = &(srp->sr_fpp);
+
+	/* Swizzle put list to get list */
+	(void) sfxge_rx_qfpp_swizzle(srp);
+	ASSERT3U(srfppp->srfpp_loaned, ==, 0);
+
+	mp = srfppp->srfpp_get;
+	srfppp->srfpp_get = NULL;
+
+	/* Free the remainder */
+	while (mp != NULL) {
+		mblk_t *next;
+		frtn_t *freep;
+		sfxge_rx_packet_t *srpp;
+
+		next = mp->b_next;
+		mp->b_next = NULL;
+
+		ASSERT3U(srfppp->srfpp_count, >, 0);
+		srfppp->srfpp_count--;
+
+		freep = DB_FRTNP(mp);
+		/*
+		 * ASSERT3P(freep->free_func, ==, sfxge_rx_qpacket_free);
+		 *   is implied by srpp test below
+		 */
+		/*LINTED*/
+		srpp = (sfxge_rx_packet_t *)(freep->free_arg);
+		ASSERT3P(srpp->srp_mp, ==, mp);
+		ASSERT3P(mp->b_cont, ==, NULL);
+		srpp->srp_recycle = B_FALSE;
+
+		freeb(mp);
+
+		mp = next;
+	}
+	ASSERT3U(srfppp->srfpp_count, ==, 0);
+
+	srfppp->srfpp_min = 0;
+
+	mutex_exit(&(sep->se_lock));
+}
+
+/*
+ * This is an estimate of all memory consumed per RX packet
+ * it can be inaccurate but but sp->s_rx_pkt_mem_alloc mustn't drift
+ */
+static uint64_t
+sfxge_rx_pkt_mem_approx(const sfxge_rx_packet_t *srpp)
+{
+	return (srpp->srp_mblksize + sizeof (mblk_t) + sizeof (dblk_t) +
+	    sizeof (sfxge_rx_packet_t));
+}
+
+static void
+sfxge_rx_qpacket_destroy(sfxge_rxq_t *srp, sfxge_rx_packet_t *srpp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	int64_t delta = sfxge_rx_pkt_mem_approx(srpp);
+
+	ASSERT(!(srpp->srp_recycle));
+	ASSERT3P(srpp->srp_mp, ==, NULL);
+
+	srpp->srp_off = 0;
+	srpp->srp_thp = NULL;
+	srpp->srp_iphp = NULL;
+	srpp->srp_etherhp = NULL;
+	srpp->srp_size = 0;
+	srpp->srp_flags = 0;
+
+	bzero(&(srpp->srp_free), sizeof (frtn_t));
+
+	srpp->srp_mblksize = 0;
+	srpp->srp_base = NULL;
+
+	/* Unbind the DMA memory from the DMA handle */
+	srpp->srp_addr = 0;
+	(void) ddi_dma_unbind_handle(srpp->srp_dma_handle);
+
+	/* Free the DMA memory */
+	srpp->srp_base = NULL;
+	ddi_dma_mem_free(&(srpp->srp_acc_handle));
+	srpp->srp_acc_handle = NULL;
+
+	srpp->srp_putp = NULL;
+	srpp->srp_srp = NULL;
+
+	kmem_cache_free(sp->s_rpc, srpp);
+	if (sp->s_rx_pkt_mem_max)
+		atomic_add_64(&sp->s_rx_pkt_mem_alloc, -delta);
+}
+
+#ifdef _USE_XESBALLOC
+static void
+sfxge_rx_qpacket_free(void *arg, mblk_t *mp, boolean_t *recyclep)
+{
+	sfxge_rx_packet_t *srpp = arg;
+	sfxge_rxq_t *srp = srpp->srp_srp;
+
+	/*
+	 * WARNING "man -s 9f esballoc" states:
+	 * => runs async in a background context
+	 * => must not sleep, or access data structures that could be freed
+	 */
+	ASSERT3P(DB_BASE(mp), ==, srpp->srp_base);
+	ASSERT3P(MBLKSIZE(mp), ==, srpp->srp_mblksize);
+
+	/* Check whether we want to recycle the receive packets */
+	if (srpp->srp_recycle) {
+		ASSERT3P(DB_FRTNP(mp), ==, &(srpp->srp_free));
+
+		srpp->srp_mp = mp;
+
+		/* NORMAL recycled case */
+		sfxge_rx_qfpp_put(srp, srpp);
+		*recyclep = B_TRUE;
+		return;
+	}
+
+	srpp->srp_mp = NULL;
+
+	sfxge_rx_qpacket_destroy(srp, srpp);
+	*recyclep = B_FALSE;
+}
+#endif	/* _USE_XESBALLOC */
+
+#ifdef _USE_DESBALLOC
+static void
+sfxge_rx_qpacket_free(void *arg)
+{
+	sfxge_rx_packet_t *srpp = arg;
+	sfxge_rxq_t *srp = srpp->srp_srp;
+
+	/*
+	 * WARNING "man -s 9f esballoc"  states:
+	 * => runs sync from the thread calling freeb()
+	 * => must not sleep, or access data structures that could be freed
+	 */
+
+	/* Check whether we want to recycle the receive packets */
+	if (srpp->srp_recycle) {
+		frtn_t *freep;
+		mblk_t *mp;
+		size_t size;
+
+		freep = &(srpp->srp_free);
+		ASSERT3P(freep->free_func, ==, sfxge_rx_qpacket_free);
+		ASSERT3P(freep->free_arg, ==, (caddr_t)srpp);
+
+		/*
+		 * Allocate a matching mblk_t before the current one is
+		 * freed.
+		 */
+		size = srpp->srp_mblksize;
+
+		if ((mp = desballoc(srpp->srp_base, size, BPRI_HI,
+		    freep)) != NULL) {
+			srpp->srp_mp = mp;
+
+			/* NORMAL recycled case */
+			sfxge_rx_qfpp_put(srp, srpp);
+			return;
+		}
+	}
+
+	srpp->srp_mp = NULL;
+
+	sfxge_rx_qpacket_destroy(srp, srpp);
+}
+#endif	/* _USE_DESBALLOC */
+
+static sfxge_rx_packet_t *
+sfxge_rx_qpacket_create(sfxge_rxq_t *srp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
+	sfxge_rx_packet_t *srpp;
+	size_t size;
+	caddr_t base;
+	size_t unit;
+	ddi_dma_cookie_t dmac;
+	unsigned int ncookies;
+	frtn_t *freep;
+	mblk_t *mp;
+	int err;
+	int rc;
+
+	size = sp->s_rx_buffer_size;
+
+	if (sp->s_rx_pkt_mem_max &&
+	    (sp->s_rx_pkt_mem_alloc + size >= sp->s_rx_pkt_mem_max)) {
+		DTRACE_PROBE(rx_pkt_mem_max);
+		srp->sr_kstat.srk_rx_pkt_mem_limit++;
+		return (NULL);
+	}
+
+	/* Allocate a new packet */
+	if ((srpp = kmem_cache_alloc(sp->s_rpc, KM_NOSLEEP)) == NULL) {
+		srp->sr_kstat.srk_kcache_alloc_nomem++;
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	srpp->srp_srp = srp;
+	srpp->srp_putp = srfppp->srfpp_putp;
+
+	/* Allocate some DMA memory */
+	err = ddi_dma_mem_alloc(srpp->srp_dma_handle, size,
+	    &sfxge_rx_packet_devacc, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT,
+	    NULL, &base, &unit, &(srpp->srp_acc_handle));
+	switch (err) {
+	case DDI_SUCCESS:
+		break;
+
+	case DDI_FAILURE:
+		srp->sr_kstat.srk_dma_alloc_nomem++;
+		rc = ENOMEM;
+		goto fail2;
+
+	default:
+		srp->sr_kstat.srk_dma_alloc_fail++;
+		rc = EFAULT;
+		goto fail2;
+	}
+
+	/* Adjust the buffer to align the start of the DMA area correctly */
+	base += sp->s_rx_buffer_align;
+	size -= sp->s_rx_buffer_align;
+
+	/* Bind the DMA memory to the DMA handle */
+	err = ddi_dma_addr_bind_handle(srpp->srp_dma_handle, NULL,
+	    base, size, DDI_DMA_READ | DDI_DMA_STREAMING,
+	    DDI_DMA_DONTWAIT, NULL, &dmac, &ncookies);
+	switch (err) {
+	case DDI_DMA_MAPPED:
+		break;
+
+	case DDI_DMA_INUSE:
+		srp->sr_kstat.srk_dma_bind_fail++;
+		rc = EEXIST;
+		goto fail3;
+
+	case DDI_DMA_NORESOURCES:
+		srp->sr_kstat.srk_dma_bind_nomem++;
+		rc = ENOMEM;
+		goto fail3;
+
+	case DDI_DMA_NOMAPPING:
+		srp->sr_kstat.srk_dma_bind_fail++;
+		rc = ENOTSUP;
+		goto fail3;
+
+	case DDI_DMA_TOOBIG:
+		srp->sr_kstat.srk_dma_bind_fail++;
+		rc = EFBIG;
+		goto fail3;
+
+	default:
+		srp->sr_kstat.srk_dma_bind_fail++;
+		rc = EFAULT;
+		goto fail3;
+	}
+	ASSERT3U(ncookies, ==, 1);
+
+	srpp->srp_addr = dmac.dmac_laddress;
+
+	srpp->srp_base = (unsigned char *)base;
+	srpp->srp_mblksize = size;
+
+	/*
+	 * Allocate a STREAMS block: We use size 1 so that the allocator will
+	 * use the first (and smallest) dblk cache.
+	 */
+	freep = &(srpp->srp_free);
+	freep->free_func = sfxge_rx_qpacket_free;
+	freep->free_arg  = (caddr_t)srpp;
+
+#ifdef _USE_XESBALLOC
+	if ((mp = xesballoc(srpp->srp_base, size, BPRI_HI, freep)) == NULL) {
+		srp->sr_kstat.srk_xesballoc_fail++;
+		rc = ENOMEM;
+		goto fail4;
+	}
+#endif	/* _USE_XESBALLOC */
+
+#ifdef _USE_DESBALLOC
+	if ((mp = desballoc(srpp->srp_base, size, BPRI_HI, freep)) == NULL) {
+		srp->sr_kstat.srk_desballoc_fail++;
+		rc = ENOMEM;
+		goto fail4;
+	}
+#endif	/* _USE_DESBALLOC */
+
+	srpp->srp_mp = mp;
+	srpp->srp_recycle = B_TRUE;
+
+	if (sp->s_rx_pkt_mem_max) {
+		int64_t delta = sfxge_rx_pkt_mem_approx(srpp);
+		atomic_add_64(&sp->s_rx_pkt_mem_alloc, delta);
+	}
+
+	return (srpp);
+
+fail4:
+	DTRACE_PROBE(fail4);
+
+	bzero(&(srpp->srp_free), sizeof (frtn_t));
+
+	srpp->srp_mblksize = 0;
+	srpp->srp_base = NULL;
+
+	/* Unbind the DMA memory from the DMA handle */
+	srpp->srp_addr = 0;
+	(void) ddi_dma_unbind_handle(srpp->srp_dma_handle);
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	/* Free the DMA memory */
+	ddi_dma_mem_free(&(srpp->srp_acc_handle));
+	srpp->srp_acc_handle = NULL;
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	srpp->srp_putp = NULL;
+	srpp->srp_srp = NULL;
+
+	kmem_cache_free(sp->s_rpc, srpp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (NULL);
+}
+
+#define	SFXGE_REFILL_BATCH  64
+
+/* Try to refill the RX descriptor ring from the associated free pkt pool */
+static void
+sfxge_rx_qrefill(sfxge_rxq_t *srp, unsigned int target)
+{
+	sfxge_t *sp = srp->sr_sp;
+	sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	efsys_dma_addr_t addr[SFXGE_REFILL_BATCH];
+	mblk_t *mp;
+	int ntodo;
+	unsigned int count;
+	unsigned int batch;
+	unsigned int rxfill;
+	unsigned int mblksize;
+
+	prefetch_read_many(sp->s_enp);
+	prefetch_read_many(srp->sr_erp);
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	if (srp->sr_state != SFXGE_RXQ_STARTED)
+		return;
+
+	rxfill = srp->sr_added - srp->sr_completed;
+	ASSERT3U(rxfill, <=, EFX_RXQ_LIMIT(sp->s_rxq_size));
+	ntodo = min(EFX_RXQ_LIMIT(sp->s_rxq_size) - rxfill, target);
+	ASSERT3U(ntodo, <=, EFX_RXQ_LIMIT(sp->s_rxq_size));
+
+	if (ntodo == 0)
+		goto out;
+
+	(void) sfxge_rx_qfpp_swizzle(srp);
+
+	mp = srfppp->srfpp_get;
+	count = srfppp->srfpp_count;
+	mblksize = sp->s_rx_buffer_size - sp->s_rx_buffer_align;
+
+	batch = 0;
+	while (ntodo-- > 0) {
+		mblk_t *next;
+		frtn_t *freep;
+		sfxge_rx_packet_t *srpp;
+		unsigned int id;
+
+		if (mp == NULL)
+			break;
+
+		next = mp->b_next;
+		mp->b_next = NULL;
+
+		if (next != NULL)
+			prefetch_read_many(next);
+
+		freep = DB_FRTNP(mp);
+		/*LINTED*/
+		srpp = (sfxge_rx_packet_t *)(freep->free_arg);
+		ASSERT3P(srpp->srp_mp, ==, mp);
+
+		/* The MTU may have changed since the packet was allocated */
+		if (MBLKSIZE(mp) != mblksize) {
+			srpp->srp_recycle = B_FALSE;
+
+			freeb(mp);
+
+			--count;
+			mp = next;
+			continue;
+		}
+
+		srpp->srp_off = 0;
+		srpp->srp_thp = NULL;
+		srpp->srp_iphp = NULL;
+		srpp->srp_etherhp = NULL;
+		srpp->srp_size = 0;
+		srpp->srp_flags = EFX_DISCARD;
+
+		id = (srp->sr_added + batch) & (sp->s_rxq_size - 1);
+		ASSERT(srp->sr_srpp[id] == NULL);
+		srp->sr_srpp[id] = srpp;
+
+		addr[batch++] = srpp->srp_addr;
+		if (batch == SFXGE_REFILL_BATCH) {
+			efx_rx_qpost(srp->sr_erp, addr, mblksize, batch,
+			    srp->sr_completed, srp->sr_added);
+			srp->sr_added += batch;
+			batch = 0;
+		}
+
+		--count;
+		mp = next;
+	}
+
+	srfppp->srfpp_get = mp;
+	srfppp->srfpp_count = count;
+
+	if (batch != 0) {
+		efx_rx_qpost(srp->sr_erp, addr, mblksize, batch,
+		    srp->sr_completed, srp->sr_added);
+		srp->sr_added += batch;
+	}
+
+	/* Make the descriptors visible to the hardware */
+	(void) ddi_dma_sync(srp->sr_mem.esm_dma_handle,
+	    0,
+	    EFX_RXQ_SIZE(sp->s_rxq_size),
+	    DDI_DMA_SYNC_FORDEV);
+
+	efx_rx_qpush(srp->sr_erp, srp->sr_added);
+
+out:
+	if (srfppp->srfpp_count < srfppp->srfpp_min)
+		srfppp->srfpp_min = srfppp->srfpp_count;
+}
+
+/* Preallocate packets and put them in the free packet pool */
+static int
+sfxge_rx_qpreallocate(sfxge_rxq_t *srp, int nprealloc)
+{
+	sfxge_rx_fpp_t *srfppp = &((srp)->sr_fpp);
+	srfppp->srfpp_lowat = nprealloc;
+	while (nprealloc-- > 0) {
+		sfxge_rx_packet_t *srpp;
+
+		if ((srpp = sfxge_rx_qpacket_create(srp)) == NULL)
+			break;
+		sfxge_rx_qfpp_put(srp, srpp);
+	}
+	return (0);
+}
+
+/* Try to refill the RX descriptor ring by allocating new packets */
+static void
+sfxge_rx_qfill(sfxge_rxq_t *srp, unsigned int target)
+{
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	unsigned int batch;
+	unsigned int rxfill;
+	unsigned int mblksize;
+	int ntodo;
+	efsys_dma_addr_t addr[SFXGE_REFILL_BATCH];
+	mblk_t *mp = NULL;
+
+	prefetch_read_many(sp->s_enp);
+	prefetch_read_many(srp->sr_erp);
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	if (srp->sr_state != SFXGE_RXQ_STARTED)
+		return;
+
+	rxfill = srp->sr_added - srp->sr_completed;
+	ASSERT3U(rxfill, <=, EFX_RXQ_LIMIT(sp->s_rxq_size));
+	ntodo = min(EFX_RXQ_LIMIT(sp->s_rxq_size) - rxfill, target);
+	ASSERT3U(ntodo, <=, EFX_RXQ_LIMIT(sp->s_rxq_size));
+
+	if (ntodo == 0)
+		return;
+
+	mblksize = sp->s_rx_buffer_size - sp->s_rx_buffer_align;
+
+	batch = 0;
+	while (ntodo-- > 0) {
+		sfxge_rx_packet_t *srpp;
+		unsigned int id;
+
+		if ((srpp = sfxge_rx_qpacket_create(srp)) == NULL)
+			break;
+
+		mp = srpp->srp_mp;
+
+		ASSERT3U(MBLKSIZE(mp), ==, mblksize);
+
+		ASSERT3U(srpp->srp_off, ==, 0);
+		ASSERT3P(srpp->srp_thp, ==, NULL);
+		ASSERT3P(srpp->srp_iphp, ==, NULL);
+		ASSERT3P(srpp->srp_etherhp, ==, NULL);
+		ASSERT3U(srpp->srp_size, ==, 0);
+
+		srpp->srp_flags = EFX_DISCARD;
+
+		id = (srp->sr_added + batch) & (sp->s_rxq_size - 1);
+		ASSERT(srp->sr_srpp[id] == NULL);
+		srp->sr_srpp[id] = srpp;
+
+		addr[batch++] = srpp->srp_addr;
+		if (batch == SFXGE_REFILL_BATCH) {
+			efx_rx_qpost(srp->sr_erp, addr, mblksize, batch,
+			    srp->sr_completed, srp->sr_added);
+			srp->sr_added += batch;
+			batch = 0;
+		}
+	}
+
+	if (batch != 0) {
+		efx_rx_qpost(srp->sr_erp, addr, mblksize, batch,
+		    srp->sr_completed, srp->sr_added);
+		srp->sr_added += batch;
+	}
+
+	/* Make the descriptors visible to the hardware */
+	(void) ddi_dma_sync(srp->sr_mem.esm_dma_handle,
+	    0,
+	    EFX_RXQ_SIZE(sp->s_rxq_size),
+	    DDI_DMA_SYNC_FORDEV);
+
+	efx_rx_qpush(srp->sr_erp, srp->sr_added);
+}
+
+void
+sfxge_rx_qfpp_trim(sfxge_rxq_t *srp)
+{
+	sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	mblk_t *p;
+	mblk_t **pp;
+	int count;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	if (srp->sr_state != SFXGE_RXQ_STARTED)
+		goto done;
+
+	/* Make sure the queue is full */
+	sfxge_rx_qrefill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
+
+	/* The refill may have emptied the pool */
+	if (srfppp->srfpp_min == 0)
+		goto done;
+
+	/* Don't trim below the pool's low water mark */
+	if (srfppp->srfpp_count <= srfppp->srfpp_lowat)
+		goto done;
+
+	ASSERT(srfppp->srfpp_min <= srfppp->srfpp_count);
+
+	/* Trim to the largest of srfppp->srfpp_min and srfpp->srfpp_lowat */
+	if (srfppp->srfpp_lowat > srfppp->srfpp_min)
+		count = srfppp->srfpp_count - srfppp->srfpp_lowat;
+	else
+		count = srfppp->srfpp_count - srfppp->srfpp_min;
+
+	/* Walk the get list */
+	pp = &(srfppp->srfpp_get);
+	while (--count >= 0) {
+		ASSERT(pp);
+		p = *pp;
+		ASSERT(p != NULL);
+
+		pp = &(p->b_next);
+	}
+	ASSERT(pp);
+	p = *pp;
+
+	/* Truncate the get list */
+	*pp = NULL;
+
+	/* Free the remainder */
+	while (p != NULL) {
+		mblk_t *next;
+		frtn_t *freep;
+		sfxge_rx_packet_t *srpp;
+
+		next = p->b_next;
+		p->b_next = NULL;
+
+		ASSERT3U(srfppp->srfpp_min, >, 0);
+		srfppp->srfpp_min--;
+		srfppp->srfpp_count--;
+
+		freep = DB_FRTNP(p);
+		/*LINTED*/
+		srpp = (sfxge_rx_packet_t *)(freep->free_arg);
+		ASSERT3P(srpp->srp_mp, ==, p);
+
+		srpp->srp_recycle = B_FALSE;
+
+		freeb(p);
+
+		p = next;
+	}
+
+done:
+	srfppp->srfpp_min = srfppp->srfpp_count;
+}
+
+static void
+sfxge_rx_qpoll(void *arg)
+{
+	sfxge_rxq_t *srp = arg;
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	uint16_t magic;
+
+	/*
+	 * man timeout(9f) states that this code should adhere to the
+	 * same requirements as a softirq handler - DO NOT BLOCK
+	 */
+
+	/*
+	 * Post an event to the event queue to cause the free packet pool to be
+	 * trimmed if it is oversize.
+	 */
+	magic = SFXGE_MAGIC_RX_QFPP_TRIM | index;
+
+#if defined(DEBUG)
+	/* This is guaranteed due to the start/stop order of rx and ev */
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
+	ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_STARTED);
+#else
+	/*
+	 * Bug22691 WORKAROUND:
+	 * This handler has been observed in the field to be invoked for a
+	 * queue in the INITIALIZED state, which should never happen.
+	 * Until the mechanism for this is properly understood, add defensive
+	 * checks.
+	 */
+	if ((sep->se_state != SFXGE_EVQ_STARTED) ||
+	    (srp->sr_state != SFXGE_RXQ_STARTED) ||
+	    (!sep->se_eep)) {
+		cmn_err(CE_WARN, SFXGE_CMN_ERR
+			"[%s%d] RXQ[%d] bad state in sfxge_rx_qpoll %d %d %p",
+			ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip),
+			index, sep->se_state, srp->sr_state, sep->se_eep);
+		return;
+	}
+#endif
+	efx_ev_qpost(sep->se_eep, magic);
+
+	srp->sr_tid = timeout(sfxge_rx_qpoll, srp,
+		drv_usectohz(sp->s_rxq_poll_usec));
+}
+
+static void
+sfxge_rx_qpoll_start(sfxge_rxq_t *srp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+	ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_STARTED);
+
+	/* Schedule a poll */
+	ASSERT3P(srp->sr_tid, ==, 0);
+	srp->sr_tid = timeout(sfxge_rx_qpoll, srp, 0);
+}
+
+static void
+sfxge_rx_qpoll_stop(sfxge_rxq_t *srp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	timeout_id_t tid;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+	ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_STARTED);
+
+	/*
+	 * Cancel the qpoll timer. Care is needed as this function
+	 * can race with sfxge_rx_qpoll() for timeout id updates.
+	 *
+	 * Do not hold locks used by any timeout(9f) handlers across
+	 * calls to untimeout(9f) as this will deadlock.
+	 */
+	tid = 0;
+	while ((srp->sr_tid != 0) && (srp->sr_tid != tid)) {
+		tid = srp->sr_tid;
+		(void) untimeout(tid);
+	}
+	srp->sr_tid = 0;
+}
+
+static int
+sfxge_rx_kstat_update(kstat_t *ksp, int rw)
+{
+	sfxge_rxq_t *srp = ksp->ks_private;
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	kstat_named_t *knp;
+	int rc;
+
+	if (rw != KSTAT_READ) {
+		rc = EACCES;
+		goto fail1;
+	}
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+	if (srp->sr_state != SFXGE_RXQ_STARTED)
+		goto done;
+
+	knp = ksp->ks_data;
+	/* NB pointer post-increment below */
+	knp++->value.ui32 = srp->sr_kstat.srk_rx_pkt_mem_limit;
+	knp++->value.ui32 = srp->sr_kstat.srk_kcache_alloc_nomem;
+	knp++->value.ui32 = srp->sr_kstat.srk_dma_alloc_nomem;
+	knp++->value.ui32 = srp->sr_kstat.srk_dma_alloc_fail;
+	knp++->value.ui32 = srp->sr_kstat.srk_dma_bind_nomem;
+	knp++->value.ui32 = srp->sr_kstat.srk_dma_bind_fail;
+#ifdef _USE_XESBALLOC
+	knp++->value.ui32 = srp->sr_kstat.srk_xesballoc_fail;
+#endif
+#ifdef _USE_DESBALLOC
+	knp++->value.ui32 = srp->sr_kstat.srk_desballoc_fail;
+#endif
+	knp++->value.ui32 = srp->sr_kstat.srk_rxq_empty_discard;
+
+done:
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_rx_kstat_init(sfxge_rxq_t *srp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	dev_info_t *dip = sp->s_dip;
+	char name[MAXNAMELEN];
+	kstat_t *ksp;
+	kstat_named_t *knp;
+	int rc;
+
+	/* Create the set */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_rxq%04d",
+	    ddi_driver_name(dip), index);
+
+	if ((ksp = kstat_create((char *)ddi_driver_name(dip),
+	    ddi_get_instance(dip), name, "rxq", KSTAT_TYPE_NAMED,
+	    SFXGE_RX_NSTATS, 0)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	srp->sr_ksp = ksp;
+
+	ksp->ks_update = sfxge_rx_kstat_update;
+	ksp->ks_private = srp;
+	ksp->ks_lock = &(sep->se_lock);
+
+	/* Initialise the named stats */
+	knp = ksp->ks_data;
+	kstat_named_init(knp, "rx_pkt_mem_limit", KSTAT_DATA_UINT32);
+	knp++;
+	kstat_named_init(knp, "kcache_alloc_nomem", KSTAT_DATA_UINT32);
+	knp++;
+	kstat_named_init(knp, "dma_alloc_nomem", KSTAT_DATA_UINT32);
+	knp++;
+	kstat_named_init(knp, "dma_alloc_fail", KSTAT_DATA_UINT32);
+	knp++;
+	kstat_named_init(knp, "dma_bind_nomem", KSTAT_DATA_UINT32);
+	knp++;
+	kstat_named_init(knp, "dma_bind_fail", KSTAT_DATA_UINT32);
+	knp++;
+#ifdef _USE_XESBALLOC
+	kstat_named_init(knp, "xesballoc_fail", KSTAT_DATA_UINT32);
+#endif
+#ifdef _USE_DESBALLOC
+	kstat_named_init(knp, "desballoc_fail", KSTAT_DATA_UINT32);
+#endif
+	kstat_named_init(knp, "rxq_empty_discard", KSTAT_DATA_UINT32);
+
+	kstat_install(ksp);
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_rx_qinit(sfxge_t *sp, unsigned int index)
+{
+	sfxge_rxq_t *srp;
+	int rc;
+
+	ASSERT3U(index, <, SFXGE_RX_SCALE_MAX);
+
+	srp = kmem_cache_alloc(sp->s_rqc, KM_SLEEP);
+
+	ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_UNINITIALIZED);
+
+	srp->sr_index = index;
+	sp->s_srp[index] = srp;
+
+	if ((rc = sfxge_rx_kstat_init(srp)) != 0)
+		goto fail1;
+
+	srp->sr_state = SFXGE_RXQ_INITIALIZED;
+
+	return (0);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	kmem_cache_free(sp->s_rqc, srp);
+
+	return (rc);
+}
+
+static int
+sfxge_rx_qstart(sfxge_t *sp, unsigned int index)
+{
+	sfxge_evq_t *sep = sp->s_sep[index];
+	sfxge_rxq_t *srp;
+	efsys_mem_t *esmp;
+	efx_nic_t *enp;
+	unsigned int level;
+	int rc;
+
+	mutex_enter(&(sep->se_lock));
+	srp = sp->s_srp[index];
+	enp = sp->s_enp;
+	esmp = &(srp->sr_mem);
+
+	ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_INITIALIZED);
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
+
+	/* Zero the memory */
+	(void) memset(esmp->esm_base, 0, EFX_RXQ_SIZE(sp->s_rxq_size));
+
+	/* Program the buffer table */
+	if ((rc = sfxge_sram_buf_tbl_set(sp, srp->sr_id, esmp,
+	    EFX_RXQ_NBUFS(sp->s_rxq_size))) != 0)
+		goto fail1;
+
+	/* Create the receive queue */
+	if ((rc = efx_rx_qcreate(enp, index, index, EFX_RXQ_TYPE_DEFAULT,
+	    esmp, sp->s_rxq_size, srp->sr_id, sep->se_eep, &(srp->sr_erp)))
+	    != 0)
+		goto fail2;
+
+	/* Enable the receive queue */
+	efx_rx_qenable(srp->sr_erp);
+
+	/* Set the water marks */
+	srp->sr_hiwat = EFX_RXQ_LIMIT(sp->s_rxq_size) * 9 / 10;
+	srp->sr_lowat = srp->sr_hiwat / 2;
+
+	srp->sr_state = SFXGE_RXQ_STARTED;
+
+	sfxge_rx_qpoll_start(srp);
+
+	/* Try to fill the queue from the pool */
+	sfxge_rx_qrefill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
+
+	/*
+	 * If there were insufficient buffers in the pool to reach the at
+	 * least a batch then allocate some.
+	 */
+	level = srp->sr_added - srp->sr_completed;
+	if (level < SFXGE_RX_BATCH)
+		sfxge_rx_qfill(srp, SFXGE_RX_BATCH);
+
+	mutex_exit(&(sep->se_lock));
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Clear entries from the buffer table */
+	sfxge_sram_buf_tbl_clear(sp, srp->sr_id,
+	    EFX_RXQ_NBUFS(sp->s_rxq_size));
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(sep->se_lock));
+
+	return (rc);
+}
+
+static void
+sfxge_rx_qflow_complete(sfxge_rxq_t *srp, sfxge_rx_flow_t *srfp)
+{
+	mblk_t *mp;
+	struct ether_header *etherhp;
+	struct ip *iphp;
+	struct tcphdr *thp;
+
+	if (srfp->srf_mp == NULL)
+		return;
+
+	mp = srfp->srf_mp;
+	etherhp = srfp->srf_etherhp;
+	iphp = srfp->srf_iphp;
+	thp = srfp->srf_last_thp;
+
+	ASSERT3U(((etherhp->ether_type == htons(ETHERTYPE_VLAN)) ?
+	    sizeof (struct ether_vlan_header) :
+	    sizeof (struct ether_header)) +
+	    srfp->srf_len, ==, msgdsize(mp));
+
+	ASSERT3U(srfp->srf_len & 0xffff, ==, srfp->srf_len);
+	iphp->ip_len = htons(srfp->srf_len);
+
+	srfp->srf_first_thp->th_ack = thp->th_ack;
+	srfp->srf_first_thp->th_win = thp->th_win;
+	srfp->srf_first_thp->th_flags = thp->th_flags;
+
+	DTRACE_PROBE2(flow_complete, uint32_t, srfp->srf_tag,
+	    size_t, srfp->srf_len);
+
+	srfp->srf_mp = NULL;
+	srfp->srf_len = 0;
+
+	ASSERT(mp->b_next == NULL);
+	*(srp->sr_mpp) = mp;
+	srp->sr_mpp = &(mp->b_next);
+}
+
+static boolean_t
+sfxge_rx_qflow_add(sfxge_rxq_t *srp, sfxge_rx_flow_t *srfp,
+    sfxge_rx_packet_t *srpp, clock_t now)
+{
+	sfxge_t *sp = srp->sr_sp;
+	struct ether_header *etherhp = srpp->srp_etherhp;
+	struct ip *iphp = srpp->srp_iphp;
+	struct tcphdr *thp = srpp->srp_thp;
+	size_t off = srpp->srp_off;
+	size_t size = (size_t)(srpp->srp_size);
+	mblk_t *mp = srpp->srp_mp;
+	uint32_t seq;
+	unsigned int shift;
+
+	ASSERT3U(MBLKL(mp), ==, off + size);
+	ASSERT3U(DB_CKSUMFLAGS(mp), ==,
+	    HCK_FULLCKSUM | HCK_FULLCKSUM_OK | HCK_IPV4_HDRCKSUM);
+
+	seq = htonl(thp->th_seq);
+
+	/*
+	 * If the time between this segment and the last is greater than RTO
+	 * then consider this a new flow.
+	 */
+	if (now - srfp->srf_lbolt > srp->sr_rto) {
+		srfp->srf_count = 1;
+		srfp->srf_seq = seq + size;
+
+		goto fail1;
+	}
+
+	if (seq != srfp->srf_seq) {
+		if (srfp->srf_count > SFXGE_SLOW_START)
+			srfp->srf_count = SFXGE_SLOW_START;
+
+		srfp->srf_count >>= 1;
+
+		srfp->srf_count++;
+		srfp->srf_seq = seq + size;
+
+		goto fail2;
+	}
+
+	/* Update the in-order segment count and sequence number */
+	srfp->srf_count++;
+	srfp->srf_seq = seq + size;
+
+	/* Don't merge across pure ACK, URG, SYN or RST segments */
+	if (size == 0 || thp->th_flags & (TH_URG | TH_SYN | TH_RST) ||
+	    thp->th_urp != 0)
+		goto fail3;
+
+	/*
+	 * If the in-order segment count has not yet reached the slow-start
+	 * threshold then we cannot coalesce.
+	 */
+	if (srfp->srf_count < SFXGE_SLOW_START)
+		goto fail4;
+
+	/* Scale up the packet size from 4k (the maximum being 64k) */
+	ASSERT3U(srfp->srf_count, >=, SFXGE_SLOW_START);
+	shift = MIN(srfp->srf_count - SFXGE_SLOW_START + 12, 16);
+	if (srfp->srf_len + size >= (1 << shift))
+		sfxge_rx_qflow_complete(srp, srfp);
+
+	ASSERT(mp->b_cont == NULL);
+
+#ifdef _USE_GLD_V3_SOL10
+	/*
+	 * The IP and UDP layers in Solaris 10 have slow paths for
+	 * handling mblks with more than 2 fragments.
+	 * UDP: see OpenSolaris CR 6305037
+	 * IP: see <http://www.mail-archive.com/networking-discuss@
+	 *   opensolaris.org/msg07366.html>
+	 */
+	if (srfp->srf_mp && srfp->srf_mp->b_cont) {
+		sfxge_rx_qflow_complete(srp, srfp);
+	}
+#endif
+
+	if (srfp->srf_mp == NULL) {
+		/* First packet in this flow */
+		srfp->srf_etherhp = etherhp;
+		srfp->srf_iphp = iphp;
+		srfp->srf_first_thp = srfp->srf_last_thp = thp;
+
+		ASSERT3P(mp->b_cont, ==, NULL);
+		srfp->srf_mp = mp;
+		srfp->srf_mpp = &(mp->b_cont);
+
+		srfp->srf_len = ntohs(iphp->ip_len);
+
+		/*
+		 * If the flow is not already in the list of occupied flows then
+		 * add it.
+		 */
+		if (srfp->srf_next == NULL &&
+		    srp->sr_srfpp != &(srfp->srf_next)) {
+			*(srp->sr_srfpp) = srfp;
+			srp->sr_srfpp = &(srfp->srf_next);
+		}
+	} else {
+		/* Later packet in this flow - skip TCP header */
+		srfp->srf_last_thp = thp;
+
+		mp->b_rptr += off;
+		ASSERT3U(MBLKL(mp), ==, size);
+
+		ASSERT3P(mp->b_cont, ==, NULL);
+		*(srfp->srf_mpp) = mp;
+		srfp->srf_mpp = &(mp->b_cont);
+
+		srfp->srf_len += size;
+
+		ASSERT(srfp->srf_next != NULL ||
+		    srp->sr_srfpp == &(srfp->srf_next));
+	}
+
+	DTRACE_PROBE2(flow_add, uint32_t, srfp->srf_tag, size_t, size);
+
+	/*
+	 * Try to align coalesced segments on push boundaries, unless they
+	 * are too frequent.
+	 */
+	if (sp->s_rx_coalesce_mode == SFXGE_RX_COALESCE_ALLOW_PUSH &&
+	    thp->th_flags & TH_PUSH)
+		sfxge_rx_qflow_complete(srp, srfp);
+
+	srfp->srf_lbolt = now;
+	return (B_TRUE);
+
+fail4:
+fail3:
+fail2:
+fail1:
+	sfxge_rx_qflow_complete(srp, srfp);
+
+	srfp->srf_lbolt = now;
+	return (B_FALSE);
+}
+
+void
+sfxge_rx_qpacket_coalesce(sfxge_rxq_t *srp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	clock_t now;
+	mblk_t *mp;
+	sfxge_rx_flow_t *srfp;
+
+	ASSERT(sp->s_rx_coalesce_mode != SFXGE_RX_COALESCE_OFF);
+
+	now = ddi_get_lbolt();
+
+	mp = srp->sr_mp;
+
+	srp->sr_mp = NULL;
+	srp->sr_mpp = &(srp->sr_mp);
+
+	/* Start with the last flow to be appended to */
+	srfp = *(srp->sr_srfpp);
+
+	while (mp != NULL) {
+		frtn_t *freep;
+		sfxge_rx_packet_t *srpp;
+		struct ether_header *etherhp;
+		struct ip *iphp;
+		struct tcphdr *thp;
+		size_t off;
+		size_t size;
+		uint16_t ether_tci;
+		uint16_t hash;
+		uint32_t tag;
+		mblk_t *next;
+
+		next = mp->b_next;
+		mp->b_next = NULL;
+
+		if (next != NULL)
+			prefetch_read_many(next);
+
+		freep = DB_FRTNP(mp);
+		/*LINTED*/
+		srpp = (sfxge_rx_packet_t *)(freep->free_arg);
+		ASSERT3P(srpp->srp_mp, ==, mp);
+
+		/* If the packet is not TCP then we cannot coalesce it */
+		if (~(srpp->srp_flags) & EFX_PKT_TCP)
+			goto reject;
+
+		/*
+		 * If the packet is not fully checksummed then we cannot
+		 * coalesce it.
+		 */
+		if (~(srpp->srp_flags) & (EFX_CKSUM_TCPUDP | EFX_CKSUM_IPV4))
+			goto reject;
+
+		/* Parse the TCP header */
+		sfxge_tcp_parse(mp, &etherhp, &iphp, &thp, &off,
+		    &size);
+		ASSERT(etherhp != NULL);
+		ASSERT(iphp != NULL);
+		ASSERT(thp != NULL);
+		ASSERT(off != 0);
+
+		if ((iphp->ip_off & ~htons(IP_DF)) != 0)
+			goto reject;
+
+		if (etherhp->ether_type == htons(ETHERTYPE_VLAN)) {
+			struct ether_vlan_header *ethervhp;
+
+			ethervhp = (struct ether_vlan_header *)etherhp;
+			ether_tci = ethervhp->ether_tci;
+		} else {
+			ether_tci = 0;
+		}
+
+		/*
+		 * Make sure any minimum length padding is stripped
+		 * before we try to add the packet to a flow.
+		 */
+		ASSERT3U(sp->s_rx_prefix_size + MBLKL(mp), ==,
+		    (size_t)(srpp->srp_size));
+		ASSERT3U(sp->s_rx_prefix_size + off + size, <=,
+		    (size_t)(srpp->srp_size));
+
+		if (sp->s_rx_prefix_size + off + size <
+		    (size_t)(srpp->srp_size))
+			mp->b_wptr = mp->b_rptr + off + size;
+
+		/*
+		 * If there is no current flow, or the segment does not match
+		 * the current flow then we must attempt to look up the
+		 * correct flow in the table.
+		 */
+		if (srfp == NULL)
+			goto lookup;
+
+		if (srfp->srf_saddr != iphp->ip_src.s_addr ||
+		    srfp->srf_daddr != iphp->ip_dst.s_addr)
+			goto lookup;
+
+		if (srfp->srf_sport != thp->th_sport ||
+		    srfp->srf_dport != thp->th_dport)
+			goto lookup;
+
+		if (srfp->srf_tci != ether_tci)
+			goto lookup;
+
+add:
+		ASSERT(srfp != NULL);
+
+		srpp->srp_etherhp = etherhp;
+		srpp->srp_iphp = iphp;
+		srpp->srp_thp = thp;
+		srpp->srp_off = off;
+
+		ASSERT3U(size, <, (1 << 16));
+		srpp->srp_size = (uint16_t)size;
+
+		/* Try to append the packet to the flow */
+		if (!sfxge_rx_qflow_add(srp, srfp, srpp, now))
+			goto reject;
+
+		mp = next;
+		continue;
+
+lookup:
+		/*
+		 * If there is a prefix area then read the hash from that,
+		 * otherwise calculate it.
+		 */
+		if (sp->s_rx_prefix_size != 0) {
+			hash = EFX_RX_HASH_VALUE(EFX_RX_HASHALG_LFSR,
+			    DB_BASE(mp));
+		} else {
+			SFXGE_TCP_HASH(
+			    ntohl(iphp->ip_src.s_addr),
+			    ntohs(thp->th_sport),
+			    ntohl(iphp->ip_dst.s_addr),
+			    ntohs(thp->th_dport),
+			    hash);
+		}
+
+		srfp = &(srp->sr_flow[(hash >> 6) % SFXGE_MAX_FLOW]);
+		tag = (uint32_t)hash + 1; /* Make sure it's not zero */
+
+		/*
+		 * If the flow we have found does not match the hash then
+		 * it may be an unused flow, or it may be stale.
+		 */
+		if (tag != srfp->srf_tag) {
+			if (srfp->srf_count != 0) {
+				if (now - srfp->srf_lbolt <= srp->sr_rto)
+					goto reject;
+			}
+
+			if (srfp->srf_mp != NULL)
+				goto reject;
+
+			/* Start a new flow */
+			ASSERT(srfp->srf_next == NULL);
+
+			srfp->srf_tag = tag;
+
+			srfp->srf_saddr = iphp->ip_src.s_addr;
+			srfp->srf_daddr = iphp->ip_dst.s_addr;
+			srfp->srf_sport = thp->th_sport;
+			srfp->srf_dport = thp->th_dport;
+			srfp->srf_tci = ether_tci;
+
+			srfp->srf_count = 0;
+			srfp->srf_seq = ntohl(thp->th_seq);
+
+			srfp->srf_lbolt = now;
+			goto add;
+		}
+
+		/*
+		 * If the flow we have found does match the hash then it could
+		 * still be an alias.
+		 */
+		if (srfp->srf_saddr != iphp->ip_src.s_addr ||
+		    srfp->srf_daddr != iphp->ip_dst.s_addr)
+			goto reject;
+
+		if (srfp->srf_sport != thp->th_sport ||
+		    srfp->srf_dport != thp->th_dport)
+			goto reject;
+
+		if (srfp->srf_tci != ether_tci)
+			goto reject;
+
+		goto add;
+
+reject:
+		*(srp->sr_mpp) = mp;
+		srp->sr_mpp = &(mp->b_next);
+
+		mp = next;
+	}
+}
+
+void
+sfxge_rx_qcomplete(sfxge_rxq_t *srp, boolean_t eop)
+{
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+	unsigned int completed;
+	sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
+	unsigned int level;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	ASSERT(srp->sr_mp == NULL);
+	ASSERT(srp->sr_mpp == &(srp->sr_mp));
+
+	completed = srp->sr_completed;
+	while (completed != srp->sr_pending) {
+		unsigned int id;
+		sfxge_rx_packet_t *srpp;
+		mblk_t *mp;
+		size_t size;
+		uint16_t flags;
+
+		id = completed++ & (sp->s_rxq_size - 1);
+
+		if (srp->sr_pending - completed >= 4) {
+			unsigned int prefetch;
+
+			prefetch = (id + 4) & (sp->s_rxq_size - 1);
+
+			srpp = srp->sr_srpp[prefetch];
+			ASSERT(srpp != NULL);
+
+			mp = srpp->srp_mp;
+			prefetch_read_many(mp->b_datap);
+		} else if (completed == srp->sr_pending) {
+			prefetch_read_many(srp->sr_mp);
+		}
+
+		srpp = srp->sr_srpp[id];
+		ASSERT(srpp != NULL);
+
+		srp->sr_srpp[id] = NULL;
+
+		mp = srpp->srp_mp;
+		ASSERT(mp->b_cont == NULL);
+
+		/* when called from sfxge_rx_qstop() */
+		if (srp->sr_state != SFXGE_RXQ_STARTED)
+			goto discard;
+
+		if (srpp->srp_flags & (EFX_ADDR_MISMATCH | EFX_DISCARD))
+			goto discard;
+
+		/* Set up the packet length */
+		ASSERT3P(mp->b_rptr, ==, DB_BASE(mp));
+		mp->b_rptr += sp->s_rx_prefix_size;
+
+		prefetch_read_many(mp->b_rptr);
+
+		ASSERT3P(mp->b_wptr, ==, DB_BASE(mp));
+		mp->b_wptr += (size_t)(srpp->srp_size);
+		ASSERT3P(mp->b_wptr, <=, DB_LIM(mp));
+
+		/* Calculate the maximum packet size */
+		size = sp->s_mtu;
+		size += (srpp->srp_flags & EFX_PKT_VLAN_TAGGED) ?
+		    sizeof (struct ether_vlan_header) :
+		    sizeof (struct ether_header);
+
+		if (MBLKL(mp) > size)
+			goto discard;
+
+		/* Make the data visible to the kernel */
+		(void) ddi_dma_sync(srpp->srp_dma_handle, 0,
+		    (size_t)(srpp->srp_size), DDI_DMA_SYNC_FORKERNEL);
+
+		/* Check for loopback packets */
+		if (!(srpp->srp_flags & EFX_PKT_IPV4) &&
+		    !(srpp->srp_flags & EFX_PKT_IPV6)) {
+			struct ether_header *etherhp;
+
+			/*LINTED*/
+			etherhp = (struct ether_header *)(mp->b_rptr);
+
+			if (etherhp->ether_type ==
+			    htons(SFXGE_ETHERTYPE_LOOPBACK)) {
+				DTRACE_PROBE(loopback);
+
+				srp->sr_loopback++;
+				goto discard;
+			}
+		}
+
+		/* Set up the checksum information */
+		flags = 0;
+
+		if (srpp->srp_flags & EFX_CKSUM_IPV4) {
+			ASSERT(srpp->srp_flags & EFX_PKT_IPV4);
+			flags |= HCK_IPV4_HDRCKSUM;
+		}
+
+		if (srpp->srp_flags & EFX_CKSUM_TCPUDP) {
+			ASSERT(srpp->srp_flags & EFX_PKT_TCP ||
+			    srpp->srp_flags & EFX_PKT_UDP);
+			flags |= HCK_FULLCKSUM | HCK_FULLCKSUM_OK;
+		}
+
+		DB_CKSUMSTART(mp) = 0;
+		DB_CKSUMSTUFF(mp) = 0;
+		DB_CKSUMEND(mp) = 0;
+		DB_CKSUMFLAGS(mp) = flags;
+		DB_CKSUM16(mp) = 0;
+
+		/* Add the packet to the tail of the chain */
+		srfppp->srfpp_loaned++;
+
+		ASSERT(mp->b_next == NULL);
+		*(srp->sr_mpp) = mp;
+		srp->sr_mpp = &(mp->b_next);
+
+		continue;
+
+discard:
+		/* Return the packet to the pool */
+		srfppp->srfpp_loaned++;
+		freeb(mp); /* Equivalent to freemsg() as b_cont==0 */
+	}
+	srp->sr_completed = completed;
+
+	/* Attempt to coalesce any TCP packets */
+	if (sp->s_rx_coalesce_mode != SFXGE_RX_COALESCE_OFF)
+		sfxge_rx_qpacket_coalesce(srp);
+
+	/*
+	 * If there are any pending flows and this is the end of the
+	 * poll then they must be completed.
+	 */
+	if (srp->sr_srfp != NULL && eop) {
+		sfxge_rx_flow_t *srfp;
+
+		srfp = srp->sr_srfp;
+
+		srp->sr_srfp = NULL;
+		srp->sr_srfpp = &(srp->sr_srfp);
+
+		do {
+			sfxge_rx_flow_t *next;
+
+			next = srfp->srf_next;
+			srfp->srf_next = NULL;
+
+			sfxge_rx_qflow_complete(srp, srfp);
+
+			srfp = next;
+		} while (srfp != NULL);
+	}
+
+	level = srp->sr_added - srp->sr_completed;
+
+	/* If there are any packets then pass them up the stack */
+	if (srp->sr_mp != NULL) {
+		mblk_t *mp;
+
+		mp = srp->sr_mp;
+
+		srp->sr_mp = NULL;
+		srp->sr_mpp = &(srp->sr_mp);
+
+		if (level == 0) {
+			/* Try to refill ASAP */
+			sfxge_rx_qrefill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
+			level = srp->sr_added - srp->sr_completed;
+		}
+
+		/*
+		 * If the RXQ is still empty, discard and recycle the
+		 * current entry to ensure that the ring always
+		 * contains at least one descriptor. This ensures that
+		 * the next hardware RX will trigger an event
+		 * (possibly delayed by interrupt moderation) and
+		 * trigger another refill/fill attempt.
+		 *
+		 * Note this drops a complete LRO fragment from the
+		 * start of the batch.
+		 *
+		 * Note also that copymsgchain() does not help with
+		 * resource starvation here, unless we are short of DMA
+		 * mappings.
+		 */
+		if (level == 0) {
+			mblk_t *nmp;
+
+			srp->sr_kstat.srk_rxq_empty_discard++;
+			DTRACE_PROBE1(rxq_empty_discard, int, index);
+			nmp = mp->b_next;
+			if (nmp)
+				sfxge_gld_rx_post(sp, index, nmp);
+			/* as level==0 will swizzle,rxpost below */
+			freemsg(mp);
+		} else {
+			sfxge_gld_rx_post(sp, index, mp);
+		}
+	}
+
+	/* Top up the queue if necessary */
+	if (level < srp->sr_hiwat) {
+		sfxge_rx_qrefill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
+
+		level = srp->sr_added - srp->sr_completed;
+		if (level < srp->sr_lowat)
+			sfxge_rx_qfill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
+	}
+}
+
+static unsigned int
+sfxge_rx_qloopback(sfxge_t *sp, unsigned int index)
+{
+	sfxge_evq_t *sep = sp->s_sep[index];
+	sfxge_rxq_t *srp;
+	unsigned int count;
+
+	mutex_enter(&(sep->se_lock));
+	srp = sp->s_srp[index];
+	count = srp->sr_loopback;
+	srp->sr_loopback = 0;
+	mutex_exit(&(sep->se_lock));
+
+	return (count);
+}
+
+void
+sfxge_rx_qflush_done(sfxge_rxq_t *srp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	/* SFCbug22989: events may be delayed. EVQs are stopped after RXQs */
+	if ((srp->sr_state != SFXGE_RXQ_INITIALIZED) ||
+	    (srp->sr_flush == SFXGE_FLUSH_DONE))
+		return;
+
+	/* Flush successful: wakeup sfxge_rx_qstop() */
+	srp->sr_flush = SFXGE_FLUSH_DONE;
+	cv_broadcast(&(srp->sr_flush_kv));
+}
+
+void
+sfxge_rx_qflush_failed(sfxge_rxq_t *srp)
+{
+	sfxge_t *sp = srp->sr_sp;
+	unsigned int index = srp->sr_index;
+	sfxge_evq_t *sep = sp->s_sep[index];
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	/* SFCbug22989: events may be delayed. EVQs are stopped after RXQs */
+	if ((srp->sr_state != SFXGE_RXQ_INITIALIZED) ||
+	    (srp->sr_flush == SFXGE_FLUSH_DONE))
+		return;
+
+	/* SFCbug22989: events may be delayed. EVQs are stopped after RXQs */
+	if (srp->sr_state != SFXGE_RXQ_STARTED)
+		return;
+
+	/* Flush failed, so retry until timeout in sfxge_rx_qstop() */
+	srp->sr_flush = SFXGE_FLUSH_FAILED;
+	efx_rx_qflush(srp->sr_erp);
+}
+
+static void
+sfxge_rx_qstop(sfxge_t *sp, unsigned int index)
+{
+	sfxge_evq_t *sep = sp->s_sep[index];
+	sfxge_rxq_t *srp;
+	clock_t timeout;
+
+	mutex_enter(&(sep->se_lock));
+
+	srp = sp->s_srp[index];
+	ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_STARTED);
+
+	sfxge_rx_qpoll_stop(srp);
+
+	srp->sr_state = SFXGE_RXQ_INITIALIZED;
+
+	if (sp->s_hw_err == SFXGE_HW_OK) {
+		/* Wait upto 2sec for queue flushing to complete */
+		srp->sr_flush = SFXGE_FLUSH_PENDING;
+		efx_rx_qflush(srp->sr_erp);
+	} else {
+		/* Do not attempt flush if indication of H/W failure */
+		srp->sr_flush = SFXGE_FLUSH_DONE;
+	}
+
+	timeout = ddi_get_lbolt() + drv_usectohz(SFXGE_RX_QFLUSH_USEC);
+
+	while (srp->sr_flush != SFXGE_FLUSH_DONE) {
+		if (cv_timedwait(&(srp->sr_flush_kv), &(sep->se_lock),
+			timeout) < 0) {
+			/* Timeout waiting for successful flush */
+			dev_info_t *dip = sp->s_dip;
+
+				ddi_driver_name(sp->s_dip),
+			cmn_err(CE_NOTE,
+			    SFXGE_CMN_ERR "[%s%d] rxq[%d] flush timeout",
+			    ddi_driver_name(dip), ddi_get_instance(dip), index);
+			break;
+		}
+	}
+
+	DTRACE_PROBE1(flush, sfxge_flush_state_t, srp->sr_flush);
+	srp->sr_flush = SFXGE_FLUSH_DONE;
+
+	/* Destroy the receive queue */
+	efx_rx_qdestroy(srp->sr_erp);
+	srp->sr_erp = NULL;
+
+	/* Clear entries from the buffer table */
+	sfxge_sram_buf_tbl_clear(sp, srp->sr_id,
+	    EFX_RXQ_NBUFS(sp->s_rxq_size));
+
+	/*
+	 * Free any unused RX packets which had descriptors on the RXQ
+	 * Packets will be discard as state != STARTED
+	 */
+	srp->sr_pending = srp->sr_added;
+	sfxge_rx_qcomplete(srp, B_TRUE);
+
+	ASSERT3U(srp->sr_completed, ==, srp->sr_pending);
+
+	srp->sr_added = 0;
+	srp->sr_pending = 0;
+	srp->sr_completed = 0;
+	srp->sr_loopback = 0;
+
+	srp->sr_lowat = 0;
+	srp->sr_hiwat = 0;
+
+	mutex_exit(&(sep->se_lock));
+}
+
+static void
+sfxge_rx_kstat_fini(sfxge_rxq_t *srp)
+{
+	kstat_delete(srp->sr_ksp);
+	srp->sr_ksp = NULL;
+}
+
+static void
+sfxge_rx_qfini(sfxge_t *sp, unsigned int index)
+{
+	sfxge_rxq_t *srp = sp->s_srp[index];
+
+	ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_INITIALIZED);
+
+	sp->s_srp[index] = NULL;
+	srp->sr_state = SFXGE_RXQ_UNINITIALIZED;
+
+	sfxge_rx_kstat_fini(srp);
+
+	/* Empty the pool */
+	sfxge_rx_qfpp_empty(srp);
+
+	srp->sr_index = 0;
+
+	kmem_cache_free(sp->s_rqc, srp);
+}
+
+static int
+sfxge_rx_scale_kstat_update(kstat_t *ksp, int rw)
+{
+	sfxge_t *sp = ksp->ks_private;
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+	sfxge_intr_t *sip = &(sp->s_intr);
+	kstat_named_t *knp;
+	unsigned int index;
+	unsigned int entry;
+	unsigned int *freq;
+	int rc;
+
+	ASSERT(mutex_owned(&(srsp->srs_lock)));
+
+	if (rw != KSTAT_READ) {
+		rc = EACCES;
+		goto fail1;
+	}
+
+	if ((freq = kmem_zalloc(sizeof (unsigned int) * sip->si_nalloc,
+				KM_NOSLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	for (index = 0; index < sip->si_nalloc; index++)
+		freq[index] = 0;
+
+	for (entry = 0; entry < SFXGE_RX_SCALE_MAX; entry++) {
+		index = srsp->srs_tbl[entry];
+
+		freq[index]++;
+	}
+
+	knp = ksp->ks_data;
+	for (index = 0; index < sip->si_nalloc; index++) {
+		knp->value.ui64 = freq[index];
+		knp++;
+	}
+
+	knp->value.ui64 = srsp->srs_count;
+
+	kmem_free(freq, sizeof (unsigned int) * sip->si_nalloc);
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	return (rc);
+}
+
+static int
+sfxge_rx_scale_kstat_init(sfxge_t *sp)
+{
+	dev_info_t *dip = sp->s_dip;
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+	sfxge_intr_t *sip = &(sp->s_intr);
+	char name[MAXNAMELEN];
+	kstat_t *ksp;
+	kstat_named_t *knp;
+	unsigned int index;
+	int rc;
+
+	/* Create the set */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_rss", ddi_driver_name(dip));
+
+	if ((ksp = kstat_create((char *)ddi_driver_name(dip),
+	    ddi_get_instance(dip), name, "rss", KSTAT_TYPE_NAMED,
+	    sip->si_nalloc + 1, 0)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	srsp->srs_ksp = ksp;
+
+	ksp->ks_update = sfxge_rx_scale_kstat_update;
+	ksp->ks_private = sp;
+	ksp->ks_lock = &(srsp->srs_lock);
+
+	/* Initialise the named stats */
+	knp = ksp->ks_data;
+	for (index = 0; index < sip->si_nalloc; index++) {
+		char name[MAXNAMELEN];
+
+		(void) snprintf(name, MAXNAMELEN - 1, "evq%04d_count", index);
+		kstat_named_init(knp, name, KSTAT_DATA_UINT64);
+		knp++;
+	}
+
+	kstat_named_init(knp, "scale", KSTAT_DATA_UINT64);
+
+	kstat_install(ksp);
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_rx_scale_kstat_fini(sfxge_t *sp)
+{
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+
+	/* Destroy the set */
+	kstat_delete(srsp->srs_ksp);
+	srsp->srs_ksp = NULL;
+}
+
+
+unsigned int
+sfxge_rx_scale_prop_get(sfxge_t *sp)
+{
+	int rx_scale;
+
+	rx_scale = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+				    DDI_PROP_DONTPASS, "rx_scale_count",
+				    SFXGE_RX_SCALE_MAX);
+	/* 0 and all -ve numbers sets to number of logical CPUs */
+	if (rx_scale <= 0)
+		rx_scale = ncpus;
+
+	return (rx_scale);
+}
+
+
+static int
+sfxge_rx_scale_init(sfxge_t *sp)
+{
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+	sfxge_intr_t *sip = &(sp->s_intr);
+	int rc;
+
+	ASSERT3U(srsp->srs_state, ==, SFXGE_RX_SCALE_UNINITIALIZED);
+
+	/* Create tables for CPU, core, cache and chip counts */
+	srsp->srs_cpu = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
+#ifdef	_USE_CPU_PHYSID
+	srsp->srs_core = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
+	srsp->srs_cache = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
+	srsp->srs_chip = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
+#endif
+
+	mutex_init(&(srsp->srs_lock), NULL, MUTEX_DRIVER, NULL);
+
+	/* We need at least one event queue */
+	srsp->srs_count = sfxge_rx_scale_prop_get(sp);
+	if (srsp->srs_count > sip->si_nalloc)
+		srsp->srs_count = sip->si_nalloc;
+	if (srsp->srs_count < 1)
+		srsp->srs_count = 1;
+
+	/* Set up the kstats */
+	if ((rc = sfxge_rx_scale_kstat_init(sp)) != 0)
+		goto fail1;
+
+	srsp->srs_state = SFXGE_RX_SCALE_INITIALIZED;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+	mutex_destroy(&(srsp->srs_lock));
+
+	return (rc);
+}
+
+void
+sfxge_rx_scale_update(void *arg)
+{
+	sfxge_t *sp = arg;
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+	sfxge_intr_t *sip;
+	processorid_t id;
+	unsigned int count;
+	unsigned int *tbl;
+	unsigned int *rating;
+	unsigned int entry;
+	int rc;
+
+	mutex_enter(&(srsp->srs_lock));
+
+	if (srsp->srs_state != SFXGE_RX_SCALE_STARTED) {
+		rc = EFAULT;
+		goto fail1;
+	}
+
+	if ((tbl =  kmem_zalloc(sizeof (unsigned int) * SFXGE_RX_SCALE_MAX,
+			    KM_NOSLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	sip = &(sp->s_intr);
+	if ((rating = kmem_zalloc(sizeof (unsigned int) * sip->si_nalloc,
+			    KM_NOSLEEP)) == NULL) {
+		rc = ENOMEM;
+		goto fail3;
+	}
+
+	mutex_enter(&cpu_lock);
+
+	/*
+	 * Substract any current CPU, core, cache and chip usage from the
+	 * global contention tables.
+	 */
+	for (id = 0; id < NCPU; id++) {
+		ASSERT3U(sfxge_cpu[id], >=, srsp->srs_cpu[id]);
+		sfxge_cpu[id] -= srsp->srs_cpu[id];
+		srsp->srs_cpu[id] = 0;
+
+#ifdef	_USE_CPU_PHYSID
+		ASSERT3U(sfxge_core[id], >=, srsp->srs_core[id]);
+		sfxge_core[id] -= srsp->srs_core[id];
+		srsp->srs_core[id] = 0;
+
+		ASSERT3U(sfxge_cache[id], >=, srsp->srs_cache[id]);
+		sfxge_cache[id] -= srsp->srs_cache[id];
+		srsp->srs_cache[id] = 0;
+
+		ASSERT3U(sfxge_chip[id], >=, srsp->srs_chip[id]);
+		sfxge_chip[id] -= srsp->srs_chip[id];
+		srsp->srs_chip[id] = 0;
+#endif
+	}
+
+	ASSERT(srsp->srs_count != 0);
+
+	/* Choose as many event queues as we need */
+	for (count = 0; count < srsp->srs_count; count++) {
+		unsigned int index;
+		sfxge_evq_t *sep;
+		unsigned int choice;
+		unsigned int choice_rating;
+
+		bzero(rating, sizeof (unsigned int) * sip->si_nalloc);
+
+		/*
+		 * Rate each event queue on its global level of CPU
+		 * contention.
+		 */
+		for (index = 0; index < sip->si_nalloc; index++) {
+			sep = sp->s_sep[index];
+
+			id = sep->se_cpu_id;
+			rating[index] += sfxge_cpu[id];
+
+#ifdef	_USE_CPU_PHYSID
+			id = sep->se_core_id;
+			rating[index] += sfxge_core[id];
+
+			id = sep->se_cache_id;
+			rating[index] += sfxge_cache[id];
+
+			id = sep->se_chip_id;
+			rating[index] += sfxge_chip[id];
+#endif
+		}
+
+		/* Choose the queue with the lowest CPU contention */
+		choice = 0;
+		choice_rating = rating[0];
+
+		for (index = 1; index < sip->si_nalloc; index++) {
+			if (rating[index] < choice_rating) {
+				choice = index;
+				choice_rating = rating[index];
+			}
+		}
+
+		/* Add our choice to the condensed RSS table */
+		tbl[count] = choice;
+
+		/* Add information to the global contention tables */
+		sep = sp->s_sep[choice];
+
+		id = sep->se_cpu_id;
+		srsp->srs_cpu[id]++;
+		sfxge_cpu[id]++;
+
+#ifdef	_USE_CPU_PHYSID
+		id = sep->se_core_id;
+		srsp->srs_core[id]++;
+		sfxge_core[id]++;
+
+		id = sep->se_cache_id;
+		srsp->srs_cache[id]++;
+		sfxge_cache[id]++;
+
+		id = sep->se_chip_id;
+		srsp->srs_chip[id]++;
+		sfxge_chip[id]++;
+#endif
+	}
+
+	mutex_exit(&cpu_lock);
+
+	/* Build the expanded RSS table */
+	count = 0;
+	for (entry = 0; entry < SFXGE_RX_SCALE_MAX; entry++) {
+		unsigned int index;
+
+		index = tbl[count];
+		count = (count + 1) % srsp->srs_count;
+
+		srsp->srs_tbl[entry] = index;
+	}
+
+	/* Program the expanded RSS table into the hardware */
+	(void) efx_rx_scale_tbl_set(sp->s_enp, srsp->srs_tbl,
+	    SFXGE_RX_SCALE_MAX);
+
+	mutex_exit(&(srsp->srs_lock));
+	kmem_free(rating, sizeof (unsigned int) * sip->si_nalloc);
+	kmem_free(tbl, sizeof (unsigned int) * SFXGE_RX_SCALE_MAX);
+	return;
+
+fail3:
+	DTRACE_PROBE(fail3);
+	kmem_free(tbl, sizeof (unsigned int) * SFXGE_RX_SCALE_MAX);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(srsp->srs_lock));
+}
+
+static int
+sfxge_rx_scale_start(sfxge_t *sp)
+{
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+	const efx_nic_cfg_t *encp;
+	int rc;
+
+	mutex_enter(&(srsp->srs_lock));
+
+	ASSERT3U(srsp->srs_state, ==, SFXGE_RX_SCALE_INITIALIZED);
+
+	/* Clear down the RSS table */
+	bzero(srsp->srs_tbl, sizeof (unsigned int) * SFXGE_RX_SCALE_MAX);
+
+	(void) efx_rx_scale_tbl_set(sp->s_enp, srsp->srs_tbl,
+	    SFXGE_RX_SCALE_MAX);
+
+	/* Make sure the LFSR hash is selected */
+	encp = efx_nic_cfg_get(sp->s_enp);
+	if ((rc = efx_rx_scale_mode_set(sp->s_enp, EFX_RX_HASHALG_LFSR, 0,
+	    (encp->enc_features & EFX_FEATURE_LFSR_HASH_INSERT))) != 0)
+		goto fail1;
+
+	srsp->srs_state = SFXGE_RX_SCALE_STARTED;
+
+	mutex_exit(&(srsp->srs_lock));
+
+	/* sfxge_t->s_state_lock held */
+	(void) ddi_taskq_dispatch(sp->s_tqp, sfxge_rx_scale_update, sp,
+	    DDI_SLEEP);
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(srsp->srs_lock));
+
+	return (rc);
+}
+
+int
+sfxge_rx_scale_count_get(sfxge_t *sp, unsigned int *countp)
+{
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+	int rc;
+
+	mutex_enter(&(srsp->srs_lock));
+
+	if (srsp->srs_state != SFXGE_RX_SCALE_INITIALIZED &&
+	    srsp->srs_state != SFXGE_RX_SCALE_STARTED) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	*countp = srsp->srs_count;
+
+	mutex_exit(&(srsp->srs_lock));
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(srsp->srs_lock));
+
+	return (rc);
+}
+
+int
+sfxge_rx_scale_count_set(sfxge_t *sp, unsigned int count)
+{
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+	sfxge_intr_t *sip = &(sp->s_intr);
+	int dispatch = 1;
+	int rc;
+
+	if (count < 1 || count > sip->si_nalloc) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	mutex_enter(&(srsp->srs_lock));
+
+	if (srsp->srs_state != SFXGE_RX_SCALE_INITIALIZED &&
+	    srsp->srs_state != SFXGE_RX_SCALE_STARTED) {
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	srsp->srs_count = count;
+
+	if (srsp->srs_state != SFXGE_RX_SCALE_STARTED)
+		dispatch = 0;
+
+	mutex_exit(&(srsp->srs_lock));
+
+	if (dispatch)
+		/* no locks held */
+		(void) ddi_taskq_dispatch(sp->s_tqp, sfxge_rx_scale_update, sp,
+		    DDI_SLEEP);
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	mutex_exit(&(srsp->srs_lock));
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_rx_scale_stop(sfxge_t *sp)
+{
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+	processorid_t id;
+
+	mutex_enter(&(srsp->srs_lock));
+
+	ASSERT3U(srsp->srs_state, ==, SFXGE_RX_SCALE_STARTED);
+
+	srsp->srs_state = SFXGE_RX_SCALE_INITIALIZED;
+
+	mutex_enter(&cpu_lock);
+
+	/*
+	 * Substract any current CPU, core, cache and chip usage from the
+	 * global contention tables.
+	 */
+	for (id = 0; id < NCPU; id++) {
+		ASSERT3U(sfxge_cpu[id], >=, srsp->srs_cpu[id]);
+		sfxge_cpu[id] -= srsp->srs_cpu[id];
+		srsp->srs_cpu[id] = 0;
+
+#ifdef	_USE_CPU_PHYSID
+		ASSERT3U(sfxge_core[id], >=, srsp->srs_core[id]);
+		sfxge_core[id] -= srsp->srs_core[id];
+		srsp->srs_core[id] = 0;
+
+		ASSERT3U(sfxge_cache[id], >=, srsp->srs_cache[id]);
+		sfxge_cache[id] -= srsp->srs_cache[id];
+		srsp->srs_cache[id] = 0;
+
+		ASSERT3U(sfxge_chip[id], >=, srsp->srs_chip[id]);
+		sfxge_chip[id] -= srsp->srs_chip[id];
+		srsp->srs_chip[id] = 0;
+#endif
+	}
+
+	mutex_exit(&cpu_lock);
+
+	/* Clear down the RSS table */
+	bzero(srsp->srs_tbl, sizeof (unsigned int) * SFXGE_RX_SCALE_MAX);
+
+	(void) efx_rx_scale_tbl_set(sp->s_enp, srsp->srs_tbl,
+	    SFXGE_RX_SCALE_MAX);
+
+	mutex_exit(&(srsp->srs_lock));
+}
+
+static void
+sfxge_rx_scale_fini(sfxge_t *sp)
+{
+	sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+
+	ASSERT3U(srsp->srs_state, ==, SFXGE_RX_SCALE_INITIALIZED);
+
+	srsp->srs_state = SFXGE_RX_SCALE_UNINITIALIZED;
+
+	/* Tear down the kstats */
+	sfxge_rx_scale_kstat_fini(sp);
+
+	srsp->srs_count = 0;
+
+	mutex_destroy(&(srsp->srs_lock));
+
+	/* Destroy tables */
+#ifdef	_USE_CPU_PHYSID
+	kmem_free(srsp->srs_chip, sizeof (unsigned int) * NCPU);
+	srsp->srs_chip = NULL;
+
+	kmem_free(srsp->srs_cache, sizeof (unsigned int) * NCPU);
+	srsp->srs_cache = NULL;
+
+	kmem_free(srsp->srs_core, sizeof (unsigned int) * NCPU);
+	srsp->srs_core = NULL;
+#endif
+	kmem_free(srsp->srs_cpu, sizeof (unsigned int) * NCPU);
+	srsp->srs_cpu = NULL;
+}
+
+int
+sfxge_rx_init(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	const efx_nic_cfg_t *encp;
+	char name[MAXNAMELEN];
+	int index;
+	int rc;
+
+	if (sip->si_state == SFXGE_INTR_UNINITIALIZED) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	encp = efx_nic_cfg_get(sp->s_enp);
+	if ((rc = sfxge_rx_scale_init(sp)) != 0)
+		goto fail2;
+
+	(void) snprintf(name, MAXNAMELEN - 1, "%s%d_rx_packet_cache",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
+
+	sp->s_rpc = kmem_cache_create(name, sizeof (sfxge_rx_packet_t),
+	    SFXGE_CPU_CACHE_SIZE, sfxge_rx_packet_ctor, sfxge_rx_packet_dtor,
+	    NULL, sp, NULL, 0);
+	ASSERT(sp->s_rpc != NULL);
+
+	(void) snprintf(name, MAXNAMELEN - 1, "%s%d_rxq_cache",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
+
+	sp->s_rqc = kmem_cache_create(name, sizeof (sfxge_rxq_t),
+	    SFXGE_CPU_CACHE_SIZE, sfxge_rx_qctor, sfxge_rx_qdtor, NULL, sp,
+	    NULL, 0);
+	ASSERT(sp->s_rqc != NULL);
+
+	sp->s_rx_pkt_mem_max = ddi_prop_get_int64(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "rx_pkt_mem_max", 0); /* disabled */
+
+	/* Initialize the receive queue(s) */
+	for (index = 0; index < sip->si_nalloc; index++) {
+		if ((rc = sfxge_rx_qinit(sp, index)) != 0)
+			goto fail3;
+	}
+
+	sp->s_rx_coalesce_mode = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "rx_coalesce_mode", SFXGE_RX_COALESCE_OFF);
+
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	/* Tear down the receive queue(s) */
+	while (--index >= 0)
+		sfxge_rx_qfini(sp, index);
+
+	kmem_cache_destroy(sp->s_rqc);
+	sp->s_rqc = NULL;
+
+	kmem_cache_destroy(sp->s_rpc);
+	sp->s_rpc = NULL;
+
+	sfxge_rx_scale_fini(sp);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+int
+sfxge_rx_start(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	sfxge_intr_t *sip;
+	const efx_nic_cfg_t *encp;
+	int index;
+	int rc;
+
+	mutex_enter(&(smp->sm_lock));
+
+	/* Calculate the receive packet buffer size and alignment */
+	sp->s_rx_buffer_size = EFX_MAC_PDU(sp->s_mtu);
+
+	encp = efx_nic_cfg_get(sp->s_enp);
+	if (encp->enc_features & EFX_FEATURE_LFSR_HASH_INSERT) {
+		size_t align;
+
+		sp->s_rx_prefix_size = EFX_RX_PREFIX_SIZE;
+
+		/*
+		 * Place the start of the buffer a prefix length minus 2
+		 * before the start of a cache line. This ensures that the
+		 * last two bytes of the prefix (which is where the LFSR hash
+		 * is located) are in the same cache line as the headers, and
+		 * the IP header is 32-bit aligned.
+		 */
+		align = SFXGE_CPU_CACHE_SIZE + SFXGE_IP_ALIGN -
+		    EFX_RX_PREFIX_SIZE;
+
+		sp->s_rx_buffer_align = align;
+		sp->s_rx_buffer_size += align;
+	} else {
+		sp->s_rx_prefix_size = 0;
+
+		/*
+		 * Place the start of the buffer 2 bytes after a cache line
+		 * boundary so that the headers fit into the cache line and
+		 * the IP header is 32-bit aligned.
+		 */
+
+		sp->s_rx_buffer_align = SFXGE_IP_ALIGN;
+		sp->s_rx_buffer_size += SFXGE_IP_ALIGN;
+	}
+
+	/* Initialize the receive module */
+	if ((rc = efx_rx_init(sp->s_enp)) != 0)
+		goto fail1;
+
+	mutex_exit(&(smp->sm_lock));
+
+	if ((rc = sfxge_rx_scale_start(sp)) != 0)
+		goto fail2;
+
+	/* Start the receive queue(s) */
+	sip = &(sp->s_intr);
+	for (index = 0; index < sip->si_nalloc; index++) {
+		if ((rc = sfxge_rx_qstart(sp, index)) != 0)
+			goto fail3;
+	}
+
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	/* Stop the receive queue(s) */
+	while (--index >= 0)
+		sfxge_rx_qstop(sp, index);
+
+	sfxge_rx_scale_stop(sp);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	mutex_enter(&(smp->sm_lock));
+
+	/* Tear down the receive module */
+	efx_rx_fini(sp->s_enp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(smp->sm_lock));
+
+	return (rc);
+}
+
+void
+sfxge_rx_coalesce_mode_get(sfxge_t *sp, sfxge_rx_coalesce_mode_t *modep)
+{
+	*modep = sp->s_rx_coalesce_mode;
+}
+
+int
+sfxge_rx_coalesce_mode_set(sfxge_t *sp, sfxge_rx_coalesce_mode_t mode)
+{
+	int rc;
+
+	switch (mode) {
+	case SFXGE_RX_COALESCE_OFF:
+	case SFXGE_RX_COALESCE_DISALLOW_PUSH:
+	case SFXGE_RX_COALESCE_ALLOW_PUSH:
+		break;
+
+	default:
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	sp->s_rx_coalesce_mode = mode;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_rx_loopback(sfxge_t *sp, unsigned int *countp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	int index;
+
+	*countp = 0;
+	for (index = 0; index < sip->si_nalloc; index++)
+		*countp += sfxge_rx_qloopback(sp, index);
+}
+
+int
+sfxge_rx_ioctl(sfxge_t *sp, sfxge_rx_ioc_t *srip)
+{
+	int rc;
+
+	switch (srip->sri_op) {
+	case SFXGE_RX_OP_LOOPBACK: {
+		unsigned int count;
+
+		sfxge_rx_loopback(sp, &count);
+
+		srip->sri_data = count;
+
+		break;
+	}
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_rx_stop(sfxge_t *sp)
+{
+	sfxge_mac_t *smp = &(sp->s_mac);
+	sfxge_intr_t *sip = &(sp->s_intr);
+	efx_nic_t *enp = sp->s_enp;
+	const efx_nic_cfg_t *encp;
+	int index;
+
+	/* Stop the receive queue(s) */
+	index = sip->si_nalloc;
+	while (--index >= 0)
+		/* TBD: Flush RXQs in parallel; HW has limit + may need retry */
+		sfxge_rx_qstop(sp, index);
+
+	encp = efx_nic_cfg_get(sp->s_enp);
+	sfxge_rx_scale_stop(sp);
+
+	mutex_enter(&(smp->sm_lock));
+
+	/* Tear down the receive module */
+	efx_rx_fini(enp);
+
+	sp->s_rx_buffer_align = 0;
+	sp->s_rx_prefix_size = 0;
+	sp->s_rx_buffer_size = 0;
+
+	mutex_exit(&(smp->sm_lock));
+}
+
+unsigned int
+sfxge_rx_loaned(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	int index;
+	unsigned int loaned;
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
+
+	loaned = 0;
+	for (index = 0; index < sip->si_nalloc; index++) {
+		sfxge_rxq_t *srp = sp->s_srp[index];
+		sfxge_evq_t *sep = sp->s_sep[srp->sr_index];
+
+		mutex_enter(&(sep->se_lock));
+
+		loaned += sfxge_rx_qfpp_swizzle(srp);
+
+		mutex_exit(&(sep->se_lock));
+	}
+
+	return (loaned);
+}
+
+void
+sfxge_rx_fini(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	const efx_nic_cfg_t *encp;
+	int index;
+
+	ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
+
+	sp->s_rx_coalesce_mode = SFXGE_RX_COALESCE_OFF;
+
+	/* Tear down the receive queue(s) */
+	index = sip->si_nalloc;
+	while (--index >= 0)
+		sfxge_rx_qfini(sp, index);
+
+	ASSERT3U(sp->s_rx_pkt_mem_alloc, ==, 0);
+
+	kmem_cache_destroy(sp->s_rqc);
+	sp->s_rqc = NULL;
+
+	kmem_cache_destroy(sp->s_rpc);
+	sp->s_rpc = NULL;
+
+	encp = efx_nic_cfg_get(sp->s_enp);
+	sfxge_rx_scale_fini(sp);
+}
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_sram.c	2013-08-22 18:57:34.836934954 -0400
@@ -0,0 +1,259 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stream.h>
+#include <sys/dlpi.h>
+
+#include "sfxge.h"
+
+void
+sfxge_sram_init(sfxge_t *sp)
+{
+	sfxge_sram_t *ssp = &(sp->s_sram);
+	dev_info_t *dip = sp->s_dip;
+	char name[MAXNAMELEN];
+
+	ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_UNINITIALIZED);
+
+	mutex_init(&(ssp->ss_lock), NULL, MUTEX_DRIVER, NULL);
+
+	/*
+	 * Create a VMEM arena for the buffer table
+	 * Note that these are not in the DDI/DKI.
+	 * See "man rmalloc" for a possible alternative
+	 */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s%d_sram", ddi_driver_name(dip),
+	    ddi_get_instance(dip));
+	ssp->ss_buf_tbl = vmem_create(name, (void *)1, EFX_BUF_TBL_SIZE, 1,
+	    NULL, NULL, NULL, 1, VM_SLEEP | VMC_IDENTIFIER);
+
+	ssp->ss_state = SFXGE_SRAM_INITIALIZED;
+}
+
+int
+sfxge_sram_buf_tbl_alloc(sfxge_t *sp, size_t n, uint32_t *idp)
+{
+	sfxge_sram_t *ssp = &(sp->s_sram);
+	void *base;
+	int rc;
+
+	mutex_enter(&(ssp->ss_lock));
+
+	ASSERT(ssp->ss_state != SFXGE_SRAM_UNINITIALIZED);
+
+	if ((base = vmem_alloc(ssp->ss_buf_tbl, n, VM_NOSLEEP)) == NULL) {
+		rc = ENOSPC;
+		goto fail1;
+	}
+
+	*idp = (uint32_t)((uintptr_t)base - 1);
+
+	mutex_exit(&(ssp->ss_lock));
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(ssp->ss_lock));
+
+	return (rc);
+}
+
+int
+sfxge_sram_start(sfxge_t *sp)
+{
+	sfxge_sram_t *ssp = &(sp->s_sram);
+
+	mutex_enter(&(ssp->ss_lock));
+
+	ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_INITIALIZED);
+	ASSERT3U(ssp->ss_count, ==, 0);
+
+	ssp->ss_state = SFXGE_SRAM_STARTED;
+
+	mutex_exit(&(ssp->ss_lock));
+
+	return (0);
+}
+
+int
+sfxge_sram_buf_tbl_set(sfxge_t *sp, uint32_t id, efsys_mem_t *esmp,
+    size_t n)
+{
+	sfxge_sram_t *ssp = &(sp->s_sram);
+	int rc;
+
+	mutex_enter(&(ssp->ss_lock));
+
+	ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
+
+	if ((rc = efx_sram_buf_tbl_set(sp->s_enp, id, esmp, n)) != 0)
+		goto fail1;
+
+	ssp->ss_count += n;
+
+	mutex_exit(&(ssp->ss_lock));
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(ssp->ss_lock));
+
+	return (rc);
+}
+
+void
+sfxge_sram_buf_tbl_clear(sfxge_t *sp, uint32_t id, size_t n)
+{
+	sfxge_sram_t *ssp = &(sp->s_sram);
+
+	mutex_enter(&(ssp->ss_lock));
+
+	ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
+
+	ASSERT3U(ssp->ss_count, >=, n);
+	ssp->ss_count -= n;
+
+	efx_sram_buf_tbl_clear(sp->s_enp, id, n);
+
+	mutex_exit(&(ssp->ss_lock));
+}
+
+void
+sfxge_sram_stop(sfxge_t *sp)
+{
+	sfxge_sram_t *ssp = &(sp->s_sram);
+
+	mutex_enter(&(ssp->ss_lock));
+
+	ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
+	ASSERT3U(ssp->ss_count, ==, 0);
+
+	ssp->ss_state = SFXGE_SRAM_INITIALIZED;
+
+	mutex_exit(&(ssp->ss_lock));
+}
+
+void
+sfxge_sram_buf_tbl_free(sfxge_t *sp, uint32_t id, size_t n)
+{
+	sfxge_sram_t *ssp = &(sp->s_sram);
+	void *base;
+
+	mutex_enter(&(ssp->ss_lock));
+
+	ASSERT(ssp->ss_state != SFXGE_SRAM_UNINITIALIZED);
+
+	base = (void *)((uintptr_t)id + 1);
+	vmem_free(ssp->ss_buf_tbl, base, n);
+
+	mutex_exit(&(ssp->ss_lock));
+}
+
+static int
+sfxge_sram_test(sfxge_t *sp, efx_pattern_type_t type)
+{
+	sfxge_sram_t *ssp = &(sp->s_sram);
+	int rc;
+
+	if (ssp->ss_state != SFXGE_SRAM_INITIALIZED) {
+		rc = EFAULT;
+		goto fail1;
+	}
+
+	if (type >= EFX_PATTERN_NTYPES) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	mutex_enter(&(ssp->ss_lock));
+
+	if ((rc = efx_sram_test(sp->s_enp, type)) != 0)
+		goto fail3;
+
+	mutex_exit(&(ssp->ss_lock));
+
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+	mutex_exit(&(ssp->ss_lock));
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+int
+sfxge_sram_ioctl(sfxge_t *sp, sfxge_sram_ioc_t *ssip)
+{
+	int rc;
+
+	switch (ssip->ssi_op) {
+	case SFXGE_SRAM_OP_TEST: {
+		efx_pattern_type_t type = ssip->ssi_data;
+
+		if ((rc = sfxge_sram_test(sp, type)) != 0)
+			goto fail1;
+
+		break;
+	}
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_sram_fini(sfxge_t *sp)
+{
+	sfxge_sram_t *ssp = &(sp->s_sram);
+
+	ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_INITIALIZED);
+
+	/* Destroy the VMEM arena */
+	vmem_destroy(ssp->ss_buf_tbl);
+	ssp->ss_buf_tbl = NULL;
+
+	mutex_destroy(&(ssp->ss_lock));
+
+	ssp->ss_state = SFXGE_SRAM_UNINITIALIZED;
+}
--- /dev/null	2013-08-22 18:57:34.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_tcp.c	2013-08-22 18:57:34.922861647 -0400
@@ -0,0 +1,142 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/pattr.h>
+
+#include <sys/ethernet.h>
+#include <inet/ip.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include "sfxge.h"
+
+#include "efx.h"
+
+void
+sfxge_tcp_parse(mblk_t *mp, struct ether_header **etherhpp, struct ip **iphpp,
+    struct tcphdr **thpp, size_t *offp, size_t *sizep)
+{
+	struct ether_header *etherhp;
+	uint16_t ether_type;
+	size_t etherhs;
+	struct ip *iphp;
+	size_t iphs;
+	struct tcphdr *thp;
+	size_t ths;
+	size_t off;
+	size_t size;
+
+	etherhp = NULL;
+	iphp = NULL;
+	thp = NULL;
+	off = 0;
+	size = 0;
+
+	/* Grab the MAC header */
+	if (MBLKL(mp) < sizeof (struct ether_header))
+		if (!pullupmsg(mp, sizeof (struct ether_header)))
+			goto done;
+
+	/*LINTED*/
+	etherhp = (struct ether_header *)(mp->b_rptr);
+	ether_type = etherhp->ether_type;
+	etherhs = sizeof (struct ether_header);
+
+	if (ether_type == htons(ETHERTYPE_VLAN)) {
+		struct ether_vlan_header *ethervhp;
+
+		if (MBLKL(mp) < sizeof (struct ether_vlan_header))
+			if (!pullupmsg(mp, sizeof (struct ether_vlan_header)))
+				goto done;
+
+		/*LINTED*/
+		ethervhp = (struct ether_vlan_header *)(mp->b_rptr);
+		ether_type = ethervhp->ether_type;
+		etherhs = sizeof (struct ether_vlan_header);
+	}
+
+	if (ether_type != htons(ETHERTYPE_IP))
+		goto done;
+
+	/* Skip over the MAC header */
+	off += etherhs;
+
+	/* Grab the IP header */
+	if (MBLKL(mp) < off + sizeof (struct ip))
+		if (!pullupmsg(mp, off + sizeof (struct ip)))
+			goto done;
+
+	/*LINTED*/
+	iphp = (struct ip *)(mp->b_rptr + off);
+	iphs = iphp->ip_hl * 4;
+
+	if (iphp->ip_v != IPV4_VERSION)
+		goto done;
+
+	/* Get the size of the packet */
+	size = ntohs(iphp->ip_len);
+
+	ASSERT3U(etherhs + size, <=, msgdsize(mp));
+
+	if (iphp->ip_p != IPPROTO_TCP)
+		goto done;
+
+	/* Skip over the IP header */
+	off += iphs;
+	size -= iphs;
+
+	/* Grab the TCP header */
+	if (MBLKL(mp) < off + sizeof (struct tcphdr))
+		if (!pullupmsg(mp, off + sizeof (struct tcphdr)))
+			goto done;
+
+	/*LINTED*/
+	thp = (struct tcphdr *)(mp->b_rptr + off);
+	ths = thp->th_off * 4;
+
+	/* Skip over the TCP header */
+	off += ths;
+	size -= ths;
+
+	if (MBLKL(mp) < off)
+		(void) pullupmsg(mp, off);
+
+done:
+	*etherhpp = etherhp;
+	*iphpp = iphp;
+	*thpp = thp;
+	*offp = off;
+	*sizep = size;
+}
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_tx.c	2013-08-22 18:57:35.010504816 -0400
@@ -0,0 +1,3041 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/atomic.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/strsubr.h>
+#include <sys/pattr.h>
+#include <sys/cpu.h>
+
+#include <sys/ethernet.h>
+#include <inet/ip.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include "sfxge.h"
+
+#include "efx.h"
+
+/* TXQ flush response timeout (in microseconds) */
+#define	SFXGE_TX_QFLUSH_USEC	(2000000)
+#define	EVQ_0 0
+
+/* See sfxge.conf.private for descriptions */
+#define	SFXGE_TX_DPL_GET_PKT_LIMIT_DEFAULT 4096
+#define	SFXGE_TX_DPL_PUT_PKT_LIMIT_DEFAULT 256
+
+
+/* Transmit buffer DMA attributes */
+static ddi_device_acc_attr_t sfxge_tx_buffer_devacc = {
+
+	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
+	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
+	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
+};
+
+static ddi_dma_attr_t sfxge_tx_buffer_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	SFXGE_TX_BUFFER_SIZE,	/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	1,			/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+/* Transmit mapping DMA attributes */
+static ddi_dma_attr_t sfxge_tx_mapping_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	1,			/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	0x7fffffff,		/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+/* Transmit queue DMA attributes */
+static ddi_device_acc_attr_t sfxge_txq_devacc = {
+
+	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
+	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
+	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
+};
+
+static ddi_dma_attr_t sfxge_txq_dma_attr = {
+	DMA_ATTR_V0,		/* dma_attr_version	*/
+	0,			/* dma_attr_addr_lo	*/
+	0xffffffffffffffffull,	/* dma_attr_addr_hi	*/
+	0xffffffffffffffffull,	/* dma_attr_count_max	*/
+	EFX_BUF_SIZE,		/* dma_attr_align	*/
+	0xffffffff,		/* dma_attr_burstsizes	*/
+	1,			/* dma_attr_minxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_maxxfer	*/
+	0xffffffffffffffffull,	/* dma_attr_seg		*/
+	1,			/* dma_attr_sgllen	*/
+	1,			/* dma_attr_granular	*/
+	0			/* dma_attr_flags	*/
+};
+
+
+/*
+ * A sfxge_tx_qdpl_swizzle() can happen when the DPL get list is one packet
+ * under the limit, and must move all packets from the DPL put->get list
+ * Hence this is the real maximum length of the TX DPL get list.
+ */
+static int
+sfxge_tx_dpl_get_pkt_max(sfxge_txq_t *stp)
+{
+	sfxge_tx_dpl_t *stdp = &(stp->st_dpl);
+	return (stdp->get_pkt_limit + stdp->put_pkt_limit - 1);
+}
+
+
+static int
+sfxge_tx_packet_ctor(void *buf, void *arg, int kmflags)
+{
+	_NOTE(ARGUNUSED(arg, kmflags))
+
+	bzero(buf, sizeof (sfxge_tx_packet_t));
+
+	return (0);
+}
+
+static void
+sfxge_tx_packet_dtor(void *buf, void *arg)
+{
+	sfxge_tx_packet_t *stpp = buf;
+
+	_NOTE(ARGUNUSED(arg))
+
+	SFXGE_OBJ_CHECK(stpp, sfxge_tx_packet_t);
+}
+
+static int
+sfxge_tx_buffer_ctor(void *buf, void *arg, int kmflags)
+{
+	sfxge_tx_buffer_t *stbp = buf;
+	sfxge_t *sp = arg;
+	sfxge_dma_buffer_attr_t dma_attr;
+	int rc;
+
+	bzero(buf, sizeof (sfxge_tx_buffer_t));
+
+	dma_attr.sdba_dip	 = sp->s_dip;
+	dma_attr.sdba_dattrp	 = &sfxge_tx_buffer_dma_attr;
+	dma_attr.sdba_callback	 = ((kmflags == KM_SLEEP) ?
+	    DDI_DMA_SLEEP : DDI_DMA_DONTWAIT);
+	dma_attr.sdba_length	 = SFXGE_TX_BUFFER_SIZE;
+	dma_attr.sdba_memflags	 = DDI_DMA_STREAMING;
+	dma_attr.sdba_devaccp	 = &sfxge_tx_buffer_devacc;
+	dma_attr.sdba_bindflags	 = DDI_DMA_WRITE | DDI_DMA_STREAMING;
+	dma_attr.sdba_maxcookies = 1;
+	dma_attr.sdba_zeroinit	 = B_FALSE;
+
+	if ((rc = sfxge_dma_buffer_create(&(stbp->stb_esm), &dma_attr)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	SFXGE_OBJ_CHECK(stbp, sfxge_tx_buffer_t);
+
+	return (-1);
+}
+
+static void
+sfxge_tx_buffer_dtor(void *buf, void *arg)
+{
+	sfxge_tx_buffer_t *stbp = buf;
+
+	_NOTE(ARGUNUSED(arg))
+
+	sfxge_dma_buffer_destroy(&(stbp->stb_esm));
+
+	SFXGE_OBJ_CHECK(stbp, sfxge_tx_buffer_t);
+}
+
+static int
+sfxge_tx_mapping_ctor(void *buf, void *arg, int kmflags)
+{
+	sfxge_tx_mapping_t *stmp = buf;
+	sfxge_t *sp = arg;
+	dev_info_t *dip = sp->s_dip;
+	int rc;
+
+	bzero(buf, sizeof (sfxge_tx_mapping_t));
+
+	stmp->stm_sp = sp;
+
+	/* Allocate DMA handle */
+	rc = ddi_dma_alloc_handle(dip, &sfxge_tx_mapping_dma_attr,
+	    (kmflags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
+	    NULL, &(stmp->stm_dma_handle));
+	if (rc != DDI_SUCCESS)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	stmp->stm_sp = NULL;
+
+	SFXGE_OBJ_CHECK(stmp, sfxge_tx_mapping_t);
+
+	return (-1);
+}
+
+static void
+sfxge_tx_mapping_dtor(void *buf, void *arg)
+{
+	sfxge_tx_mapping_t *stmp = buf;
+
+	_NOTE(ARGUNUSED(arg))
+
+	ASSERT3P(stmp->stm_sp, ==, arg);
+
+	/* Free the DMA handle */
+	ddi_dma_free_handle(&(stmp->stm_dma_handle));
+	stmp->stm_dma_handle = NULL;
+
+	stmp->stm_sp = NULL;
+
+	SFXGE_OBJ_CHECK(stmp, sfxge_tx_mapping_t);
+}
+
+static int
+sfxge_tx_qctor(void *buf, void *arg, int kmflags)
+{
+	sfxge_txq_t *stp = buf;
+	efsys_mem_t *esmp = &(stp->st_mem);
+	sfxge_t *sp = arg;
+	sfxge_dma_buffer_attr_t dma_attr;
+	sfxge_tx_dpl_t *stdp;
+	int rc;
+
+	/* Compile-time structure layout checks */
+	EFX_STATIC_ASSERT(sizeof (stp->__st_u1.__st_s1) <=
+	    sizeof (stp->__st_u1.__st_pad));
+	EFX_STATIC_ASSERT(sizeof (stp->__st_u2.__st_s2) <=
+	    sizeof (stp->__st_u2.__st_pad));
+	EFX_STATIC_ASSERT(sizeof (stp->__st_u3.__st_s3) <=
+	    sizeof (stp->__st_u3.__st_pad));
+	EFX_STATIC_ASSERT(sizeof (stp->__st_u4.__st_s4) <=
+	    sizeof (stp->__st_u4.__st_pad));
+
+	bzero(buf, sizeof (sfxge_txq_t));
+
+	stp->st_sp = sp;
+
+	dma_attr.sdba_dip	 = sp->s_dip;
+	dma_attr.sdba_dattrp	 = &sfxge_txq_dma_attr;
+	dma_attr.sdba_callback	 = DDI_DMA_SLEEP;
+	dma_attr.sdba_length	 = EFX_TXQ_SIZE(SFXGE_TX_NDESCS);
+	dma_attr.sdba_memflags	 = DDI_DMA_CONSISTENT;
+	dma_attr.sdba_devaccp	 = &sfxge_txq_devacc;
+	dma_attr.sdba_bindflags	 = DDI_DMA_READ | DDI_DMA_CONSISTENT;
+	dma_attr.sdba_maxcookies = EFX_TXQ_NBUFS(SFXGE_TX_NDESCS);
+	dma_attr.sdba_zeroinit	 = B_FALSE;
+
+	if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
+		goto fail1;
+
+	/* Allocate some buffer table entries */
+	if ((rc = sfxge_sram_buf_tbl_alloc(sp, EFX_TXQ_NBUFS(SFXGE_TX_NDESCS),
+	    &(stp->st_id))) != 0)
+		goto fail2;
+
+	/* Allocate the descriptor array */
+	if ((stp->st_eb = kmem_zalloc(sizeof (efx_buffer_t) *
+	    EFX_TXQ_LIMIT(SFXGE_TX_NDESCS), kmflags)) == NULL) {
+		rc = ENOMEM;
+		goto fail3;
+	}
+
+	/* Allocate the context arrays */
+	if ((stp->st_stmp = kmem_zalloc(sizeof (sfxge_tx_mapping_t *) *
+	    SFXGE_TX_NDESCS, kmflags)) == NULL) {
+		rc = ENOMEM;
+		goto fail4;
+	}
+
+	if ((stp->st_stbp = kmem_zalloc(sizeof (sfxge_tx_buffer_t *) *
+	    SFXGE_TX_NDESCS, kmflags)) == NULL) {
+		rc = ENOMEM;
+		goto fail5;
+	}
+
+	if ((stp->st_mp = kmem_zalloc(sizeof (mblk_t *) *
+	    SFXGE_TX_NDESCS, kmflags)) == NULL) {
+		rc = ENOMEM;
+		goto fail6;
+	}
+
+	/* Initialize the deferred packet list */
+	stdp = &(stp->st_dpl);
+	stdp->std_getp = &(stdp->std_get);
+
+	stp->st_unblock = SFXGE_TXQ_NOT_BLOCKED;
+
+	return (0);
+
+fail6:
+	DTRACE_PROBE(fail6);
+
+	kmem_free(stp->st_stbp, sizeof (sfxge_tx_buffer_t *) * SFXGE_TX_NDESCS);
+	stp->st_stbp = NULL;
+
+fail5:
+	DTRACE_PROBE(fail5);
+
+	kmem_free(stp->st_stmp,
+	    sizeof (sfxge_tx_mapping_t *) * SFXGE_TX_NDESCS);
+	stp->st_stmp = NULL;
+
+fail4:
+	DTRACE_PROBE(fail4);
+
+	/* Free the descriptor array */
+	kmem_free(stp->st_eb, sizeof (efx_buffer_t) *
+	    EFX_TXQ_LIMIT(SFXGE_TX_NDESCS));
+	stp->st_eb = NULL;
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	/* Free the buffer table entries */
+	sfxge_sram_buf_tbl_free(sp, stp->st_id, EFX_TXQ_NBUFS(SFXGE_TX_NDESCS));
+	stp->st_id = 0;
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Tear down DMA setup */
+	sfxge_dma_buffer_destroy(esmp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	stp->st_sp = NULL;
+
+	SFXGE_OBJ_CHECK(stp, sfxge_txq_t);
+
+	return (-1);
+}
+
+static void
+sfxge_tx_qdtor(void *buf, void *arg)
+{
+	sfxge_txq_t *stp = buf;
+	efsys_mem_t *esmp = &(stp->st_mem);
+	sfxge_t *sp = stp->st_sp;
+	sfxge_tx_dpl_t *stdp;
+
+	_NOTE(ARGUNUSED(arg))
+
+	stp->st_unblock = 0;
+
+	/* Tear down the deferred packet list */
+	stdp = &(stp->st_dpl);
+	ASSERT3P(stdp->std_getp, ==, &(stdp->std_get));
+	stdp->std_getp = NULL;
+
+	/* Free the context arrays */
+	kmem_free(stp->st_mp, sizeof (mblk_t *) * SFXGE_TX_NDESCS);
+	stp->st_mp = NULL;
+
+	kmem_free(stp->st_stbp, sizeof (sfxge_tx_buffer_t *) * SFXGE_TX_NDESCS);
+	stp->st_stbp = NULL;
+
+	kmem_free(stp->st_stmp,
+	    sizeof (sfxge_tx_mapping_t *) * SFXGE_TX_NDESCS);
+	stp->st_stmp = NULL;
+
+	/* Free the descriptor array */
+	kmem_free(stp->st_eb, sizeof (efx_buffer_t) *
+	    EFX_TXQ_LIMIT(SFXGE_TX_NDESCS));
+	stp->st_eb = NULL;
+
+	/* Free the buffer table entries */
+	sfxge_sram_buf_tbl_free(sp, stp->st_id, EFX_TXQ_NBUFS(SFXGE_TX_NDESCS));
+	stp->st_id = 0;
+
+	/* Tear down dma setup */
+	sfxge_dma_buffer_destroy(esmp);
+
+	stp->st_sp = NULL;
+
+	SFXGE_OBJ_CHECK(stp, sfxge_txq_t);
+}
+
+static void
+sfxge_tx_packet_destroy(sfxge_t *sp, sfxge_tx_packet_t *stpp)
+{
+	kmem_cache_free(sp->s_tpc, stpp);
+}
+
+static sfxge_tx_packet_t *
+sfxge_tx_packet_create(sfxge_t *sp)
+{
+	sfxge_tx_packet_t *stpp;
+
+	stpp = kmem_cache_alloc(sp->s_tpc, KM_NOSLEEP);
+
+	return (stpp);
+}
+
+static inline int
+sfxge_tx_qfpp_put(sfxge_txq_t *stp, sfxge_tx_packet_t *stpp)
+{
+	sfxge_tx_fpp_t *stfp = &(stp->st_fpp);
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	ASSERT3P(stpp->stp_next, ==, NULL);
+	ASSERT3P(stpp->stp_mp, ==, NULL);
+	ASSERT3P(stpp->stp_etherhp, ==, NULL);
+	ASSERT3P(stpp->stp_iphp, ==, NULL);
+	ASSERT3P(stpp->stp_thp, ==, NULL);
+	ASSERT3U(stpp->stp_off, ==, 0);
+	ASSERT3U(stpp->stp_size, ==, 0);
+	ASSERT3U(stpp->stp_mss, ==, 0);
+	ASSERT3U(stpp->stp_dpl_put_len, ==, 0);
+
+	if (stfp->stf_count < SFXGE_TX_FPP_MAX) {
+		/* Add to the start of the list */
+		stpp->stp_next = stfp->stf_stpp;
+		stfp->stf_stpp = stpp;
+		stfp->stf_count++;
+
+		return (0);
+	}
+
+	DTRACE_PROBE(fpp_full);
+	return (ENOSPC);
+}
+
+static inline sfxge_tx_packet_t *
+sfxge_tx_qfpp_get(sfxge_txq_t *stp)
+{
+	sfxge_tx_packet_t *stpp;
+	sfxge_tx_fpp_t *stfp = &(stp->st_fpp);
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	stpp = stfp->stf_stpp;
+	if (stpp == NULL) {
+		ASSERT3U(stfp->stf_count, ==, 0);
+		return (NULL);
+	}
+
+	/* Remove item from the head of the list */
+	stfp->stf_stpp = stpp->stp_next;
+	stpp->stp_next = NULL;
+
+	ASSERT3U(stfp->stf_count, >, 0);
+	stfp->stf_count--;
+
+	if (stfp->stf_count != 0) {
+		ASSERT(stfp->stf_stpp != NULL);
+		prefetch_read_many(stfp->stf_stpp);
+	}
+	return (stpp);
+}
+
+static void
+sfxge_tx_qfpp_empty(sfxge_txq_t *stp)
+{
+	sfxge_t *sp = stp->st_sp;
+	sfxge_tx_fpp_t *stfp = &(stp->st_fpp);
+	sfxge_tx_packet_t *stpp;
+
+	mutex_enter(&(stp->st_lock));
+
+	stpp = stfp->stf_stpp;
+	stfp->stf_stpp = NULL;
+
+	while (stpp != NULL) {
+		sfxge_tx_packet_t *next;
+
+		next = stpp->stp_next;
+		stpp->stp_next = NULL;
+
+		ASSERT3U(stfp->stf_count, >, 0);
+		stfp->stf_count--;
+
+		sfxge_tx_packet_destroy(sp, stpp);
+
+		stpp = next;
+	}
+	ASSERT3U(stfp->stf_count, ==, 0);
+
+	mutex_exit(&(stp->st_lock));
+}
+
+static inline void
+sfxge_tx_qfbp_put(sfxge_txq_t *stp, sfxge_tx_buffer_t *stbp)
+{
+	sfxge_tx_fbp_t *stfp = &(stp->st_fbp);
+
+	ASSERT3P(stbp->stb_next, ==, NULL);
+	ASSERT3U(stbp->stb_off, ==, 0);
+	ASSERT3U(stbp->stb_esm.esm_size, ==, 0);
+
+	stbp->stb_next = stfp->stf_stbp;
+	stfp->stf_stbp = stbp;
+	stfp->stf_count++;
+}
+
+
+static inline sfxge_tx_buffer_t *
+sfxge_tx_qfbp_get(sfxge_txq_t *stp)
+{
+	sfxge_tx_buffer_t *stbp;
+	sfxge_tx_fbp_t *stfp = &(stp->st_fbp);
+
+	stbp = stfp->stf_stbp;
+	if (stbp == NULL) {
+		ASSERT3U(stfp->stf_count, ==, 0);
+		return (NULL);
+	}
+
+	stfp->stf_stbp = stbp->stb_next;
+	stbp->stb_next = NULL;
+
+	ASSERT3U(stfp->stf_count, >, 0);
+	stfp->stf_count--;
+
+	if (stfp->stf_count != 0) {
+		ASSERT(stfp->stf_stbp != NULL);
+		prefetch_read_many(stfp->stf_stbp);
+	}
+
+	return (stbp);
+}
+
+static void
+sfxge_tx_qfbp_empty(sfxge_txq_t *stp)
+{
+	sfxge_t *sp = stp->st_sp;
+	sfxge_tx_fbp_t *stfp = &(stp->st_fbp);
+	sfxge_tx_buffer_t *stbp;
+
+	mutex_enter(&(stp->st_lock));
+
+	stbp = stfp->stf_stbp;
+	stfp->stf_stbp = NULL;
+
+	while (stbp != NULL) {
+		sfxge_tx_buffer_t *next;
+
+		next = stbp->stb_next;
+		stbp->stb_next = NULL;
+
+		ASSERT3U(stfp->stf_count, >, 0);
+		stfp->stf_count--;
+
+		kmem_cache_free(sp->s_tbc, stbp);
+
+		stbp = next;
+	}
+	ASSERT3U(stfp->stf_count, ==, 0);
+
+	mutex_exit(&(stp->st_lock));
+}
+
+static inline void
+sfxge_tx_qfmp_put(sfxge_txq_t *stp, sfxge_tx_mapping_t *stmp)
+{
+	sfxge_tx_fmp_t *stfp = &(stp->st_fmp);
+
+	ASSERT3P(stmp->stm_next, ==, NULL);
+	ASSERT3P(stmp->stm_mp, ==, NULL);
+	ASSERT3P(stmp->stm_base, ==, NULL);
+	ASSERT3U(stmp->stm_off, ==, 0);
+	ASSERT3U(stmp->stm_size, ==, 0);
+
+	stmp->stm_next = stfp->stf_stmp;
+	stfp->stf_stmp = stmp;
+	stfp->stf_count++;
+}
+
+static inline sfxge_tx_mapping_t *
+sfxge_tx_qfmp_get(sfxge_txq_t *stp)
+{
+	sfxge_tx_mapping_t *stmp;
+	sfxge_tx_fmp_t *stfp = &(stp->st_fmp);
+
+	stmp = stfp->stf_stmp;
+	if (stmp == NULL) {
+		ASSERT3U(stfp->stf_count, ==, 0);
+		return (NULL);
+	}
+
+	stfp->stf_stmp = stmp->stm_next;
+	stmp->stm_next = NULL;
+
+	ASSERT3U(stfp->stf_count, >, 0);
+	stfp->stf_count--;
+
+	if (stfp->stf_count != 0) {
+		ASSERT(stfp->stf_stmp != NULL);
+		prefetch_read_many(stfp->stf_stmp);
+	}
+	return (stmp);
+}
+
+static void
+sfxge_tx_qfmp_empty(sfxge_txq_t *stp)
+{
+	sfxge_t *sp = stp->st_sp;
+	sfxge_tx_fmp_t *stfp = &(stp->st_fmp);
+	sfxge_tx_mapping_t *stmp;
+
+	mutex_enter(&(stp->st_lock));
+
+	stmp = stfp->stf_stmp;
+	stfp->stf_stmp = NULL;
+
+	while (stmp != NULL) {
+		sfxge_tx_mapping_t *next;
+
+		next = stmp->stm_next;
+		stmp->stm_next = NULL;
+
+		ASSERT3U(stfp->stf_count, >, 0);
+		stfp->stf_count--;
+
+		kmem_cache_free(sp->s_tmc, stmp);
+
+		stmp = next;
+	}
+	ASSERT3U(stfp->stf_count, ==, 0);
+
+	mutex_exit(&(stp->st_lock));
+}
+
+static void
+sfxge_tx_msgb_unbind(sfxge_tx_mapping_t *stmp)
+{
+	bzero(stmp->stm_addr, sizeof (uint64_t) * SFXGE_TX_MAPPING_NADDR);
+	stmp->stm_off = 0;
+
+	(void) ddi_dma_unbind_handle(stmp->stm_dma_handle);
+
+	stmp->stm_size = 0;
+	stmp->stm_base = NULL;
+
+	stmp->stm_mp = NULL;
+}
+
+#define	SFXGE_TX_DESCSHIFT	12
+#define	SFXGE_TX_DESCSIZE	(1 << 12)
+
+#define	SFXGE_TX_DESCOFFSET	(SFXGE_TX_DESCSIZE - 1)
+#define	SFXGE_TX_DESCMASK	(~SFXGE_TX_DESCOFFSET)
+
+static int
+sfxge_tx_msgb_bind(mblk_t *mp, sfxge_tx_mapping_t *stmp)
+{
+	ddi_dma_cookie_t dmac;
+	unsigned int ncookies;
+	size_t size;
+	unsigned int n;
+	int rc;
+
+	ASSERT(mp != NULL);
+	ASSERT3U(DB_TYPE(mp), ==, M_DATA);
+
+	ASSERT(stmp->stm_mp == NULL);
+	stmp->stm_mp = mp;
+
+	stmp->stm_base = (caddr_t)(mp->b_rptr);
+	stmp->stm_size = MBLKL(mp);
+
+	/* Bind the STREAMS block to the mapping */
+	rc = ddi_dma_addr_bind_handle(stmp->stm_dma_handle, NULL,
+	    stmp->stm_base, stmp->stm_size, DDI_DMA_WRITE | DDI_DMA_STREAMING,
+	    DDI_DMA_DONTWAIT, NULL, &dmac, &ncookies);
+	if (rc != DDI_DMA_MAPPED)
+		goto fail1;
+
+	ASSERT3U(ncookies, <=, SFXGE_TX_MAPPING_NADDR);
+
+	/*
+	 * Construct an array of addresses and an initial
+	 * offset.
+	 */
+	n = 0;
+	stmp->stm_addr[n++] = dmac.dmac_laddress & SFXGE_TX_DESCMASK;
+	DTRACE_PROBE1(addr, uint64_t, dmac.dmac_laddress & SFXGE_TX_DESCMASK);
+
+	stmp->stm_off = dmac.dmac_laddress & SFXGE_TX_DESCOFFSET;
+
+	size = MIN(SFXGE_TX_DESCSIZE - stmp->stm_off, dmac.dmac_size);
+	dmac.dmac_laddress += size;
+	dmac.dmac_size -= size;
+
+	for (;;) {
+		ASSERT3U(n, <, SFXGE_TX_MAPPING_NADDR);
+
+		if (dmac.dmac_size == 0) {
+			if (--ncookies == 0)
+				break;
+
+			ddi_dma_nextcookie(stmp->stm_dma_handle, &dmac);
+		}
+
+		ASSERT((dmac.dmac_laddress & SFXGE_TX_DESCMASK) != 0);
+		ASSERT((dmac.dmac_laddress & SFXGE_TX_DESCOFFSET) == 0);
+		stmp->stm_addr[n++] = dmac.dmac_laddress;
+		DTRACE_PROBE1(addr, uint64_t, dmac.dmac_laddress);
+
+		size = MIN(SFXGE_TX_DESCSIZE, dmac.dmac_size);
+		dmac.dmac_laddress += size;
+		dmac.dmac_size -= size;
+	}
+	ASSERT3U(n, <=, SFXGE_TX_MAPPING_NADDR);
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	stmp->stm_size = 0;
+	stmp->stm_base = NULL;
+
+	stmp->stm_mp = NULL;
+
+	return (-1);
+}
+
+static void
+sfxge_tx_qreap(sfxge_txq_t *stp)
+{
+	unsigned int reaped;
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	reaped = stp->st_reaped;
+	while (reaped != stp->st_completed) {
+		unsigned int id;
+		sfxge_tx_mapping_t *stmp;
+		sfxge_tx_buffer_t *stbp;
+
+		id = reaped++ & (SFXGE_TX_NDESCS - 1);
+
+		ASSERT3P(stp->st_mp[id], ==, NULL);
+
+		if ((stmp = stp->st_stmp[id]) != NULL) {
+			stp->st_stmp[id] = NULL;
+
+			/* Free all the mappings */
+			do {
+				sfxge_tx_mapping_t *next;
+
+				next = stmp->stm_next;
+				stmp->stm_next = NULL;
+
+				sfxge_tx_qfmp_put(stp, stmp);
+
+				stmp = next;
+			} while (stmp != NULL);
+		}
+
+		if ((stbp = stp->st_stbp[id]) != NULL) {
+			stp->st_stbp[id] = NULL;
+
+			/* Free all the buffers */
+			do {
+				sfxge_tx_buffer_t *next;
+
+				next = stbp->stb_next;
+				stbp->stb_next = NULL;
+
+				stbp->stb_esm.esm_size = 0;
+				stbp->stb_off = 0;
+
+				sfxge_tx_qfbp_put(stp, stbp);
+
+				stbp = next;
+			} while (stbp != NULL);
+		}
+	}
+	stp->st_reaped = reaped;
+}
+
+static void
+sfxge_tx_qlist_abort(sfxge_txq_t *stp)
+{
+	unsigned int id;
+	sfxge_tx_mapping_t *stmp;
+	sfxge_tx_buffer_t *stbp;
+	mblk_t *mp;
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	id = stp->st_added & (SFXGE_TX_NDESCS - 1);
+
+	/* Clear the completion information */
+	stmp = stp->st_stmp[id];
+	stp->st_stmp[id] = NULL;
+
+	/* Free any mappings that were used */
+	while (stmp != NULL) {
+		sfxge_tx_mapping_t *next;
+
+		next = stmp->stm_next;
+		stmp->stm_next = NULL;
+
+		if (stmp->stm_mp != NULL)
+			sfxge_tx_msgb_unbind(stmp);
+
+		sfxge_tx_qfmp_put(stp, stmp);
+
+		stmp = next;
+	}
+
+	stbp = stp->st_stbp[id];
+	stp->st_stbp[id] = NULL;
+
+	/* Free any buffers that were used */
+	while (stbp != NULL) {
+		sfxge_tx_buffer_t *next;
+
+		next = stbp->stb_next;
+		stbp->stb_next = NULL;
+
+		stbp->stb_off = 0;
+		stbp->stb_esm.esm_size = 0;
+
+		sfxge_tx_qfbp_put(stp, stbp);
+
+		stbp = next;
+	}
+
+	mp = stp->st_mp[id];
+	stp->st_mp[id] = NULL;
+
+	if (mp != NULL)
+		freemsg(mp);
+
+	/* Clear the fragment list */
+	stp->st_n = 0;
+}
+
+/* Push descriptors to the TX ring setting blocked if no space */
+static void
+sfxge_tx_qlist_post(sfxge_txq_t *stp)
+{
+	unsigned int id;
+	unsigned int level;
+	unsigned int available;
+	int rc;
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	ASSERT(stp->st_n != 0);
+
+again:
+	level = stp->st_added - stp->st_reaped;
+	available = EFX_TXQ_LIMIT(SFXGE_TX_NDESCS) - level;
+
+	id = stp->st_added & (SFXGE_TX_NDESCS - 1);
+
+	if (available < stp->st_n) {
+		rc = ENOSPC;
+		goto fail1;
+	}
+
+	ASSERT3U(available, >=, stp->st_n);
+
+	/* Post the fragment list */
+	if ((rc = efx_tx_qpost(stp->st_etp, stp->st_eb, stp->st_n,
+	    stp->st_reaped, &(stp->st_added))) != 0)
+		goto fail2;
+
+	/*
+	 * If the list took more than a single descriptor then we need to
+	 * to move the completion information so it is referenced by the last
+	 * descriptor.
+	 */
+	if (((stp->st_added - 1) & (SFXGE_TX_NDESCS - 1)) != id) {
+		sfxge_tx_mapping_t *stmp;
+		sfxge_tx_buffer_t *stbp;
+		mblk_t *mp;
+
+		stmp = stp->st_stmp[id];
+		stp->st_stmp[id] = NULL;
+
+		stbp = stp->st_stbp[id];
+		stp->st_stbp[id] = NULL;
+
+		mp = stp->st_mp[id];
+		stp->st_mp[id] = NULL;
+
+		id = (stp->st_added - 1) & (SFXGE_TX_NDESCS - 1);
+
+		ASSERT(stp->st_stmp[id] == NULL);
+		stp->st_stmp[id] = stmp;
+
+		ASSERT(stp->st_stbp[id] == NULL);
+		stp->st_stbp[id] = stbp;
+
+		ASSERT(stp->st_mp[id] == NULL);
+		stp->st_mp[id] = mp;
+	}
+
+	/* Make the descriptors visible to the hardware */
+	(void) ddi_dma_sync(stp->st_mem.esm_dma_handle,
+	    0,
+	    EFX_TXQ_SIZE(SFXGE_TX_NDESCS),
+	    DDI_DMA_SYNC_FORDEV);
+
+	/* Clear the list */
+	stp->st_n = 0;
+
+	ASSERT3U(stp->st_unblock, ==, SFXGE_TXQ_NOT_BLOCKED);
+	return;
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	ASSERT(rc == ENOSPC);
+
+	level = stp->st_added - stp->st_completed;
+	available = EFX_TXQ_LIMIT(SFXGE_TX_NDESCS) - level;
+
+	/*
+	 * If there would be enough space after we've reaped any completed
+	 * mappings and buffers, and we gain sufficient queue space by doing
+	 * so, then reap now and try posting again.
+	 */
+	if (stp->st_n <= available &&
+	    stp->st_completed - stp->st_reaped >= SFXGE_TX_BATCH) {
+		sfxge_tx_qreap(stp);
+
+		goto again;
+	}
+
+	/* Set the unblock level */
+	if (stp->st_unblock == SFXGE_TXQ_NOT_BLOCKED) {
+		stp->st_unblock = SFXGE_TXQ_UNBLOCK_LEVEL1;
+	} else {
+		ASSERT(stp->st_unblock == SFXGE_TXQ_UNBLOCK_LEVEL1);
+
+		stp->st_unblock = SFXGE_TXQ_UNBLOCK_LEVEL2;
+	}
+
+	/*
+	 * Avoid a race with completion interrupt handling that could leave the
+	 * queue blocked.
+	 *
+	 * NOTE: The use of st_pending rather than st_completed is intentional
+	 *	 as st_pending is updated per-event rather than per-batch and
+	 *	 therefore avoids needless deferring.
+	 */
+	if (stp->st_pending == stp->st_added) {
+		sfxge_tx_qreap(stp);
+
+		stp->st_unblock = SFXGE_TXQ_NOT_BLOCKED;
+		goto again;
+	}
+
+	ASSERT(stp->st_unblock != SFXGE_TXQ_NOT_BLOCKED);
+}
+
+static int
+sfxge_tx_kstat_update(kstat_t *ksp, int rw)
+{
+	sfxge_txq_t *stp = ksp->ks_private;
+	sfxge_tx_dpl_t *stdp = &(stp->st_dpl);
+	kstat_named_t *knp;
+	int rc;
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	if (rw != KSTAT_READ) {
+		rc = EACCES;
+		goto fail1;
+	}
+
+	if (stp->st_state != SFXGE_TXQ_STARTED)
+		goto done;
+
+	efx_tx_qstats_update(stp->st_etp, stp->st_stat);
+	knp = (kstat_named_t *)ksp->ks_data + TX_NQSTATS;
+	knp->value.ui64 = stdp->get_pkt_limit;
+	knp++;
+	knp->value.ui64 = stdp->put_pkt_limit;
+	knp++;
+	knp->value.ui64 = stdp->get_full_count;
+	knp++;
+	knp->value.ui64 = stdp->put_full_count;
+
+done:
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_tx_kstat_init(sfxge_txq_t *stp)
+{
+	sfxge_t *sp = stp->st_sp;
+	unsigned int index = stp->st_index;
+	dev_info_t *dip = sp->s_dip;
+	kstat_t *ksp;
+	kstat_named_t *knp;
+	char name[MAXNAMELEN];
+	unsigned int id;
+	int rc;
+
+	/* Create the set */
+	(void) snprintf(name, MAXNAMELEN - 1, "%s_txq%04d",
+	    ddi_driver_name(dip), index);
+
+	if ((ksp = kstat_create((char *)ddi_driver_name(dip),
+	    ddi_get_instance(dip), name, "queue", KSTAT_TYPE_NAMED,
+	    TX_NQSTATS + 4, 0)) == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	stp->st_ksp = ksp;
+
+	ksp->ks_update = sfxge_tx_kstat_update;
+	ksp->ks_private = stp;
+	ksp->ks_lock = &(stp->st_lock);
+
+	/* Initialise the named stats */
+	stp->st_stat = knp = ksp->ks_data;
+	for (id = 0; id < TX_NQSTATS; id++) {
+		kstat_named_init(knp, (char *)efx_tx_qstat_name(sp->s_enp, id),
+		    KSTAT_DATA_UINT64);
+		knp++;
+	}
+	kstat_named_init(knp, "dpl_get_pkt_limit", KSTAT_DATA_UINT64);
+	knp++;
+	kstat_named_init(knp, "dpl_put_pkt_limit", KSTAT_DATA_UINT64);
+	knp++;
+	kstat_named_init(knp, "dpl_get_full_count", KSTAT_DATA_UINT64);
+	knp++;
+	kstat_named_init(knp, "dpl_put_full_count", KSTAT_DATA_UINT64);
+
+	kstat_install(ksp);
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static void
+sfxge_tx_kstat_fini(sfxge_txq_t *stp)
+{
+	/* Destroy the set */
+	kstat_delete(stp->st_ksp);
+	stp->st_ksp = NULL;
+	stp->st_stat = NULL;
+}
+
+static int
+sfxge_tx_qinit(sfxge_t *sp, unsigned int index, sfxge_txq_type_t type,
+    unsigned int evq)
+{
+	sfxge_txq_t *stp;
+	sfxge_tx_dpl_t *stdp;
+	int rc;
+
+	ASSERT3U(index, <, SFXGE_TXQ_NTYPES + SFXGE_RX_SCALE_MAX);
+	ASSERT3U(type, <, SFXGE_TXQ_NTYPES);
+	ASSERT3U(evq, <, SFXGE_RX_SCALE_MAX);
+
+	stp = kmem_cache_alloc(sp->s_tqc, KM_SLEEP);
+	stdp = &(stp->st_dpl);
+
+	ASSERT3U(stp->st_state, ==, SFXGE_TXQ_UNINITIALIZED);
+
+	stp->st_index = index;
+	stp->st_type = type;
+	stp->st_evq = evq;
+
+	mutex_init(&(stp->st_lock), NULL, MUTEX_DRIVER,
+	    DDI_INTR_PRI(sp->s_intr.si_intr_pri));
+
+	/* Initialize the statistics */
+	if ((rc = sfxge_tx_kstat_init(stp)) != 0)
+		goto fail1;
+
+	stdp->get_pkt_limit = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "tx_dpl_get_pkt_limit",
+	    SFXGE_TX_DPL_GET_PKT_LIMIT_DEFAULT);
+
+	stdp->put_pkt_limit = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
+	    DDI_PROP_DONTPASS, "tx_dpl_put_pkt_limit",
+	    SFXGE_TX_DPL_PUT_PKT_LIMIT_DEFAULT);
+
+	stp->st_state = SFXGE_TXQ_INITIALIZED;
+
+	/* Attach the TXQ to the driver */
+	ASSERT3P(sp->s_stp[index], ==, NULL);
+	sp->s_stp[index] = stp;
+	sp->s_tx_qcount++;
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	stp->st_evq = 0;
+	stp->st_type = 0;
+	stp->st_index = 0;
+
+	mutex_destroy(&(stp->st_lock));
+
+	kmem_cache_free(sp->s_tqc, stp);
+
+	return (rc);
+}
+
+static int
+sfxge_tx_qstart(sfxge_t *sp, unsigned int index)
+{
+	sfxge_txq_t *stp = sp->s_stp[index];
+	efx_nic_t *enp = sp->s_enp;
+	efsys_mem_t *esmp;
+	sfxge_evq_t *sep;
+	unsigned int evq;
+	unsigned int flags;
+	int rc;
+
+	mutex_enter(&(stp->st_lock));
+
+	esmp = &(stp->st_mem);
+	evq = stp->st_evq;
+	sep = sp->s_sep[evq];
+
+	ASSERT3U(stp->st_state, ==, SFXGE_TXQ_INITIALIZED);
+	ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
+
+	/* Zero the memory */
+	(void) memset(esmp->esm_base, 0, EFX_TXQ_SIZE(SFXGE_TX_NDESCS));
+
+	/* Program the buffer table */
+	if ((rc = sfxge_sram_buf_tbl_set(sp, stp->st_id, esmp,
+	    EFX_TXQ_NBUFS(SFXGE_TX_NDESCS))) != 0)
+		goto fail1;
+
+	switch (stp->st_type) {
+	case SFXGE_TXQ_NON_CKSUM:
+		flags = 0;
+		break;
+
+	case SFXGE_TXQ_IP_CKSUM:
+		flags = EFX_CKSUM_IPV4;
+		break;
+
+	case SFXGE_TXQ_IP_TCP_UDP_CKSUM:
+		flags = EFX_CKSUM_IPV4 | EFX_CKSUM_TCPUDP;
+		break;
+
+	default:
+		ASSERT(B_FALSE);
+
+		flags = 0;
+		break;
+	}
+
+	/* Create the transmit queue */
+	if ((rc = efx_tx_qcreate(enp, index, index, esmp, SFXGE_TX_NDESCS,
+	    stp->st_id, flags, sep->se_eep, &(stp->st_etp))) != 0)
+		goto fail2;
+
+	/* Enable the transmit queue */
+	efx_tx_qenable(stp->st_etp);
+
+	stp->st_state = SFXGE_TXQ_STARTED;
+
+	mutex_exit(&(stp->st_lock));
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	/* Clear entries from the buffer table */
+	sfxge_sram_buf_tbl_clear(sp, stp->st_id,
+	    EFX_TXQ_NBUFS(SFXGE_TX_NDESCS));
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	mutex_exit(&(stp->st_lock));
+
+	return (rc);
+}
+
+static inline int
+sfxge_tx_qmapping_add(sfxge_txq_t *stp, sfxge_tx_mapping_t *stmp,
+size_t *offp, size_t *limitp)
+{
+	mblk_t *mp;
+	size_t mapping_off;
+	size_t mapping_size;
+	int rc;
+
+	ASSERT3U(*offp, <, stmp->stm_size);
+	ASSERT(*limitp != 0);
+
+	mp = stmp->stm_mp;
+
+	ASSERT3P(stmp->stm_base, ==, mp->b_rptr);
+	ASSERT3U(stmp->stm_size, ==, MBLKL(mp));
+
+	mapping_off = stmp->stm_off + *offp;
+	mapping_size = stmp->stm_size - *offp;
+
+	while (mapping_size != 0 && *limitp != 0) {
+		size_t page =
+		    mapping_off >> SFXGE_TX_DESCSHIFT;
+		size_t page_off =
+		    mapping_off & SFXGE_TX_DESCOFFSET;
+		size_t page_size =
+		    SFXGE_TX_DESCSIZE - page_off;
+		efx_buffer_t *ebp;
+
+		ASSERT3U(page, <, SFXGE_TX_MAPPING_NADDR);
+		ASSERT((stmp->stm_addr[page] &
+			SFXGE_TX_DESCMASK) != 0);
+
+		page_size = MIN(page_size, mapping_size);
+		page_size = MIN(page_size, *limitp);
+
+		ASSERT3U(stp->st_n, <=,
+		    EFX_TXQ_LIMIT(SFXGE_TX_NDESCS));
+		if (stp->st_n ==
+		    EFX_TXQ_LIMIT(SFXGE_TX_NDESCS)) {
+			rc = ENOSPC;
+			goto fail1;
+		}
+
+		ebp = &(stp->st_eb[stp->st_n++]);
+		ebp->eb_addr = stmp->stm_addr[page] +
+		    page_off;
+		ebp->eb_size = page_size;
+
+		*offp += page_size;
+		*limitp -= page_size;
+
+		mapping_off += page_size;
+		mapping_size -= page_size;
+
+		ebp->eb_eop = (*limitp == 0 ||
+		    (mapping_size == 0 && mp->b_cont == NULL));
+
+		DTRACE_PROBE5(tx_mapping_add,
+		    unsigned int, stp->st_index,
+		    unsigned int, stp->st_n - 1,
+		    uint64_t, ebp->eb_addr,
+		    size_t, ebp->eb_size,
+		    boolean_t, ebp->eb_eop);
+	}
+
+	ASSERT3U(*offp, <=, stmp->stm_size);
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static inline int
+sfxge_tx_qbuffer_add(sfxge_txq_t *stp, sfxge_tx_buffer_t *stbp, boolean_t eop)
+{
+	efx_buffer_t *ebp;
+	int rc;
+
+	ASSERT3U(stp->st_n, <=,
+	    EFX_TXQ_LIMIT(SFXGE_TX_NDESCS));
+	if (stp->st_n == EFX_TXQ_LIMIT(SFXGE_TX_NDESCS)) {
+		rc = ENOSPC;
+		goto fail1;
+	}
+
+	ebp = &(stp->st_eb[stp->st_n++]);
+	ebp->eb_addr = stbp->stb_esm.esm_addr + stbp->stb_off;
+	ebp->eb_size = stbp->stb_esm.esm_size - stbp->stb_off;
+	ebp->eb_eop = eop;
+
+	(void) ddi_dma_sync(stbp->stb_esm.esm_dma_handle,
+	    stbp->stb_off, ebp->eb_size,
+	    DDI_DMA_SYNC_FORDEV);
+
+	stbp->stb_off = stbp->stb_esm.esm_size;
+
+	DTRACE_PROBE5(tx_buffer_add,
+	    unsigned int, stp->st_index,
+	    unsigned int, stp->st_n - 1,
+	    uint64_t, ebp->eb_addr, size_t, ebp->eb_size,
+	    boolean_t, ebp->eb_eop);
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static inline boolean_t
+sfxge_tx_msgb_copy(mblk_t *mp, sfxge_tx_buffer_t *stbp, size_t *offp,
+    size_t *limitp)
+{
+	size_t data_off;
+	size_t data_size;
+	size_t copy_off;
+	size_t copy_size;
+	boolean_t eop;
+
+	ASSERT3U(*offp, <=, MBLKL(mp));
+	ASSERT(*limitp != 0);
+
+	data_off = *offp;
+	data_size = MBLKL(mp) - *offp;
+
+	copy_off = stbp->stb_esm.esm_size;
+	copy_size = SFXGE_TX_BUFFER_SIZE - copy_off;
+
+	copy_size = MIN(copy_size, data_size);
+	copy_size = MIN(copy_size, *limitp);
+
+	bcopy(mp->b_rptr + data_off,
+	    stbp->stb_esm.esm_base + copy_off, copy_size);
+
+	stbp->stb_esm.esm_size += copy_size;
+	ASSERT3U(stbp->stb_esm.esm_size, <=,
+	    SFXGE_TX_BUFFER_SIZE);
+
+	*offp += copy_size;
+	*limitp -= copy_size;
+
+	data_off += copy_size;
+	data_size -= copy_size;
+
+	eop = (*limitp == 0 ||
+	    (data_size == 0 && mp->b_cont == NULL));
+
+	ASSERT3U(*offp, <=, MBLKL(mp));
+
+	return (eop);
+}
+
+static int
+sfxge_tx_qpayload_fragment(sfxge_txq_t *stp, unsigned int id, mblk_t **mpp,
+    size_t *offp, size_t size, boolean_t copy)
+{
+	sfxge_t *sp = stp->st_sp;
+	mblk_t *mp = *mpp;
+	size_t off = *offp;
+	sfxge_tx_buffer_t *stbp;
+	sfxge_tx_mapping_t *stmp;
+	int rc;
+
+	stbp = stp->st_stbp[id];
+	ASSERT(stbp == NULL || (stbp->stb_esm.esm_size == stbp->stb_off));
+
+	stmp = stp->st_stmp[id];
+
+	while (size != 0) {
+		boolean_t eop;
+
+		ASSERT(mp != NULL);
+
+		if (mp->b_cont != NULL)
+			prefetch_read_many(mp->b_cont);
+
+		ASSERT3U(off, <, MBLKL(mp));
+
+		if (copy)
+			goto copy;
+
+		/*
+		 * Check whether we have already mapped this data block for
+		 * DMA.
+		 */
+		if (stmp == NULL || stmp->stm_mp != mp) {
+			/*
+			 * If we are part way through copying a data block then
+			 * there's no point in trying to map it for DMA.
+			 */
+			if (off != 0)
+				goto copy;
+
+			/*
+			 * If the data block is too short then the cost of
+			 * mapping it for DMA would outweigh the cost of
+			 * copying it.
+			 */
+			if (MBLKL(mp) < SFXGE_TX_COPY_THRESHOLD)
+				goto copy;
+
+			/* Try to grab a transmit mapping from the pool */
+			stmp = sfxge_tx_qfmp_get(stp);
+			if (stmp == NULL) {
+				/*
+				 * The pool was empty so allocate a new
+				 * mapping.
+				 */
+				if ((stmp = kmem_cache_alloc(sp->s_tmc,
+				    KM_NOSLEEP)) == NULL)
+					goto copy;
+			}
+
+			/* Add the DMA mapping to the list */
+			stmp->stm_next = stp->st_stmp[id];
+			stp->st_stmp[id] = stmp;
+
+			/* Try to bind the data block to the mapping */
+			if (sfxge_tx_msgb_bind(mp, stmp) != 0)
+				goto copy;
+		}
+		ASSERT3P(stmp->stm_mp, ==, mp);
+
+		/*
+		 * If we have a partially filled buffer then we must add it to
+		 * the fragment list before adding the mapping.
+		 */
+		if (stbp != NULL && (stbp->stb_esm.esm_size > stbp->stb_off)) {
+			rc = sfxge_tx_qbuffer_add(stp, stbp, B_FALSE);
+			if (rc != 0)
+				goto fail1;
+		}
+
+		/* Add the mapping to the fragment list */
+		rc = sfxge_tx_qmapping_add(stp, stmp, &off, &size);
+		if (rc != 0)
+			goto fail2;
+
+		ASSERT(off == MBLKL(mp) || size == 0);
+
+		/*
+		 * If the data block has been exhausted then Skip over the
+		 * control block and advance to the next data block.
+		 */
+		if (off == MBLKL(mp)) {
+			mp = mp->b_cont;
+			off = 0;
+		}
+
+		continue;
+
+copy:
+		if (stbp == NULL ||
+		    stbp->stb_esm.esm_size == SFXGE_TX_BUFFER_SIZE) {
+			/* Try to grab a buffer from the pool */
+			stbp = sfxge_tx_qfbp_get(stp);
+			if (stbp == NULL) {
+				/*
+				 * The pool was empty so allocate a new
+				 * buffer.
+				 */
+				if ((stbp = kmem_cache_alloc(sp->s_tbc,
+				    KM_NOSLEEP)) == NULL) {
+					rc = ENOMEM;
+					goto fail3;
+				}
+			}
+
+			/* Add it to the list */
+			stbp->stb_next = stp->st_stbp[id];
+			stp->st_stbp[id] = stbp;
+		}
+
+		/* Copy as much of the data block as we can into the buffer */
+		eop = sfxge_tx_msgb_copy(mp, stbp, &off, &size);
+
+		ASSERT(off == MBLKL(mp) || size == 0 ||
+		    stbp->stb_esm.esm_size == SFXGE_TX_BUFFER_SIZE);
+
+		/*
+		 * If we have reached the end of the packet, or the buffer is
+		 * full, then add the buffer to the fragment list.
+		 */
+		if (stbp->stb_esm.esm_size == SFXGE_TX_BUFFER_SIZE || eop) {
+			rc = sfxge_tx_qbuffer_add(stp, stbp, eop);
+			if (rc != 0)
+				goto fail4;
+		}
+
+		/*
+		 * If the data block has been exhaused then advance to the next
+		 * one.
+		 */
+		if (off == MBLKL(mp)) {
+			mp = mp->b_cont;
+			off = 0;
+		}
+	}
+
+	*mpp = mp;
+	*offp = off;
+
+	return (0);
+
+fail4:
+	DTRACE_PROBE(fail4);
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_tx_qlso_fragment(sfxge_txq_t *stp, sfxge_tx_packet_t *stpp,
+    boolean_t copy)
+{
+	sfxge_t *sp = stp->st_sp;
+	mblk_t *mp = stpp->stp_mp;
+	struct ether_header *etherhp = stpp->stp_etherhp;
+	struct ip *iphp = stpp->stp_iphp;
+	struct tcphdr *thp = stpp->stp_thp;
+	size_t size = stpp->stp_size;
+	size_t off = stpp->stp_off;
+	size_t mss = stpp->stp_mss;
+	unsigned int id;
+	caddr_t hp;
+	size_t ehs, hs;
+	uint16_t start_len;
+	uint16_t start_id;
+	uint16_t ip_id;
+	uint8_t start_flags;
+	uint32_t start_seq;
+	uint32_t th_seq;
+	size_t lss;
+	sfxge_tx_buffer_t *stbp;
+	int rc;
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	if ((DB_LSOFLAGS(mp) & HW_LSO) == 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	id = stp->st_added & (SFXGE_TX_NDESCS - 1);
+
+	ASSERT(stp->st_n == 0);
+	ASSERT(stp->st_stbp[id] == NULL);
+	ASSERT(stp->st_stmp[id] == NULL);
+
+	ehs = (etherhp->ether_type == htons(ETHERTYPE_VLAN)) ?
+	    sizeof (struct ether_vlan_header) :
+	    sizeof (struct ether_header);
+	if (msgdsize(mp) != ehs + ntohs(iphp->ip_len)) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	/* The payload offset is equivalent to the size of the headers */
+	hp = (caddr_t)(mp->b_rptr);
+	hs = off;
+
+	/*
+	 * If the initial data block only contains the headers then advance
+	 * to the next one.
+	 */
+	if (hs > MBLKL(mp)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+	mp->b_rptr += hs;
+
+	if (MBLKL(mp) == 0)
+		mp = mp->b_cont;
+
+	off = 0;
+
+	/* Check IP and TCP headers are suitable for LSO */
+	if (((iphp->ip_off & ~htons(IP_DF)) != 0) ||
+	    ((thp->th_flags & (TH_URG | TH_SYN)) != 0) ||
+	    (thp->th_urp != 0)) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	if (size + (thp->th_off << 2) + (iphp->ip_hl << 2) !=
+	    ntohs(iphp->ip_len)) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	/*
+	 * Get the base IP id, The stack leaves enough of a gap in id space
+	 * for us to increment this for each segment we send out.
+	 */
+	start_len = ntohs(iphp->ip_len);
+	start_id = ip_id = ntohs(iphp->ip_id);
+
+	/* Get the base TCP sequence number and flags */
+	start_flags = thp->th_flags;
+	start_seq = th_seq = ntohl(thp->th_seq);
+
+	/* Adjust the header for interim segments */
+	iphp->ip_len = htons((iphp->ip_hl << 2) + (thp->th_off << 2) + mss);
+	thp->th_flags = start_flags & ~(TH_PUSH | TH_FIN);
+
+	lss = size;
+	if ((lss / mss) >= (EFX_TXQ_LIMIT(SFXGE_TX_NDESCS) / 2)) {
+		rc = EINVAL;
+		goto fail5;
+	}
+
+	stbp = NULL;
+	while (lss != 0) {
+		size_t ss = MIN(lss, mss);
+		boolean_t eol = (ss == lss);
+
+		/* Adjust the header for this segment */
+		iphp->ip_id = htons(ip_id);
+		ip_id++;
+
+		thp->th_seq = htonl(th_seq);
+		th_seq += ss;
+
+		/* If this is the final segment then do some extra adjustment */
+		if (eol) {
+			iphp->ip_len = htons((iphp->ip_hl << 2) +
+			    (thp->th_off << 2) + ss);
+			thp->th_flags = start_flags;
+		}
+
+		if (stbp == NULL ||
+		    stbp->stb_esm.esm_size + hs > SFXGE_TX_BUFFER_SIZE) {
+			/* Try to grab a buffer from the pool */
+			stbp = sfxge_tx_qfbp_get(stp);
+			if (stbp == NULL) {
+				/*
+				 * The pool was empty so allocate a new
+				 * buffer.
+				 */
+				if ((stbp = kmem_cache_alloc(sp->s_tbc,
+				    KM_NOSLEEP)) == NULL) {
+					rc = ENOMEM;
+					goto fail6;
+				}
+			}
+
+			/* Add it to the list */
+			stbp->stb_next = stp->st_stbp[id];
+			stp->st_stbp[id] = stbp;
+		}
+
+		/* Copy in the headers */
+		ASSERT3U(stbp->stb_off, ==, stbp->stb_esm.esm_size);
+		bcopy(hp, stbp->stb_esm.esm_base + stbp->stb_off, hs);
+		stbp->stb_esm.esm_size += hs;
+
+		/* Add the buffer to the fragment list */
+		rc = sfxge_tx_qbuffer_add(stp, stbp, B_FALSE);
+		if (rc != 0)
+			goto fail7;
+
+		/* Add the payload to the fragment list */
+		if ((rc = sfxge_tx_qpayload_fragment(stp, id, &mp, &off,
+		    ss, copy)) != 0)
+			goto fail8;
+
+		lss -= ss;
+	}
+	ASSERT3U(off, ==, 0);
+	ASSERT3P(mp, ==, NULL);
+
+	ASSERT3U(th_seq - start_seq, ==, size);
+
+	/*
+	 * If no part of the packet has been mapped for DMA then we can free
+	 * it now, otherwise it can only be freed on completion.
+	 */
+	if (stp->st_stmp[id] == NULL)
+		freemsg(stpp->stp_mp);
+	else
+		stp->st_mp[id] = stpp->stp_mp;
+
+	stpp->stp_mp = NULL;
+
+	return (0);
+
+fail8:
+	DTRACE_PROBE(fail8);
+fail7:
+	DTRACE_PROBE(fail7);
+fail6:
+	DTRACE_PROBE(fail6);
+fail5:
+	DTRACE_PROBE(fail5);
+
+	/* Restore the header */
+	thp->th_seq = htonl(start_seq);
+	thp->th_flags = start_flags;
+
+	iphp->ip_len = htons(start_len);
+	iphp->ip_id = htons(start_id);
+
+fail4:
+	DTRACE_PROBE(fail4);
+
+	mp = stpp->stp_mp;
+	mp->b_rptr -= hs;
+
+	ASSERT3U(((etherhp->ether_type == htons(ETHERTYPE_VLAN)) ?
+	    sizeof (struct ether_vlan_header) :
+	    sizeof (struct ether_header)) +
+	    ntohs(iphp->ip_len), ==, msgdsize(mp));
+
+	ASSERT(stp->st_mp[id] == NULL);
+
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static int
+sfxge_tx_qpacket_fragment(sfxge_txq_t *stp, sfxge_tx_packet_t *stpp,
+    boolean_t copy)
+{
+	sfxge_t *sp = stp->st_sp;
+	mblk_t *mp = stpp->stp_mp;
+	unsigned int id;
+	size_t off;
+	size_t size;
+	sfxge_tx_mapping_t *stmp;
+	sfxge_tx_buffer_t *stbp;
+	int rc;
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	ASSERT(stp->st_n == 0);
+
+	id = stp->st_added & (SFXGE_TX_NDESCS - 1);
+
+	ASSERT(stp->st_stbp[id] == NULL);
+	ASSERT(stp->st_stmp[id] == NULL);
+
+	off = 0;
+	size = LONG_MAX;	/* must be larger than the packet */
+
+	stbp = NULL;
+	stmp = NULL;
+
+	while (mp != NULL) {
+		boolean_t eop;
+
+		ASSERT(mp != NULL);
+
+		if (mp->b_cont != NULL)
+			prefetch_read_many(mp->b_cont);
+
+		ASSERT(stmp == NULL || stmp->stm_mp != mp);
+
+		if (copy)
+			goto copy;
+
+		/*
+		 * If we are part way through copying a data block then there's
+		 * no point in trying to map it for DMA.
+		 */
+		if (off != 0)
+			goto copy;
+
+		/*
+		 * If the data block is too short then the cost of mapping it
+		 * for DMA would outweigh the cost of copying it.
+		 *
+		 * TX copy break
+		 */
+		if (MBLKL(mp) < SFXGE_TX_COPY_THRESHOLD)
+			goto copy;
+
+		/* Try to grab a transmit mapping from the pool */
+		stmp = sfxge_tx_qfmp_get(stp);
+		if (stmp == NULL) {
+			/*
+			 * The pool was empty so allocate a new
+			 * mapping.
+			 */
+			if ((stmp = kmem_cache_alloc(sp->s_tmc,
+			    KM_NOSLEEP)) == NULL)
+				goto copy;
+		}
+
+		/* Add the DMA mapping to the list */
+		stmp->stm_next = stp->st_stmp[id];
+		stp->st_stmp[id] = stmp;
+
+		/* Try to bind the data block to the mapping */
+		if (sfxge_tx_msgb_bind(mp, stmp) != 0)
+			goto copy;
+
+		/*
+		 * If we have a partially filled buffer then we must add it to
+		 * the fragment list before adding the mapping.
+		 */
+		if (stbp != NULL && (stbp->stb_esm.esm_size > stbp->stb_off)) {
+			rc = sfxge_tx_qbuffer_add(stp, stbp, B_FALSE);
+			if (rc != 0)
+				goto fail1;
+		}
+
+		/* Add the mapping to the fragment list */
+		rc = sfxge_tx_qmapping_add(stp, stmp, &off, &size);
+		if (rc != 0)
+			goto fail2;
+
+		ASSERT3U(off, ==, MBLKL(mp));
+
+		/* Advance to the next data block */
+		mp = mp->b_cont;
+		off = 0;
+		continue;
+
+copy:
+		if (stbp == NULL ||
+		    stbp->stb_esm.esm_size == SFXGE_TX_BUFFER_SIZE) {
+			/* Try to grab a buffer from the pool */
+			stbp = sfxge_tx_qfbp_get(stp);
+			if (stbp == NULL) {
+				/*
+				 * The pool was empty so allocate a new
+				 * buffer.
+				 */
+				if ((stbp = kmem_cache_alloc(sp->s_tbc,
+				    KM_NOSLEEP)) == NULL) {
+					rc = ENOMEM;
+					goto fail3;
+				}
+			}
+
+			/* Add it to the list */
+			stbp->stb_next = stp->st_stbp[id];
+			stp->st_stbp[id] = stbp;
+		}
+
+		/* Copy as much of the data block as we can into the buffer */
+		eop = sfxge_tx_msgb_copy(mp, stbp, &off, &size);
+
+		ASSERT(off == MBLKL(mp) ||
+		    stbp->stb_esm.esm_size == SFXGE_TX_BUFFER_SIZE);
+
+		/*
+		 * If we have reached the end of the packet, or the buffer is
+		 * full, then add the buffer to the fragment list.
+		 */
+		if (stbp->stb_esm.esm_size == SFXGE_TX_BUFFER_SIZE || eop) {
+			rc = sfxge_tx_qbuffer_add(stp, stbp, eop);
+			if (rc != 0)
+				goto fail4;
+		}
+
+		/*
+		 * If the data block has been exhaused then advance to the next
+		 * one.
+		 */
+		if (off == MBLKL(mp)) {
+			mp = mp->b_cont;
+			off = 0;
+		}
+	}
+	ASSERT3U(off, ==, 0);
+	ASSERT3P(mp, ==, NULL);
+	ASSERT3U(size, !=, 0);
+
+	/*
+	 * If no part of the packet has been mapped for DMA then we can free
+	 * it now, otherwise it can only be freed on completion.
+	 */
+	if (stp->st_stmp[id] == NULL)
+		freemsg(stpp->stp_mp);
+	else
+		stp->st_mp[id] = stpp->stp_mp;
+
+	stpp->stp_mp = NULL;
+
+	return (0);
+
+fail4:
+	DTRACE_PROBE(fail4);
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	ASSERT(stp->st_stmp[id] == NULL);
+
+	return (rc);
+}
+
+
+#define	SFXGE_TX_QDPL_PUT_PENDING(_stp)					\
+	((_stp)->st_dpl.std_put != 0)
+
+static void
+sfxge_tx_qdpl_swizzle(sfxge_txq_t *stp)
+{
+	sfxge_tx_dpl_t *stdp = &(stp->st_dpl);
+	volatile uintptr_t *putp;
+	uintptr_t put;
+	sfxge_tx_packet_t *stpp;
+	sfxge_tx_packet_t *p;
+	sfxge_tx_packet_t **pp;
+	unsigned int count;
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	/*
+	 * Guaranteed that in flight TX packets will cause more TX completions
+	 * hence more swizzles must happen
+	 */
+	ASSERT3U(stdp->std_count, <=, sfxge_tx_dpl_get_pkt_max(stp));
+	if (stdp->std_count >= stdp->get_pkt_limit)
+		return;
+
+	/* Acquire the put list - replacing with an empty list */
+	putp = &(stdp->std_put);
+	put = atomic_swap_ulong(putp, 0);
+	stpp = (void *)put;
+
+	if (stpp == NULL)
+		return;
+
+	/* Reverse the list */
+	pp = &(stpp->stp_next);
+	p = NULL;
+
+	count = 0;
+	do {
+		sfxge_tx_packet_t *next;
+
+		next = stpp->stp_next;
+
+		stpp->stp_next = p;
+		p = stpp;
+
+		count++;
+		stpp = next;
+	} while (stpp != NULL);
+
+	/* Add it to the tail of the get list */
+	ASSERT3P(*pp, ==, NULL);
+
+	*(stdp->std_getp) = p;
+	stdp->std_getp = pp;
+	stdp->std_count += count;
+	ASSERT3U(stdp->std_count, <=, sfxge_tx_dpl_get_pkt_max(stp));
+
+	DTRACE_PROBE2(dpl_counts, int, stdp->std_count, int, count);
+}
+
+
+/*
+ * If TXQ locked, add the RX DPL put list and this packet to the TX DPL get list
+ * If TXQ unlocked, atomically add this packet to TX DPL put list
+ *
+ * The only possible error is ENOSPC (used for TX backpressure)
+ * For the TX DPL put or get list becoming full, in both cases there must be
+ * future TX completions (as represented by the packets on the DPL get lists).
+ *
+ * This ensures that in the future mac_tx_update() will be called from
+ * sfxge_tx_qcomplete()
+ */
+static inline int
+sfxge_tx_qdpl_add(sfxge_txq_t *stp, sfxge_tx_packet_t *stpp, int locked)
+{
+	sfxge_tx_dpl_t *stdp = &stp->st_dpl;
+
+	ASSERT3P(stpp->stp_next, ==, NULL);
+
+	if (locked) {
+		ASSERT(mutex_owned(&stp->st_lock));
+
+		if (stdp->std_count >= stdp->get_pkt_limit) {
+			stdp->get_full_count++;
+			return (ENOSPC);
+		}
+
+		/* Reverse the put list onto the get list */
+		sfxge_tx_qdpl_swizzle(stp);
+
+		/* Add to the tail of the get list */
+		*(stdp->std_getp) = stpp;
+		stdp->std_getp = &stpp->stp_next;
+		stdp->std_count++;
+		ASSERT3U(stdp->std_count, <=, sfxge_tx_dpl_get_pkt_max(stp));
+
+	} else {
+		volatile uintptr_t *putp;
+		uintptr_t old;
+		uintptr_t new;
+		sfxge_tx_packet_t *old_pkt;
+
+		putp = &(stdp->std_put);
+		new = (uintptr_t)stpp;
+
+		/* Add to the head of the put list, keeping a list length */
+		do {
+			old = *putp;
+			old_pkt =  (sfxge_tx_packet_t *)old;
+
+			stpp->stp_dpl_put_len = old ?
+			    old_pkt->stp_dpl_put_len + 1 : 1;
+
+			if (stpp->stp_dpl_put_len >= stdp->put_pkt_limit) {
+				stpp->stp_next = 0;
+				stpp->stp_dpl_put_len = 0;
+				stdp->put_full_count++;
+				return (ENOSPC);
+			}
+
+			stpp->stp_next = (void *)old;
+		} while (atomic_cas_ulong(putp, old, new) != old);
+	}
+	return (0);
+}
+
+
+/* Take all packets from DPL get list and try to send to HW */
+static void
+sfxge_tx_qdpl_drain(sfxge_txq_t *stp)
+{
+	sfxge_t *sp = stp->st_sp;
+	sfxge_tx_dpl_t *stdp = &(stp->st_dpl);
+	unsigned int pushed = stp->st_added;
+	sfxge_tx_packet_t *stpp;
+	unsigned int count;
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	prefetch_read_many(sp->s_enp);
+	prefetch_read_many(stp->st_etp);
+
+	stpp = stdp->std_get;
+	count = stdp->std_count;
+
+	while (count != 0) {
+		sfxge_tx_packet_t *next;
+		boolean_t copy;
+		int rc;
+
+		ASSERT(stpp != NULL);
+
+		/* Split stpp off */
+		next = stpp->stp_next;
+		stpp->stp_next = NULL;
+
+		if (next != NULL)
+			prefetch_read_many(next);
+
+		if (stp->st_state != SFXGE_TXQ_STARTED)
+			goto reject;
+
+		copy = B_FALSE;
+
+again:
+		/* Fragment the packet */
+		if (stpp->stp_mss != 0) {
+			rc = sfxge_tx_qlso_fragment(stp, stpp, copy);
+		} else {
+			rc = sfxge_tx_qpacket_fragment(stp, stpp, copy);
+		}
+
+		switch (rc) {
+		case 0:
+			break;
+
+		case ENOSPC:
+			if (!copy)
+				goto copy;
+
+		/*FALLTHRU*/
+		default:
+			goto reject;
+		}
+
+		/* Free the packet structure */
+		stpp->stp_etherhp = NULL;
+		stpp->stp_iphp = NULL;
+		stpp->stp_thp = NULL;
+		stpp->stp_off = 0;
+		stpp->stp_size = 0;
+		stpp->stp_mss = 0;
+		stpp->stp_dpl_put_len = 0;
+
+		ASSERT3P(stpp->stp_mp, ==, NULL);
+
+		if (sfxge_tx_qfpp_put(stp, stpp) != 0) {
+			sfxge_tx_packet_destroy(sp, stpp);
+			stpp = NULL;
+		}
+
+		--count;
+		stpp = next;
+
+		/* Post the packet */
+		sfxge_tx_qlist_post(stp);
+
+		if (stp->st_unblock != SFXGE_TXQ_NOT_BLOCKED)
+			goto defer;
+
+		if (stp->st_added - pushed >= SFXGE_TX_BATCH) {
+			efx_tx_qpush(stp->st_etp, stp->st_added);
+			pushed = stp->st_added;
+		}
+
+		continue;
+
+copy:
+		/* Abort the current fragment list */
+		sfxge_tx_qlist_abort(stp);
+
+		/* Try copying the packet to flatten it */
+		ASSERT(!copy);
+		copy = B_TRUE;
+
+		goto again;
+
+reject:
+		/* Abort the current fragment list */
+		sfxge_tx_qlist_abort(stp);
+
+		/* Discard the packet */
+		freemsg(stpp->stp_mp);
+		stpp->stp_mp = NULL;
+
+		/* Free the packet structure */
+		stpp->stp_etherhp = NULL;
+		stpp->stp_iphp = NULL;
+		stpp->stp_thp = NULL;
+		stpp->stp_off = 0;
+		stpp->stp_size = 0;
+		stpp->stp_mss = 0;
+		stpp->stp_dpl_put_len = 0;
+
+		if (sfxge_tx_qfpp_put(stp, stpp) != 0) {
+			sfxge_tx_packet_destroy(sp, stpp);
+			stpp = NULL;
+		}
+
+		--count;
+		stpp = next;
+		continue;
+defer:
+		DTRACE_PROBE1(defer, unsigned int, stp->st_index);
+		break;
+	}
+
+	if (count == 0) {
+		/* New empty get list */
+		ASSERT3P(stpp, ==, NULL);
+		stdp->std_get = NULL;
+		stdp->std_count = 0;
+
+		stdp->std_getp = &(stdp->std_get);
+	} else {
+		/* shorten the list by moving the head */
+		stdp->std_get = stpp;
+		stdp->std_count = count;
+		ASSERT3U(stdp->std_count, <=, sfxge_tx_dpl_get_pkt_max(stp));
+	}
+
+	if (stp->st_added != pushed)
+		efx_tx_qpush(stp->st_etp, stp->st_added);
+
+	ASSERT(stp->st_unblock != SFXGE_TXQ_NOT_BLOCKED ||
+	    stdp->std_count == 0);
+}
+
+/* Swizzle deferred packet list, try and push to HW */
+static inline void
+sfxge_tx_qdpl_service(sfxge_txq_t *stp)
+{
+	do {
+		ASSERT(mutex_owned(&(stp->st_lock)));
+
+		if (SFXGE_TX_QDPL_PUT_PENDING(stp))
+			sfxge_tx_qdpl_swizzle(stp);
+
+		if (stp->st_unblock == SFXGE_TXQ_NOT_BLOCKED)
+			sfxge_tx_qdpl_drain(stp);
+
+		mutex_exit(&(stp->st_lock));
+
+		if (!SFXGE_TX_QDPL_PUT_PENDING(stp))
+			break;
+	} while (mutex_tryenter(&(stp->st_lock)));
+}
+
+static void
+sfxge_tx_qdpl_flush_locked(sfxge_txq_t *stp)
+{
+	sfxge_t *sp = stp->st_sp;
+	sfxge_tx_dpl_t *stdp = &(stp->st_dpl);
+	sfxge_tx_packet_t *stpp;
+	unsigned int count;
+
+	ASSERT(mutex_owned(&(stp->st_lock)));
+
+	/* Swizzle put list to the get list */
+	sfxge_tx_qdpl_swizzle(stp);
+
+	stpp = stdp->std_get;
+	count = stdp->std_count;
+
+	while (count != 0) {
+		sfxge_tx_packet_t *next;
+
+		next = stpp->stp_next;
+		stpp->stp_next = NULL;
+
+		/* Discard the packet */
+		freemsg(stpp->stp_mp);
+		stpp->stp_mp = NULL;
+
+		/* Free the packet structure */
+		stpp->stp_etherhp = NULL;
+		stpp->stp_iphp = NULL;
+		stpp->stp_thp = NULL;
+		stpp->stp_off = 0;
+		stpp->stp_size = 0;
+		stpp->stp_mss = 0;
+		stpp->stp_dpl_put_len = 0;
+
+		sfxge_tx_packet_destroy(sp, stpp);
+
+		--count;
+		stpp = next;
+	}
+
+	ASSERT3P(stpp, ==, NULL);
+
+	/* Empty list */
+	stdp->std_get = NULL;
+	stdp->std_count = 0;
+	stdp->std_getp = &(stdp->std_get);
+}
+
+
+void
+sfxge_tx_qdpl_flush(sfxge_txq_t *stp)
+{
+	mutex_enter(&(stp->st_lock));
+	sfxge_tx_qdpl_flush_locked(stp);
+	mutex_exit(&(stp->st_lock));
+}
+
+
+static void
+sfxge_tx_qunblock(sfxge_txq_t *stp)
+{
+	sfxge_t *sp = stp->st_sp;
+	unsigned int evq = stp->st_evq;
+	sfxge_evq_t *sep = sp->s_sep[evq];
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	if (stp->st_state != SFXGE_TXQ_STARTED)
+		return;
+
+	mutex_enter(&(stp->st_lock));
+
+	if (stp->st_unblock != SFXGE_TXQ_NOT_BLOCKED) {
+		unsigned int level;
+
+		level = stp->st_added - stp->st_completed;
+		if (level <= stp->st_unblock) {
+			stp->st_unblock = SFXGE_TXQ_NOT_BLOCKED;
+			sfxge_tx_qlist_post(stp);
+		}
+	}
+
+	sfxge_tx_qdpl_service(stp);
+	/* lock has been dropped */
+}
+
+void
+sfxge_tx_qcomplete(sfxge_txq_t *stp)
+{
+	sfxge_t *sp = stp->st_sp;
+	sfxge_tx_dpl_t *stdp = &(stp->st_dpl);
+	unsigned int evq = stp->st_evq;
+	sfxge_evq_t *sep = sp->s_sep[evq];
+	unsigned int completed;
+
+	ASSERT(mutex_owned(&(sep->se_lock)));
+
+	completed = stp->st_completed;
+	while (completed != stp->st_pending) {
+		unsigned int id;
+		sfxge_tx_mapping_t *stmp;
+
+		id = completed++ & (SFXGE_TX_NDESCS - 1);
+
+		if ((stmp = stp->st_stmp[id]) != NULL) {
+			mblk_t *mp;
+
+			/* Unbind all the mappings */
+			do {
+				ASSERT(stmp->stm_mp != NULL);
+				sfxge_tx_msgb_unbind(stmp);
+
+				stmp = stmp->stm_next;
+			} while (stmp != NULL);
+
+			/*
+			 * Now that the packet is no longer mapped for DMA it
+			 * can be freed.
+			 */
+			mp = stp->st_mp[id];
+			stp->st_mp[id] = NULL;
+
+			ASSERT(mp != NULL);
+			freemsg(mp);
+		}
+	}
+	stp->st_completed = completed;
+
+	/* Check whether we need to unblock the queue */
+	if (stp->st_unblock != SFXGE_TXQ_NOT_BLOCKED) {
+		unsigned int level;
+
+		level = stp->st_added - stp->st_completed;
+		if (level <= stp->st_unblock)
+			sfxge_tx_qunblock(stp);
+	}
+
+	/* Release TX backpressure from the TX DPL put/get list being full */
+	if (stdp->std_count < stdp->get_pkt_limit)
+		mac_tx_update(sp->s_mh);
+}
+
+void
+sfxge_tx_qflush_done(sfxge_txq_t *stp)
+{
+	sfxge_t *sp = stp->st_sp;
+
+	ASSERT(mutex_owned(&(sp->s_sep[stp->st_evq]->se_lock)));
+
+	mutex_enter(&(stp->st_lock));
+
+	if (stp->st_flush == SFXGE_FLUSH_PENDING)
+		stp->st_flush = SFXGE_FLUSH_DONE;
+
+	mutex_exit(&(stp->st_lock));
+
+	mutex_enter(&(sp->s_tx_flush_lock));
+	sp->s_tx_flush_pending--;
+	if (sp->s_tx_flush_pending <= 0) {
+		/* All queues flushed: wakeup sfxge_tx_stop() */
+		cv_signal(&(sp->s_tx_flush_kv));
+	}
+	mutex_exit(&(sp->s_tx_flush_lock));
+}
+
+static void
+sfxge_tx_qflush(sfxge_t *sp, unsigned int index, boolean_t do_flush)
+{
+	sfxge_txq_t *stp = sp->s_stp[index];
+
+	ASSERT(mutex_owned(&(sp->s_state_lock)));
+
+	mutex_enter(&(stp->st_lock));
+
+	/* Prepare to flush and stop the queue */
+	if (stp->st_state == SFXGE_TXQ_STARTED)
+		stp->st_state = SFXGE_TXQ_INITIALIZED;
+	else
+		do_flush = B_FALSE; /* No hardware ring, so don't flush */
+
+	if (do_flush)
+		stp->st_flush = SFXGE_FLUSH_PENDING;
+	else
+		stp->st_flush = SFXGE_FLUSH_INACTIVE;
+
+	mutex_exit(&(stp->st_lock));
+
+	/* Flush the transmit queue */
+	if (do_flush)
+		efx_tx_qflush(stp->st_etp);
+}
+
+static void
+sfxge_tx_qstop(sfxge_t *sp, unsigned int index)
+{
+	sfxge_txq_t *stp = sp->s_stp[index];
+	unsigned int evq = stp->st_evq;
+	sfxge_evq_t *sep = sp->s_sep[evq];
+
+	mutex_enter(&(sep->se_lock));
+	mutex_enter(&(stp->st_lock));
+	ASSERT3U(stp->st_state, ==, SFXGE_TXQ_INITIALIZED);
+
+	/* All queues should have been flushed */
+	ASSERT3S(stp->st_sp->s_tx_flush_pending, ==, 0);
+	ASSERT(stp->st_flush != SFXGE_FLUSH_FAILED);
+
+	/* in case of TX flush timeout */
+	stp->st_flush = SFXGE_FLUSH_DONE;
+
+	/* Destroy the transmit queue */
+	efx_tx_qdestroy(stp->st_etp);
+	stp->st_etp = NULL;
+
+	/* Clear entries from the buffer table */
+	sfxge_sram_buf_tbl_clear(sp, stp->st_id,
+	    EFX_TXQ_NBUFS(SFXGE_TX_NDESCS));
+
+	sfxge_tx_qlist_abort(stp);
+	ASSERT3U(stp->st_n, ==, 0);
+
+	stp->st_unblock = SFXGE_TXQ_NOT_BLOCKED;
+
+	stp->st_pending = stp->st_added;
+
+	sfxge_tx_qcomplete(stp);
+	ASSERT3U(stp->st_completed, ==, stp->st_pending);
+
+	sfxge_tx_qreap(stp);
+	ASSERT3U(stp->st_reaped, ==, stp->st_completed);
+
+	/*
+	 * Ensure the deferred packet list is cleared
+	 * Can race with sfxge_tx_packet_add() adding to the put list
+	 */
+	sfxge_tx_qdpl_flush_locked(stp);
+
+	stp->st_added = 0;
+	stp->st_pending = 0;
+	stp->st_completed = 0;
+	stp->st_reaped = 0;
+
+	mutex_exit(&(stp->st_lock));
+	mutex_exit(&(sep->se_lock));
+}
+
+static void
+sfxge_tx_qfini(sfxge_t *sp, unsigned int index)
+{
+	sfxge_txq_t *stp = sp->s_stp[index];
+	sfxge_tx_dpl_t *stdp = &(stp->st_dpl);
+
+	/* Detach the TXQ from the driver */
+	sp->s_stp[index] = NULL;
+	ASSERT(sp->s_tx_qcount > 0);
+	sp->s_tx_qcount--;
+
+	ASSERT3U(stp->st_state, ==, SFXGE_TXQ_INITIALIZED);
+	stp->st_state = SFXGE_TXQ_UNINITIALIZED;
+
+	/* Tear down the statistics */
+	sfxge_tx_kstat_fini(stp);
+
+	/* Ensure the deferred packet list is empty */
+	ASSERT3U(stdp->std_count, ==, 0);
+	ASSERT3P(stdp->std_get, ==, NULL);
+	ASSERT3U(stdp->std_put, ==, 0);
+
+	/* Clear the free buffer pool */
+	sfxge_tx_qfbp_empty(stp);
+
+	/* Clear the free mapping pool */
+	sfxge_tx_qfmp_empty(stp);
+
+	/* Clear the free packet pool */
+	sfxge_tx_qfpp_empty(stp);
+
+	mutex_destroy(&(stp->st_lock));
+
+	stp->st_evq = 0;
+	stp->st_type = 0;
+	stp->st_index = 0;
+
+	kmem_cache_free(sp->s_tqc, stp);
+}
+
+int
+sfxge_tx_init(sfxge_t *sp)
+{
+	sfxge_intr_t *sip = &(sp->s_intr);
+	char name[MAXNAMELEN];
+	int index;
+	int rc;
+
+	(void) snprintf(name, MAXNAMELEN - 1, "%s%d_tx_packet_cache",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
+
+	sp->s_tpc = kmem_cache_create(name, sizeof (sfxge_tx_packet_t),
+	    SFXGE_CPU_CACHE_SIZE, sfxge_tx_packet_ctor, sfxge_tx_packet_dtor,
+	    NULL, sp, NULL, 0);
+	ASSERT(sp->s_tpc != NULL);
+
+	(void) snprintf(name, MAXNAMELEN - 1, "%s%d_tx_buffer_cache",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
+
+	sp->s_tbc = kmem_cache_create(name, sizeof (sfxge_tx_buffer_t),
+	    SFXGE_CPU_CACHE_SIZE, sfxge_tx_buffer_ctor, sfxge_tx_buffer_dtor,
+	    NULL, sp, NULL, 0);
+	ASSERT(sp->s_tbc != NULL);
+
+	(void) snprintf(name, MAXNAMELEN - 1, "%s%d_tx_mapping_cache",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
+
+	sp->s_tmc = kmem_cache_create(name, sizeof (sfxge_tx_mapping_t),
+	    SFXGE_CPU_CACHE_SIZE, sfxge_tx_mapping_ctor, sfxge_tx_mapping_dtor,
+	    NULL, sp, NULL, 0);
+	ASSERT(sp->s_tmc != NULL);
+
+	(void) snprintf(name, MAXNAMELEN - 1, "%s%d_txq_cache",
+	    ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
+
+	sp->s_tqc = kmem_cache_create(name, sizeof (sfxge_txq_t),
+	    SFXGE_CPU_CACHE_SIZE, sfxge_tx_qctor, sfxge_tx_qdtor, NULL, sp,
+	    NULL, 0);
+	ASSERT(sp->s_tqc != NULL);
+
+	/* Initialize the special non-checksummed transmit queues */
+
+	/* NB sfxge_ev_qinit() is sensitive to using EVQ_0 */
+	if ((rc = sfxge_tx_qinit(sp, SFXGE_TXQ_NON_CKSUM,
+		    SFXGE_TXQ_NON_CKSUM, EVQ_0)) != 0)
+		goto fail1;
+
+	/* NB sfxge_ev_qinit() is sensitive to using EVQ_0 */
+	if ((rc = sfxge_tx_qinit(sp, SFXGE_TXQ_IP_CKSUM,
+	    SFXGE_TXQ_IP_CKSUM, EVQ_0)) != 0)
+		goto fail2;
+
+	/* Initialize the normal transmit queues */
+	for (index = 0; index < sip->si_nalloc; index++) {
+		if ((rc = sfxge_tx_qinit(sp, SFXGE_TXQ_IP_TCP_UDP_CKSUM + index,
+		    SFXGE_TXQ_IP_TCP_UDP_CKSUM, index)) != 0)
+			goto fail3;
+	}
+
+	return (0);
+
+fail3:
+	DTRACE_PROBE(fail3);
+
+	while (--index >= 0)
+		sfxge_tx_qfini(sp, SFXGE_TXQ_IP_TCP_UDP_CKSUM + index);
+
+	sfxge_tx_qfini(sp, SFXGE_TXQ_IP_CKSUM);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	sfxge_tx_qfini(sp, SFXGE_TXQ_NON_CKSUM);
+
+	kmem_cache_destroy(sp->s_tqc);
+	sp->s_tqc = NULL;
+
+	kmem_cache_destroy(sp->s_tmc);
+	sp->s_tmc = NULL;
+
+	kmem_cache_destroy(sp->s_tbc);
+	sp->s_tbc = NULL;
+
+	kmem_cache_destroy(sp->s_tpc);
+	sp->s_tpc = NULL;
+
+	return (rc);
+}
+
+int
+sfxge_tx_start(sfxge_t *sp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	int index;
+	int rc;
+
+	/* Initialize the transmit module */
+	if ((rc = efx_tx_init(enp)) != 0)
+		goto fail1;
+
+	for (index = 0; index < sp->s_tx_qcount; index++) {
+		if ((rc = sfxge_tx_qstart(sp, index)) != 0)
+			goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+
+	while (--index >= 0)
+		sfxge_tx_qstop(sp, index);
+
+	/* Tear down the transmit module */
+	efx_tx_fini(enp);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+/*
+ * Add a packet to the TX Deferred Packet List and if the TX queue lock
+ * can be acquired then call sfxge_tx_qdpl_service() to fragment and push
+ * to the H/W transmit descriptor ring
+ *
+ * If ENOSPC is returned then the DPL is full or the packet create failed, but
+ * the mblk isn't freed so that the caller can return this mblk from mc_tx() to
+ * back-pressure the OS stack.
+ *
+ * For all other errors the mblk is freed
+ */
+int
+sfxge_tx_packet_add(sfxge_t *sp, mblk_t *mp)
+{
+	struct ether_header *etherhp;
+	struct ip *iphp;
+	struct tcphdr *thp;
+	size_t off;
+	size_t size;
+	size_t mss;
+	sfxge_txq_t *stp;
+	boolean_t locked;
+	sfxge_tx_packet_t *stpp;
+	int rc = 0;
+
+	ASSERT3P(mp->b_next, ==, NULL);
+	ASSERT(!(DB_CKSUMFLAGS(mp) & HCK_PARTIALCKSUM));
+
+	/*
+	 * Do not enqueue packets during startup/shutdown;
+	 *
+	 * NOTE: This access to the state is NOT protected by the state lock. It
+	 * is an imperfect test and anything further getting onto the get/put
+	 * deferred packet lists is cleaned up in (possibly repeated) calls to
+	 * sfxge_can_destroy().
+	 */
+	if (sp->s_state != SFXGE_STARTED) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	etherhp = NULL;
+	iphp = NULL;
+	thp = NULL;
+	off = 0;
+	size = 0;
+	mss = 0;
+
+	/* Check whether we need the header pointers for LSO segmentation */
+	if (DB_LSOFLAGS(mp) & HW_LSO) {
+		/* LSO segmentation relies on hardware checksum offload */
+		DB_CKSUMFLAGS(mp) |= HCK_FULLCKSUM;
+
+		if ((mss = DB_LSOMSS(mp)) == 0) {
+			rc = EINVAL;
+			goto fail1;
+		}
+
+		sfxge_tcp_parse(mp, &etherhp, &iphp, &thp, &off, &size);
+
+		if (etherhp == NULL ||
+		    iphp == NULL ||
+		    thp == NULL ||
+		    off == 0) {
+			rc = EINVAL;
+			goto fail2;
+		}
+	}
+
+	/* Choose the appropriate transit queue */
+	if (DB_CKSUMFLAGS(mp) & HCK_FULLCKSUM) {
+		sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
+
+		if (srsp->srs_state == SFXGE_RX_SCALE_STARTED) {
+			uint16_t hash;
+			int index;
+
+			if (srsp->srs_count > 1) {
+				/*
+				 * If we have not already parsed the headers
+				 * for LSO segmentation then we need to do it
+				 * now so we can calculate the hash.
+				 */
+				if (thp == NULL)
+					sfxge_tcp_parse(mp, &etherhp, &iphp,
+					    &thp, &off, &size);
+
+				if (thp != NULL) {
+					SFXGE_TCP_HASH(
+					    ntohl(iphp->ip_dst.s_addr),
+					    ntohs(thp->th_dport),
+					    ntohl(iphp->ip_src.s_addr),
+					    ntohs(thp->th_sport), hash);
+
+					index = srsp->srs_tbl[hash %
+					    SFXGE_RX_SCALE_MAX];
+				} else {
+					/*
+					 * Non-TCP traffix always goes to the
+					 * the queue in the zero-th entry of
+					 * the RSS table.
+					 */
+					index = srsp->srs_tbl[0];
+				}
+			} else {
+				/*
+				 * It does not matter what the hash is
+				 * because all the RSS table entries will be
+				 * the same.
+				 */
+				index = srsp->srs_tbl[0];
+			}
+
+			/*
+			 * Find the event queue corresponding to the hash in
+			 * the RSS table.
+			 */
+			stp = sp->s_stp[SFXGE_TXQ_IP_TCP_UDP_CKSUM + index];
+			ASSERT3U(stp->st_evq, ==, index);
+		} else {
+			stp = sp->s_stp[SFXGE_TXQ_IP_TCP_UDP_CKSUM];
+		}
+	} else if (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) {
+		stp = sp->s_stp[SFXGE_TXQ_IP_CKSUM];
+	} else {
+		if ((stp = sp->s_stp[SFXGE_TXQ_NON_CKSUM]) == NULL)
+			stp = sp->s_stp[SFXGE_TXQ_IP_CKSUM];
+	}
+	ASSERT(stp != NULL);
+
+	ASSERT(mss == 0 || (DB_LSOFLAGS(mp) & HW_LSO));
+
+	/* Try to grab the lock */
+	locked = mutex_tryenter(&(stp->st_lock));
+
+	if (locked) {
+		/* Try to grab a packet from the pool */
+		stpp = sfxge_tx_qfpp_get(stp);
+	} else {
+		stpp = NULL;
+	}
+
+	if (stpp == NULL) {
+		/*
+		 * Either the pool was empty or we don't have the lock so
+		 * allocate a new packet.
+		 */
+		if ((stpp = sfxge_tx_packet_create(sp)) == NULL) {
+			rc = ENOSPC;
+			goto fail3;
+		}
+	}
+
+	stpp->stp_mp = mp;
+	stpp->stp_etherhp = etherhp;
+	stpp->stp_iphp = iphp;
+	stpp->stp_thp = thp;
+	stpp->stp_off = off;
+	stpp->stp_size = size;
+	stpp->stp_mss = mss;
+	stpp->stp_dpl_put_len = 0;
+
+	rc = sfxge_tx_qdpl_add(stp, stpp, locked);
+	if (rc != 0) {
+		/* ENOSPC can happen for DPL get or put list is full */
+		ASSERT3U(rc, ==, ENOSPC);
+
+		/*
+		 * Note; if this is the unlocked DPL put list full case there is
+		 * no need to worry about a race with locked
+		 * sfxge_tx_qdpl_swizzle() as we know that the TX DPL put list
+		 * was full and would have been swizzle'd to the TX DPL get
+		 * list; hence guaranteeing future TX completions and calls
+		 * to mac_tx_update() via sfxge_tx_qcomplete()
+		 */
+		goto fail4;
+	}
+
+	/* Try to grab the lock again */
+	if (!locked)
+		locked = mutex_tryenter(&(stp->st_lock));
+
+	if (locked) {
+		/* Try to service the list */
+		sfxge_tx_qdpl_service(stp);
+		/* lock has been dropped */
+	}
+
+	return (0);
+
+fail4:
+	DTRACE_PROBE(fail4);
+	sfxge_tx_packet_destroy(sp, stpp);
+fail3:
+	DTRACE_PROBE(fail3);
+	if (locked)
+		mutex_exit(&(stp->st_lock));
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	if (rc != ENOSPC)
+		freemsg(mp);
+	return (rc);
+}
+
+int
+sfxge_tx_loopback(sfxge_t *sp, unsigned int count)
+{
+	uint8_t unicst[ETHERADDRL];
+	size_t mtu;
+	mblk_t *mp;
+	struct ether_header *etherhp;
+	unsigned int byte;
+	int rc;
+
+	if (count == 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	rc = sfxge_mac_unicst_get(sp, SFXGE_UNICST_LAA, unicst);
+
+	if (rc == ENOENT)
+		rc = sfxge_mac_unicst_get(sp, SFXGE_UNICST_BIA, unicst);
+
+	if (rc != 0)
+		goto fail2;
+
+	mtu = sp->s_mtu;
+
+	if ((mp = allocb(sizeof (struct ether_header) + mtu,
+	    BPRI_HI)) == NULL) {
+		rc = ENOMEM;
+		goto fail3;
+	}
+
+	mp->b_wptr = mp->b_rptr + sizeof (struct ether_header);
+	bzero(mp->b_rptr, MBLKL(mp));
+
+	/*LINTED*/
+	etherhp = (struct ether_header *)(mp->b_rptr);
+	bcopy(sfxge_brdcst, &(etherhp->ether_dhost), ETHERADDRL);
+	bcopy(unicst, &(etherhp->ether_shost), ETHERADDRL);
+	etherhp->ether_type = htons(SFXGE_ETHERTYPE_LOOPBACK);
+
+	for (byte = 0; byte < 30; byte++)
+		*(mp->b_wptr++) = (byte & 1) ? 0xaa : 0x55;
+
+	do {
+		mblk_t *nmp;
+
+		if ((nmp = dupb(mp)) == NULL) {
+			rc = ENOMEM;
+			goto fail4;
+		}
+
+		rc = sfxge_tx_packet_add(sp, nmp);
+		if (rc != 0) {
+			freeb(nmp);
+			goto fail5;
+		}
+
+	} while (--count != 0);
+
+	freeb(mp);
+	return (0);
+
+fail5:
+	DTRACE_PROBE(fail5);
+fail4:
+	DTRACE_PROBE(fail4);
+
+	freeb(mp);
+
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+int
+sfxge_tx_ioctl(sfxge_t *sp, sfxge_tx_ioc_t *stip)
+{
+	int rc;
+
+	switch (stip->sti_op) {
+	case SFXGE_TX_OP_LOOPBACK: {
+		unsigned int count = stip->sti_data;
+
+		if ((rc = sfxge_tx_loopback(sp, count)) != 0)
+			goto fail1;
+
+		break;
+	}
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+void
+sfxge_tx_stop(sfxge_t *sp)
+{
+	efx_nic_t *enp = sp->s_enp;
+	clock_t timeout;
+	boolean_t do_flush;
+	int index;
+
+	ASSERT(mutex_owned(&(sp->s_state_lock)));
+
+	mutex_enter(&(sp->s_tx_flush_lock));
+
+	/* Flush all the queues */
+	if (sp->s_hw_err == SFXGE_HW_OK) {
+		sp->s_tx_flush_pending = sp->s_tx_qcount;
+		do_flush = B_TRUE;
+	} else {
+		sp->s_tx_flush_pending = 0;
+		do_flush = B_FALSE;
+	}
+
+	/* Prepare queues to stop and flush the hardware ring */
+	for (index = 0; index < sp->s_tx_qcount; index++)
+		sfxge_tx_qflush(sp, index, do_flush);
+
+	if (do_flush == B_FALSE)
+		goto flush_done;
+
+	/* Wait upto 2sec for queue flushing to complete */
+	timeout = ddi_get_lbolt() + drv_usectohz(SFXGE_TX_QFLUSH_USEC);
+
+	while (sp->s_tx_flush_pending > 0) {
+		if (cv_timedwait(&(sp->s_tx_flush_kv), &(sp->s_tx_flush_lock),
+			timeout) < 0) {
+			/* Timeout waiting for queues to flush */
+			dev_info_t *dip = sp->s_dip;
+
+			DTRACE_PROBE(timeout);
+			cmn_err(CE_NOTE,
+			    SFXGE_CMN_ERR "[%s%d] tx qflush timeout",
+			    ddi_driver_name(dip), ddi_get_instance(dip));
+			break;
+		}
+	}
+	sp->s_tx_flush_pending = 0;
+
+flush_done:
+	mutex_exit(&(sp->s_tx_flush_lock));
+
+	/* Stop all the queues */
+	for (index = 0; index < sp->s_tx_qcount; index++)
+		sfxge_tx_qstop(sp, index);
+
+	/* Tear down the transmit module */
+	efx_tx_fini(enp);
+}
+
+void
+sfxge_tx_fini(sfxge_t *sp)
+{
+	int index;
+
+	index = sp->s_tx_qcount;
+	while (--index >= 0)
+		sfxge_tx_qfini(sp, index);
+
+	kmem_cache_destroy(sp->s_tqc);
+	sp->s_tqc = NULL;
+
+	kmem_cache_destroy(sp->s_tmc);
+	sp->s_tmc = NULL;
+
+	kmem_cache_destroy(sp->s_tbc);
+	sp->s_tbc = NULL;
+
+	kmem_cache_destroy(sp->s_tpc);
+	sp->s_tpc = NULL;
+}
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/sfxge_vpd.c	2013-08-22 18:57:35.124610734 -0400
@@ -0,0 +1,178 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * 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.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include "sfxge.h"
+
+
+int
+sfxge_vpd_get_keyword(sfxge_t *sp, sfxge_vpd_ioc_t *svip)
+{
+	efx_nic_t *enp = sp->s_enp;
+	efx_vpd_value_t vpd;
+	size_t size;
+	void *buf;
+	int rc;
+
+	if ((rc = efx_vpd_size(enp, &size)) != 0)
+		goto fail1;
+
+	buf = kmem_zalloc(size, KM_SLEEP);
+	ASSERT(buf);
+
+	if ((rc = efx_vpd_read(enp, buf, size)) != 0)
+		goto fail2;
+
+	if ((rc = efx_vpd_verify(enp, buf, size)) != 0)
+		goto fail3;
+
+	vpd.evv_tag = svip->svi_tag;
+	vpd.evv_keyword = svip->svi_keyword;
+
+	if ((rc = efx_vpd_get(enp, buf, size, &vpd)) != 0)
+		goto fail4;
+
+	svip->svi_len = vpd.evv_length;
+	EFX_STATIC_ASSERT(sizeof (svip->svi_payload) == sizeof (vpd.evv_value));
+	memcpy(svip->svi_payload, &vpd.evv_value[0],
+	    sizeof (svip->svi_payload));
+
+	kmem_free(buf, size);
+
+	return (0);
+
+fail4:
+	DTRACE_PROBE(fail4);
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+	kmem_free(buf, size);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+int
+sfxge_vpd_set_keyword(sfxge_t *sp, sfxge_vpd_ioc_t *svip)
+{
+	efx_nic_t *enp = sp->s_enp;
+	efx_vpd_value_t vpd;
+	size_t size;
+	void *buf;
+	int rc;
+
+	/* restriction on writable tags is in efx_vpd_hunk_set() */
+
+	if ((rc = efx_vpd_size(enp, &size)) != 0)
+		goto fail1;
+
+	buf = kmem_zalloc(size, KM_SLEEP);
+	ASSERT(buf);
+
+	if ((rc = efx_vpd_read(enp, buf, size)) != 0)
+		goto fail2;
+
+	if ((rc = efx_vpd_verify(enp, buf, size)) != 0) {
+		if ((rc = efx_vpd_reinit(enp, buf, size)) != 0)
+			goto fail3;
+		if ((rc = efx_vpd_verify(enp, buf, size)) != 0)
+			goto fail4;
+	}
+
+	vpd.evv_tag = svip->svi_tag;
+	vpd.evv_keyword = svip->svi_keyword;
+	vpd.evv_length = svip->svi_len;
+
+	EFX_STATIC_ASSERT(sizeof (svip->svi_payload) == sizeof (vpd.evv_value));
+	memcpy(&vpd.evv_value[0], svip->svi_payload,
+	    sizeof (svip->svi_payload));
+
+	if ((rc = efx_vpd_set(enp, buf, size, &vpd)) != 0)
+		goto fail5;
+
+	if ((rc = efx_vpd_verify(enp, buf, size)) != 0)
+			goto fail6;
+
+	/* And write the VPD back to the hardware */
+	if ((rc = efx_vpd_write(enp, buf, size)) != 0)
+		goto fail7;
+
+	kmem_free(buf, size);
+
+	return (0);
+
+fail7:
+	DTRACE_PROBE(fail7);
+fail6:
+	DTRACE_PROBE(fail6);
+fail5:
+	DTRACE_PROBE(fail5);
+fail4:
+	DTRACE_PROBE(fail4);
+fail3:
+	DTRACE_PROBE(fail3);
+fail2:
+	DTRACE_PROBE(fail2);
+	kmem_free(buf, size);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+int
+sfxge_vpd_ioctl(sfxge_t *sp, sfxge_vpd_ioc_t *svip)
+{
+	int rc;
+
+	switch (svip->svi_op) {
+	case SFXGE_VPD_OP_GET_KEYWORD:
+		if ((rc = sfxge_vpd_get_keyword(sp, svip)) != 0)
+			goto fail1;
+		break;
+	case SFXGE_VPD_OP_SET_KEYWORD:
+		if ((rc = sfxge_vpd_set_keyword(sp, svip)) != 0)
+			goto fail1;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	DTRACE_PROBE(fail2);
+fail1:
+	DTRACE_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/siena_flash.h	2013-08-22 18:57:35.210108509 -0400
@@ -0,0 +1,134 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef	_SYS_SIENA_FLASH_H
+#define	_SYS_SIENA_FLASH_H
+
+#pragma pack(1)
+
+/* Fixed locations near the start of flash (which may be in the internal PHY
+ * firmware header) point to the boot header.
+ *
+ * - parsed by MC boot ROM and firmware
+ * - reserved (but not parsed) by PHY firmware
+ * - opaque to driver
+ */
+
+#define	SIENA_MC_BOOT_PHY_FW_HDR_LEN (0x20)
+
+#define	SIENA_MC_BOOT_PTR_LOCATION (0x18)      /* First thing we try to boot */
+#define	SIENA_MC_BOOT_ALT_PTR_LOCATION (0x1c)  /* Alternative if that fails */
+
+#define	SIENA_MC_BOOT_HDR_LEN (0x200)
+
+#define	SIENA_MC_BOOT_MAGIC (0x51E4A001)
+#define	SIENA_MC_BOOT_VERSION (1)
+
+typedef struct siena_mc_boot_hdr_s {		/* GENERATED BY scripts/genfwdef */
+	efx_dword_t	magic;			/* = SIENA_MC_BOOT_MAGIC */
+	efx_word_t	hdr_version;		/* this structure definition is version 1 */
+	efx_byte_t	board_type;
+	efx_byte_t	firmware_version_a;
+	efx_byte_t	firmware_version_b;
+	efx_byte_t	firmware_version_c;
+	efx_word_t	checksum;		/* of whole header area + firmware image */
+	efx_word_t	firmware_version_d;
+	efx_word_t	reserved_a[1];		/* (set to 0) */
+	efx_dword_t	firmware_text_offset;	/* offset to firmware .text */
+	efx_dword_t	firmware_text_size;	/* length of firmware .text, in bytes */
+	efx_dword_t	firmware_data_offset;	/* offset to firmware .data */
+	efx_dword_t	firmware_data_size;	/* length of firmware .data, in bytes */
+	efx_dword_t	reserved_b[8];		/* (set to 0) */
+} siena_mc_boot_hdr_t;
+
+#define	SIENA_MC_STATIC_CONFIG_MAGIC (0xBDCF5555)
+#define	SIENA_MC_STATIC_CONFIG_VERSION (0)
+
+typedef struct siena_mc_static_config_hdr_s {	/* GENERATED BY scripts/genfwdef */
+	efx_dword_t	magic;			/* = SIENA_MC_STATIC_CONFIG_MAGIC */
+	efx_word_t	length;			/* of header area (i.e. not including VPD) */
+	efx_byte_t	version;
+	efx_byte_t	csum;			/* over header area (i.e. not including VPD) */
+	efx_dword_t	static_vpd_offset;
+	efx_dword_t	static_vpd_length;
+	efx_dword_t	capabilities;
+	efx_byte_t	mac_addr_base[6];
+	efx_byte_t	green_mode_cal;		/* Green mode calibration result */
+	efx_byte_t	green_mode_valid;	/* Whether cal holds a valid value */
+	efx_word_t	mac_addr_count;
+	efx_word_t	mac_addr_stride;
+	efx_word_t	calibrated_vref;
+	efx_word_t	adc_vref;
+	efx_dword_t	reserved2[1];		/* (write as zero) */
+	efx_dword_t	num_dbi_items;
+	struct {
+		efx_word_t	addr;
+		efx_word_t	byte_enables;
+		efx_dword_t	value;
+	} dbi[];
+} siena_mc_static_config_hdr_t;
+
+#define	SIENA_MC_DYNAMIC_CONFIG_MAGIC (0xBDCFDDDD)
+#define	SIENA_MC_DYNAMIC_CONFIG_VERSION (0)
+
+typedef struct siena_mc_fw_version_s {		/* GENERATED BY scripts/genfwdef */
+	efx_dword_t	fw_subtype;
+	efx_word_t	version_w;
+	efx_word_t	version_x;
+	efx_word_t	version_y;
+	efx_word_t	version_z;
+} siena_mc_fw_version_t;
+
+typedef struct siena_mc_dynamic_config_hdr_s {	/* GENERATED BY scripts/genfwdef */
+	efx_dword_t	magic;			/* = SIENA_MC_DYNAMIC_CONFIG_MAGIC */
+	efx_word_t	length;			/* of header area (i.e. not including VPD) */
+	efx_byte_t	version;
+	efx_byte_t	csum;			/* over header area (i.e. not including VPD) */
+	efx_dword_t	dynamic_vpd_offset;
+	efx_dword_t	dynamic_vpd_length;
+	efx_dword_t	num_fw_version_items;
+	siena_mc_fw_version_t	fw_version[];
+} siena_mc_dynamic_config_hdr_t;
+
+#define	SIENA_MC_EXPROM_SINGLE_MAGIC (0xAA55)  /* little-endian uint16_t */
+
+#define	SIENA_MC_EXPROM_COMBO_MAGIC (0xB0070102)  /* little-endian uint32_t */
+
+typedef struct siena_mc_combo_rom_hdr_s {	/* GENERATED BY scripts/genfwdef */
+	efx_dword_t	magic;			/* = SIENA_MC_EXPROM_COMBO_MAGIC */
+	efx_dword_t	len1;			/* length of first image */
+	efx_dword_t	len2;			/* length of second image */
+	efx_dword_t	off1;			/* offset of first byte to edit to combine images */
+	efx_dword_t	off2;			/* offset of second byte to edit to combine images */
+	efx_word_t	infoblk0_off;		/* infoblk offset */
+	efx_word_t	infoblk1_off;		/* infoblk offset */
+	efx_byte_t	infoblk_len;		/* length of space reserved for infoblk structures */
+	efx_byte_t	reserved[7];		/* (set to 0) */
+} siena_mc_combo_rom_hdr_t;
+
+#pragma pack()
+
+#endif	/* _SYS_SIENA_FLASH_H */
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/siena_impl.h	2013-08-22 18:57:35.296069461 -0400
@@ -0,0 +1,477 @@
+/*-
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_SIENA_IMPL_H
+#define	_SYS_SIENA_IMPL_H
+
+#include "efx.h"
+#include "efx_regs.h"
+#include "efx_mcdi.h"
+#include "siena_flash.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_PROPS
+
+/* START MKCONFIG GENERATED SienaPhyHeaderPropsBlock a8db1f8eb5106efd */
+typedef enum siena_phy_prop_e {
+	SIENA_PHY_NPROPS
+} siena_phy_prop_t;
+
+/* END MKCONFIG GENERATED SienaPhyHeaderPropsBlock */
+
+#endif  /* EFSYS_OPT_PHY_PROPS */
+
+#define	SIENA_NVRAM_CHUNK 0x80
+
+extern	__checkReturn	int
+siena_nic_probe(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_PCIE_TUNE
+
+extern	__checkReturn	int
+siena_nic_pcie_extended_sync(
+	__in		efx_nic_t *enp);
+
+#endif
+
+extern	__checkReturn	int
+siena_nic_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+siena_nic_init(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_DIAG
+
+extern	__checkReturn	int
+siena_nic_register_test(
+	__in		efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+extern			void
+siena_nic_fini(
+	__in		efx_nic_t *enp);
+
+extern			void
+siena_nic_unprobe(
+	__in		efx_nic_t *enp);
+
+#define	SIENA_SRAM_ROWS	0x12000
+
+extern			void
+siena_sram_init(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_DIAG
+
+extern	__checkReturn	int
+siena_sram_test(
+	__in		efx_nic_t *enp,
+	__in		efx_sram_pattern_fn_t func);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+
+#if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
+
+extern	__checkReturn		int
+siena_nvram_partn_size(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__out			size_t *sizep);
+
+extern	__checkReturn		int
+siena_nvram_partn_lock(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn);
+
+extern	__checkReturn		int
+siena_nvram_partn_read(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+siena_nvram_partn_erase(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__in			unsigned int offset,
+	__in			size_t size);
+
+extern	__checkReturn		int
+siena_nvram_partn_write(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern				void
+siena_nvram_partn_unlock(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn);
+
+extern	__checkReturn		int
+siena_nvram_get_dynamic_cfg(
+	__in			efx_nic_t *enp,
+	__in			unsigned int index,
+	__in			boolean_t vpd,
+	__out			siena_mc_dynamic_config_hdr_t **dcfgp,
+	__out			size_t *sizep);
+
+#endif	/* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
+
+#if EFSYS_OPT_NVRAM
+
+#if EFSYS_OPT_DIAG
+
+extern	__checkReturn		int
+siena_nvram_test(
+	__in			efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_DIAG */
+
+extern	__checkReturn		int
+siena_nvram_size(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *sizep);
+
+extern	__checkReturn		int
+siena_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4]);
+
+extern	__checkReturn		int
+siena_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *pref_chunkp);
+
+extern	__checkReturn		int
+siena_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	 __checkReturn		int
+siena_nvram_erase(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type);
+
+extern	__checkReturn		int
+siena_nvram_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern				void
+siena_nvram_rw_finish(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type);
+
+extern	__checkReturn		int
+siena_nvram_set_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint16_t version[4]);
+
+#endif	/* EFSYS_OPT_NVRAM */
+
+#if EFSYS_OPT_VPD
+
+extern	__checkReturn		int
+siena_vpd_init(
+	__in			efx_nic_t *enp);
+
+extern	__checkReturn		int
+siena_vpd_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep);
+
+extern	__checkReturn		int
+siena_vpd_read(
+	__in			efx_nic_t *enp,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+siena_vpd_verify(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+siena_vpd_reinit(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern	__checkReturn		int
+siena_vpd_get(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__inout			efx_vpd_value_t *evvp);
+
+extern	__checkReturn		int
+siena_vpd_set(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_value_t *evvp);
+
+extern	__checkReturn		int
+siena_vpd_next(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out			efx_vpd_value_t *evvp,
+	__inout			unsigned int *contp);
+
+extern __checkReturn		int
+siena_vpd_write(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size);
+
+extern				void
+siena_vpd_fini(
+	__in			efx_nic_t *enp);
+
+#endif	/* EFSYS_OPT_VPD */
+
+typedef struct siena_link_state_s {
+	uint32_t		sls_adv_cap_mask;
+	uint32_t		sls_lp_cap_mask;
+	unsigned int 		sls_fcntl;
+	efx_link_mode_t		sls_link_mode;
+#if EFSYS_OPT_LOOPBACK
+	efx_loopback_type_t	sls_loopback;
+#endif
+	boolean_t		sls_mac_up;
+} siena_link_state_t;
+
+extern			void
+siena_phy_link_ev(
+	__in		efx_nic_t *enp,
+	__in		efx_qword_t *eqp,
+	__out		efx_link_mode_t *link_modep);
+
+extern	__checkReturn	int
+siena_phy_get_link(
+	__in		efx_nic_t *enp,
+	__out		siena_link_state_t *slsp);
+
+extern	__checkReturn	int
+siena_phy_power(
+	__in		efx_nic_t *enp,
+	__in		boolean_t on);
+
+extern	__checkReturn	int
+siena_phy_reconfigure(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+siena_phy_verify(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+siena_phy_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip);
+
+#if EFSYS_OPT_PHY_STATS
+
+extern					void
+siena_phy_decode_stats(
+	__in				efx_nic_t *enp,
+	__in				uint32_t vmask,
+	__in_opt			efsys_mem_t *esmp,
+	__out_opt			uint64_t *smaskp,
+	__out_ecount_opt(EFX_PHY_NSTATS)	uint32_t *stat);
+
+extern	__checkReturn			int
+siena_phy_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat);
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+siena_phy_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id);
+
+#endif	/* EFSYS_OPT_NAMES */
+
+extern	__checkReturn	int
+siena_phy_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp);
+
+extern	__checkReturn	int
+siena_phy_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val);
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#if EFSYS_OPT_PHY_BIST
+
+extern	__checkReturn		int
+siena_phy_bist_start(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type);
+
+extern	__checkReturn		int
+siena_phy_bist_poll(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type,
+	__out			efx_phy_bist_result_t *resultp,
+	__out_opt __drv_when(count > 0, __notnull)
+	uint32_t 	*value_maskp,
+	__out_ecount_opt(count)	__drv_when(count > 0, __notnull)
+	unsigned long	*valuesp,
+	__in			size_t count);
+
+extern				void
+siena_phy_bist_stop(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type);
+
+#endif	/* EFSYS_OPT_PHY_BIST */
+
+extern	__checkReturn	int
+siena_mac_poll(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *link_modep);
+
+extern	__checkReturn	int
+siena_mac_up(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *mac_upp);
+
+extern	__checkReturn	int
+siena_mac_reconfigure(
+	__in	efx_nic_t *enp);
+
+#if EFSYS_OPT_LOOPBACK
+
+extern	__checkReturn	int
+siena_mac_loopback_set(
+	__in		efx_nic_t *enp,
+	__in		efx_link_mode_t link_mode,
+	__in		efx_loopback_type_t loopback_type);
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+#if EFSYS_OPT_MAC_STATS
+
+extern	__checkReturn			int
+siena_mac_stats_clear(
+	__in				efx_nic_t *enp);
+
+extern	__checkReturn			int
+siena_mac_stats_upload(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp);
+
+extern	__checkReturn			int
+siena_mac_stats_periodic(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__in				uint16_t period_ms,
+	__in				boolean_t events);
+
+extern	__checkReturn			int
+siena_mac_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MAC_NSTATS)	efsys_stat_t *stat,
+	__out_opt			uint32_t *generationp);
+
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+extern	__checkReturn	int
+siena_mon_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+siena_mon_reconfigure(
+	__in		efx_nic_t *enp);
+
+#if EFSYS_OPT_MON_STATS
+
+extern					void
+siena_mon_decode_stats(
+	__in				efx_nic_t *enp,
+	__in				uint32_t dmask,
+	__in_opt			efsys_mem_t *esmp,
+	__out_opt				uint32_t *vmaskp,
+	__out_ecount_opt(EFX_MON_NSTATS)	efx_mon_stat_value_t *value);
+
+extern	__checkReturn			int
+siena_mon_ev(
+	__in				efx_nic_t *enp,
+	__in				efx_qword_t *eqp,
+	__out				efx_mon_stat_t *idp,
+	__out				efx_mon_stat_value_t *valuep);
+
+extern	__checkReturn			int
+siena_mon_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values);
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_SIENA_IMPL_H */
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/siena_mac.c	2013-08-22 18:57:35.384943229 -0400
@@ -0,0 +1,546 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "efsys.h"
+#include "efx.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_SIENA
+
+	__checkReturn	int
+siena_mac_poll(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *link_modep)
+{
+	efx_port_t *epp = &(enp->en_port);
+	siena_link_state_t sls;
+	int rc;
+
+	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
+		goto fail1;
+
+	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
+	epp->ep_fcntl = sls.sls_fcntl;
+
+	*link_modep = sls.sls_link_mode;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	*link_modep = EFX_LINK_UNKNOWN;
+
+	return (rc);
+}
+
+	__checkReturn	int
+siena_mac_up(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *mac_upp)
+{
+	siena_link_state_t sls;
+	int rc;
+
+	/*
+	 * Because Siena doesn't *require* polling, we can't rely on
+	 * siena_mac_poll() being executed to populate epp->ep_mac_up.
+	 */
+	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
+		goto fail1;
+
+	*mac_upp = sls.sls_mac_up;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+siena_mac_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	uint8_t payload[MAX(MC_CMD_SET_MAC_IN_LEN,
+			    MC_CMD_SET_MCAST_HASH_IN_LEN)];
+	efx_mcdi_req_t req;
+	unsigned int fcntl;
+	int rc;
+
+	req.emr_cmd = MC_CMD_SET_MAC;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_SET_MAC_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_SET_MAC_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, SET_MAC_IN_MTU, epp->ep_mac_pdu);
+	MCDI_IN_SET_DWORD(req, SET_MAC_IN_DRAIN, epp->ep_mac_drain ? 1 : 0);
+	EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, SET_MAC_IN_ADDR),
+			    epp->ep_mac_addr);
+	MCDI_IN_POPULATE_DWORD_2(req, SET_MAC_IN_REJECT,
+				    SET_MAC_IN_REJECT_UNCST, !epp->ep_unicst,
+				    SET_MAC_IN_REJECT_BRDCST, !epp->ep_brdcst);
+
+	if (epp->ep_fcntl_autoneg)
+		/* efx_fcntl_set() has already set the phy capabilities */
+		fcntl = MC_CMD_FCNTL_AUTO;
+	else if (epp->ep_fcntl & EFX_FCNTL_RESPOND)
+		fcntl = (epp->ep_fcntl & EFX_FCNTL_GENERATE)
+			? MC_CMD_FCNTL_BIDIR
+			: MC_CMD_FCNTL_RESPOND;
+	else
+		fcntl = MC_CMD_FCNTL_OFF;
+
+	MCDI_IN_SET_DWORD(req, SET_MAC_IN_FCNTL, fcntl);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	/* Push multicast hash. Set the broadcast bit (0xff) appropriately */
+	req.emr_cmd = MC_CMD_SET_MCAST_HASH;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_SET_MCAST_HASH_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_SET_MCAST_HASH_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	memcpy(MCDI_IN2(req, uint8_t, SET_MCAST_HASH_IN_HASH0),
+	    epp->ep_multicst_hash, sizeof (epp->ep_multicst_hash));
+	if (epp->ep_brdcst)
+		EFX_SET_OWORD_BIT(*MCDI_IN2(req, efx_oword_t,
+		    SET_MCAST_HASH_IN_HASH1), 0x7f);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_LOOPBACK
+
+	__checkReturn	int
+siena_mac_loopback_set(
+	__in		efx_nic_t *enp,
+	__in		efx_link_mode_t link_mode,
+	__in		efx_loopback_type_t loopback_type)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_phy_ops_t *epop = epp->ep_epop;
+	efx_loopback_type_t old_loopback_type;
+	efx_link_mode_t old_loopback_link_mode;
+	int rc;
+
+	/* The PHY object handles this on Siena */
+	old_loopback_type = epp->ep_loopback_type;
+	old_loopback_link_mode = epp->ep_loopback_link_mode;
+	epp->ep_loopback_type = loopback_type;
+	epp->ep_loopback_link_mode = link_mode;
+
+	if ((rc = epop->epo_reconfigure(enp)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE(fail2);
+
+	epp->ep_loopback_type = old_loopback_type;
+	epp->ep_loopback_link_mode = old_loopback_link_mode;
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+#if EFSYS_OPT_MAC_STATS
+
+	__checkReturn			int
+siena_mac_stats_clear(
+	__in				efx_nic_t *enp)
+{
+	uint8_t payload[MC_CMD_MAC_STATS_IN_LEN];
+	efx_mcdi_req_t req;
+	int rc;
+
+	req.emr_cmd = MC_CMD_MAC_STATS;
+	req.emr_in_buf = payload;
+	req.emr_in_length = sizeof (payload);
+	EFX_STATIC_ASSERT(MC_CMD_MAC_STATS_OUT_DMA_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_POPULATE_DWORD_3(req, MAC_STATS_IN_CMD,
+				    MAC_STATS_IN_DMA, 0,
+				    MAC_STATS_IN_CLEAR, 1,
+				    MAC_STATS_IN_PERIODIC_CHANGE, 0);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+siena_mac_stats_upload(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp)
+{
+	uint8_t payload[MC_CMD_MAC_STATS_IN_LEN];
+	efx_mcdi_req_t req;
+	size_t bytes;
+	int rc;
+
+	EFX_STATIC_ASSERT(MC_CMD_MAC_NSTATS * sizeof (uint64_t) <=
+	    EFX_MAC_STATS_SIZE);
+
+	bytes = MC_CMD_MAC_NSTATS * sizeof (uint64_t);
+
+	req.emr_cmd = MC_CMD_MAC_STATS;
+	req.emr_in_buf = payload;
+	req.emr_in_length = sizeof (payload);
+	EFX_STATIC_ASSERT(MC_CMD_MAC_STATS_OUT_DMA_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_LO,
+			    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
+	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_HI,
+			    EFSYS_MEM_ADDR(esmp) >> 32);
+	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_LEN, bytes);
+
+	/*
+	 * The MC DMAs aggregate statistics for our convinience, so we can
+	 * avoid having to pull the statistics buffer into the cache to
+	 * maintain cumulative statistics.
+	 */
+	MCDI_IN_POPULATE_DWORD_3(req, MAC_STATS_IN_CMD,
+				    MAC_STATS_IN_DMA, 1,
+				    MAC_STATS_IN_CLEAR, 0,
+				    MAC_STATS_IN_PERIODIC_CHANGE, 0);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+siena_mac_stats_periodic(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__in				uint16_t period,
+	__in				boolean_t events)
+{
+	uint8_t payload[MC_CMD_MAC_STATS_IN_LEN];
+	efx_mcdi_req_t req;
+	size_t bytes;
+	int rc;
+
+	bytes = MC_CMD_MAC_NSTATS * sizeof (uint64_t);
+
+	req.emr_cmd = MC_CMD_MAC_STATS;
+	req.emr_in_buf = payload;
+	req.emr_in_length = sizeof (payload);
+	EFX_STATIC_ASSERT(MC_CMD_MAC_STATS_OUT_DMA_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_LO,
+			    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
+	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_HI,
+			    EFSYS_MEM_ADDR(esmp) >> 32);
+	MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_LEN, bytes);
+
+	/*
+	 * The MC DMAs aggregate statistics for our convinience, so we can
+	 * avoid having to pull the statistics buffer into the cache to
+	 * maintain cumulative statistics.
+	 */
+	MCDI_IN_POPULATE_DWORD_6(req, MAC_STATS_IN_CMD,
+			    MAC_STATS_IN_DMA, 0,
+			    MAC_STATS_IN_CLEAR, 0,
+			    MAC_STATS_IN_PERIODIC_CHANGE, 1,
+			    MAC_STATS_IN_PERIODIC_ENABLE, period ? 1 : 0,
+			    MAC_STATS_IN_PERIODIC_NOEVENT, events ? 0 : 1,
+			    MAC_STATS_IN_PERIOD_MS, period);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+
+#define	SIENA_MAC_STAT_READ(_esmp, _field, _eqp)			\
+	EFSYS_MEM_READQ((_esmp), (_field) * sizeof (efx_qword_t), _eqp)
+
+	__checkReturn			int
+siena_mac_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MAC_NSTATS)	efsys_stat_t *stat,
+	__out_opt			uint32_t *generationp)
+{
+	efx_qword_t rx_pkts;
+	efx_qword_t value;
+	efx_qword_t generation_start;
+	efx_qword_t generation_end;
+
+	_NOTE(ARGUNUSED(enp))
+
+	/* Read END first so we don't race with the MC */
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_END,
+			    &generation_end);
+	EFSYS_MEM_READ_BARRIER();
+
+	/* TX */
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_CONTROL_PKTS, &value);
+	EFSYS_STAT_SUBR_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PAUSE_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PAUSE_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_UNICAST_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_UNICST_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTICAST_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULTICST_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BROADCAST_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_BRDCST_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BYTES, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_OCTETS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LT64_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_64_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_65_TO_127_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_65_TO_127_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_128_TO_255_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_128_TO_255_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_256_TO_511_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_256_TO_511_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_512_TO_1023_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_512_TO_1023_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_1024_TO_15XX_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_1024_TO_15XX_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_GTJUMBO_PKTS, &value);
+	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BAD_FCS_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_ERRORS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_SGL_COL_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS,
+			    &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULT_COL_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS,
+			    &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_COL_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LATE_COLLISION_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LATE_COL_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_DEFERRED_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_DEF_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS,
+	    &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_DEF_PKTS]), &value);
+
+	/* RX */
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BYTES, &rx_pkts);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_OCTETS]), &rx_pkts);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNICAST_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_UNICST_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MULTICAST_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MULTICST_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BROADCAST_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_BRDCST_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PAUSE_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PAUSE_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNDERSIZE_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_64_PKTS, &value);
+	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_65_TO_127_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_65_TO_127_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_128_TO_255_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_128_TO_255_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_256_TO_511_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_256_TO_511_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_512_TO_1023_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_512_TO_1023_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_1024_TO_15XX_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_1024_TO_15XX_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_GTJUMBO_PKTS, &value);
+	EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BAD_FCS_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FCS_ERRORS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_OVERFLOW_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_DROP_EVENTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_FALSE_CARRIER_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FALSE_CARRIER_ERRORS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_SYMBOL_ERRORS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_ALIGN_ERROR_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_ALIGN_ERRORS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_INTERNAL_ERRORS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_JABBER_PKTS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_JABBER_PKTS]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_CHAR_ERR, &value);
+	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_CHAR_ERR]),
+			    &(value.eq_dword[0]));
+	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_CHAR_ERR]),
+			    &(value.eq_dword[1]));
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_CHAR_ERR, &value);
+	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_CHAR_ERR]),
+			    &(value.eq_dword[0]));
+	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_CHAR_ERR]),
+			    &(value.eq_dword[1]));
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_DISP_ERR, &value);
+	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_DISP_ERR]),
+			    &(value.eq_dword[0]));
+	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_DISP_ERR]),
+			    &(value.eq_dword[1]));
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_DISP_ERR, &value);
+	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_DISP_ERR]),
+			    &(value.eq_dword[0]));
+	EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_DISP_ERR]),
+			    &(value.eq_dword[1]));
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MATCH_FAULT, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MATCH_FAULT]), &value);
+
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_NODESC_DROPS, &value);
+	EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_NODESC_DROP_CNT]), &value);
+
+	EFSYS_MEM_READ_BARRIER();
+	SIENA_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_START,
+			    &generation_start);
+
+	/* Check that we didn't read the stats in the middle of a DMA */
+	/* Not a good enough check ? */
+	if (memcmp(&generation_start, &generation_end,
+	    sizeof (generation_start)))
+		return (EAGAIN);
+
+	if (generationp)
+		*generationp = EFX_QWORD_FIELD(generation_start, EFX_DWORD_0);
+
+	return (0);
+}
+
+#endif	/* EFSYS_OPT_MAC_STATS */
+
+#endif	/* EFSYS_OPT_SIENA */
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/siena_mon.c	2013-08-22 18:57:35.474985226 -0400
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "efsys.h"
+#include "efx.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_MON_SIENA
+
+	__checkReturn	int
+siena_mon_reset(
+	__in		efx_nic_t *enp)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	return (0);
+}
+
+	__checkReturn	int
+siena_mon_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	_NOTE(ARGUNUSED(enp))
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	return (0);
+}
+
+#if EFSYS_OPT_MON_STATS
+
+#define	SIENA_MON_WRONG_PORT (uint16_t)0xffff
+
+static __cs uint16_t __siena_mon_port0_map[] = {
+	EFX_MON_STAT_INT_TEMP,		/* MC_CMD_SENSOR_CONTROLLER_TEMP */
+	EFX_MON_STAT_EXT_TEMP,		/* MC_CMD_SENSOR_PHY_COMMON_TEMP */
+	EFX_MON_STAT_INT_COOLING,	/* MC_CMD_SENSOR_CONTROLLER_COOLING */
+	EFX_MON_STAT_EXT_TEMP,		/* MC_CMD_SENSOR_PHY0_TEMP */
+	EFX_MON_STAT_EXT_COOLING,	/* MC_CMD_SENSOR_PHY0_COOLING */
+	SIENA_MON_WRONG_PORT,		/* MC_CMD_SENSOR_PHY1_TEMP */
+	SIENA_MON_WRONG_PORT,		/* MC_CMD_SENSOR_PHY1_COOLING */
+	EFX_MON_STAT_1V,		/* MC_CMD_SENSOR_IN_1V0 */
+	EFX_MON_STAT_1_2V,		/* MC_CMD_SENSOR_IN_1V2 */
+	EFX_MON_STAT_1_8V,		/* MC_CMD_SENSOR_IN_1V8 */
+	EFX_MON_STAT_2_5V,		/* MC_CMD_SENSOR_IN_2V5 */
+	EFX_MON_STAT_3_3V,		/* MC_CMD_SENSOR_IN_3V3 */
+	EFX_MON_STAT_12V,		/* MC_CMD_SENSOR_IN_12V0 */
+	EFX_MON_STAT_1_2VA,		/* MC_CMD_SENSOR_IN_1V2A */
+	EFX_MON_STAT_VREF,		/* MC_CMD_SENSOR_IN_VREF */
+};
+
+static __cs uint16_t __siena_mon_port1_map[] = {
+	EFX_MON_STAT_INT_TEMP,		/* MC_CMD_SENSOR_CONTROLLER_TEMP */
+	EFX_MON_STAT_EXT_TEMP,		/* MC_CMD_SENSOR_PHY_COMMON_TEMP */
+	EFX_MON_STAT_INT_COOLING,	/* MC_CMD_SENSOR_CONTROLLER_COOLING */
+	SIENA_MON_WRONG_PORT,		/* MC_CMD_SENSOR_PHY0_TEMP */
+	SIENA_MON_WRONG_PORT,		/* MC_CMD_SENSOR_PHY0_COOLING */
+	EFX_MON_STAT_EXT_TEMP,		/* MC_CMD_SENSOR_PHY1_TEMP */
+	EFX_MON_STAT_EXT_COOLING,	/* MC_CMD_SENSOR_PHY1_COOLING */
+	EFX_MON_STAT_1V,		/* MC_CMD_SENSOR_IN_1V0 */
+	EFX_MON_STAT_1_2V,		/* MC_CMD_SENSOR_IN_1V2 */
+	EFX_MON_STAT_1_8V,		/* MC_CMD_SENSOR_IN_1V8 */
+	EFX_MON_STAT_2_5V,		/* MC_CMD_SENSOR_IN_2V5 */
+	EFX_MON_STAT_3_3V,		/* MC_CMD_SENSOR_IN_3V3 */
+	EFX_MON_STAT_12V,		/* MC_CMD_SENSOR_IN_12V0 */
+	EFX_MON_STAT_1_2VA,		/* MC_CMD_SENSOR_IN_1V2A */
+	EFX_MON_STAT_VREF,		/* MC_CMD_SENSOR_IN_VREF */
+};
+
+#define	SIENA_STATIC_SENSOR_ASSERT(_field)				\
+	EFX_STATIC_ASSERT(MC_CMD_SENSOR_STATE_ ## _field		\
+			    == EFX_MON_STAT_STATE_ ## _field)
+
+					void
+siena_mon_decode_stats(
+	__in				efx_nic_t *enp,
+	__in				uint32_t dmask,
+	__in_opt			efsys_mem_t *esmp,
+	__out_opt			uint32_t *vmaskp,
+	__out_ecount_opt(EFX_MON_NSTATS)	efx_mon_stat_value_t *value)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	uint16_t *sensor_map;
+	uint16_t mc_sensor;
+	size_t mc_sensor_max;
+	uint32_t vmask = 0;
+	uint32_t idx = 0;
+
+	/* Assert the MC_CMD_SENSOR and EFX_MON_STATE namespaces agree */
+	SIENA_STATIC_SENSOR_ASSERT(OK);
+	SIENA_STATIC_SENSOR_ASSERT(WARNING);
+	SIENA_STATIC_SENSOR_ASSERT(FATAL);
+	SIENA_STATIC_SENSOR_ASSERT(BROKEN);
+
+	EFX_STATIC_ASSERT(sizeof (__siena_mon_port1_map)
+			    == sizeof (__siena_mon_port0_map));
+	mc_sensor_max = EFX_ARRAY_SIZE(__siena_mon_port0_map);
+	sensor_map = (emip->emi_port == 1)
+		? __siena_mon_port0_map
+		: __siena_mon_port1_map;
+
+	/*
+	 * dmask may legitimately contain sensors not understood by the driver
+	 */
+	for (mc_sensor = 0; mc_sensor < mc_sensor_max; ++mc_sensor) {
+		uint16_t efx_sensor = sensor_map[mc_sensor];
+
+		if (~dmask & (1 << mc_sensor))
+			continue;
+		idx++;
+
+		if (efx_sensor == SIENA_MON_WRONG_PORT)
+			continue;
+		EFSYS_ASSERT(efx_sensor < EFX_MON_NSTATS);
+
+		vmask |= (1 << efx_sensor);
+		if (value != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
+			efx_mon_stat_value_t *emsvp = value + efx_sensor;
+			efx_dword_t dword;
+			EFSYS_MEM_READD(esmp, 4 * (idx - 1), &dword);
+			emsvp->emsv_value =
+			    (uint16_t)EFX_DWORD_FIELD(
+				dword,
+				MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
+			emsvp->emsv_state =
+			    (uint16_t)EFX_DWORD_FIELD(
+				dword,
+				MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
+		}
+	}
+
+	if (vmaskp != NULL)
+		*vmaskp = vmask;
+}
+
+	__checkReturn			int
+siena_mon_ev(
+	__in				efx_nic_t *enp,
+	__in				efx_qword_t *eqp,
+	__out				efx_mon_stat_t *idp,
+	__out				efx_mon_stat_value_t *valuep)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint16_t ev_monitor;
+	uint16_t ev_state;
+	uint16_t ev_value;
+	uint16_t *sensor_map;
+	efx_mon_stat_t id;
+	int rc;
+
+	sensor_map = (emip->emi_port == 1)
+		? __siena_mon_port0_map
+		: __siena_mon_port1_map;
+
+	ev_monitor = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_MONITOR);
+	ev_state = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_STATE);
+	ev_value = (uint16_t)MCDI_EV_FIELD(eqp, SENSOREVT_VALUE);
+
+	/* Hardware must support this statistic */
+	EFSYS_ASSERT((1 << ev_monitor) & encp->enc_siena_mon_stat_mask);
+
+	/* But we don't have to understand it */
+	if (ev_monitor >= EFX_ARRAY_SIZE(__siena_mon_port0_map)) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	id = sensor_map[ev_monitor];
+	if (id == SIENA_MON_WRONG_PORT)
+		return (ENODEV);
+	EFSYS_ASSERT(id < EFX_MON_NSTATS);
+
+	*idp = id;
+	valuep->emsv_value = ev_value;
+	valuep->emsv_state = ev_state;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+siena_mon_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_MON_NSTATS)	efx_mon_stat_value_t *values)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint32_t dmask = encp->enc_siena_mon_stat_mask;
+	uint32_t vmask;
+	uint8_t payload[MC_CMD_READ_SENSORS_IN_LEN];
+	efx_mcdi_req_t req;
+	int rc;
+
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	req.emr_cmd = MC_CMD_READ_SENSORS;
+	req.emr_in_buf = payload;
+	req.emr_in_length = sizeof (payload);
+	EFX_STATIC_ASSERT(MC_CMD_READ_SENSORS_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_LO,
+			    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
+	MCDI_IN_SET_DWORD(req, READ_SENSORS_IN_DMA_ADDR_HI,
+			    EFSYS_MEM_ADDR(esmp) >> 32);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	siena_mon_decode_stats(enp, dmask, esmp, &vmask, values);
+	EFSYS_ASSERT(vmask == encp->enc_mon_stat_mask);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+#endif	/* EFSYS_OPT_MON_SIENA */
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/siena_nic.c	2013-08-22 18:57:35.560540348 -0400
@@ -0,0 +1,984 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "efsys.h"
+#include "efx.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_SIENA
+
+static	__checkReturn		int
+siena_nic_get_partn_mask(
+	__in			efx_nic_t *enp,
+	__out			unsigned int *maskp)
+{
+	efx_mcdi_req_t req;
+	uint8_t outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN];
+	int rc;
+
+	req.emr_cmd = MC_CMD_NVRAM_TYPES;
+	EFX_STATIC_ASSERT(MC_CMD_NVRAM_TYPES_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = sizeof (outbuf);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	*maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+siena_nic_exit_assertion_handler(
+	__in		efx_nic_t *enp)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_REBOOT_IN_LEN];
+	int rc;
+
+	req.emr_cmd = MC_CMD_REBOOT;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_REBOOT_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_REBOOT_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS,
+			    MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0 && req.emr_rc != EIO) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+siena_nic_read_assertion(
+	__in		efx_nic_t *enp)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN,
+			    MC_CMD_GET_ASSERTS_OUT_LEN)];
+	const char *reason;
+	unsigned int flags;
+	unsigned int index;
+	unsigned int ofst;
+	int retry;
+	int rc;
+
+	/*
+	 * Before we attempt to chat to the MC, we should verify that the MC
+	 * isn't in it's assertion handler, either due to a previous reboot,
+	 * or because we're reinitializing due to an eec_exception().
+	 *
+	 * Use GET_ASSERTS to read any assertion state that may be present.
+	 * Retry this command twice. Once because a boot-time assertion failure
+	 * might cause the 1st MCDI request to fail. And once again because
+	 * we might race with siena_nic_exit_assertion_handler() running on the
+	 * other port.
+	 */
+	retry = 2;
+	do {
+		req.emr_cmd = MC_CMD_GET_ASSERTS;
+		req.emr_in_buf = payload;
+		req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN;
+		req.emr_out_buf = payload;
+		req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN;
+
+		MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1);
+		efx_mcdi_execute(enp, &req);
+
+	} while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	/* Print out any assertion state recorded */
+	flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS);
+	if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
+		return (0);
+
+	reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
+		? "system-level assertion"
+		: (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
+		? "thread-level assertion"
+		: (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
+		? "watchdog reset"
+		: "unknown assertion";
+	EFSYS_PROBE3(mcpu_assertion,
+	    const char *, reason, unsigned int,
+	    MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS),
+	    unsigned int,
+	    MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS));
+
+	/* Print out the registers */
+	ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST;
+	for (index = 1; index < 32; index++) {
+		EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int,
+			    EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst),
+					    EFX_DWORD_0));
+		ofst += sizeof (efx_dword_t);
+	}
+	EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+siena_nic_attach(
+	__in		efx_nic_t *enp,
+	__in		boolean_t attach)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_DRV_ATTACH_IN_LEN];
+	int rc;
+
+	req.emr_cmd = MC_CMD_DRV_ATTACH;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN;
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0);
+	MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_PCIE_TUNE
+
+	__checkReturn	int
+siena_nic_pcie_extended_sync(
+	__in		efx_nic_t *enp)
+{
+	uint8_t inbuf[MC_CMD_WORKAROUND_IN_LEN];
+	efx_mcdi_req_t req;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+
+	req.emr_cmd = MC_CMD_WORKAROUND;
+	req.emr_in_buf = inbuf;
+	req.emr_in_length = sizeof (inbuf);
+	EFX_STATIC_ASSERT(MC_CMD_WORKAROUND_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, MC_CMD_WORKAROUND_BUG17230);
+	MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, 1);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_PCIE_TUNE */
+
+static	__checkReturn	int
+siena_board_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LENMIN,
+		    MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)];
+	efx_mcdi_req_t req;
+	uint8_t *mac_addr;
+	efx_dword_t *capabilities;
+	int rc;
+
+	/* Board configuration */
+	req.emr_cmd = MC_CMD_GET_BOARD_CFG;
+	EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMIN;
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	if (emip->emi_port == 1) {
+		mac_addr = MCDI_OUT2(req, uint8_t,
+			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0);
+		capabilities = MCDI_OUT2(req, efx_dword_t,
+			    GET_BOARD_CFG_OUT_CAPABILITIES_PORT0);
+	} else {
+		mac_addr = MCDI_OUT2(req, uint8_t,
+			    GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1);
+		capabilities = MCDI_OUT2(req, efx_dword_t,
+			    GET_BOARD_CFG_OUT_CAPABILITIES_PORT1);
+	}
+	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
+
+	encp->enc_board_type = MCDI_OUT_DWORD(req,
+				    GET_BOARD_CFG_OUT_BOARD_TYPE);
+
+	/* Additional capabilities */
+	encp->enc_clk_mult = 1;
+	if (MCDI_CMD_DWORD_FIELD(capabilities, CAPABILITIES_TURBO)) {
+		enp->en_features |= EFX_FEATURE_TURBO;
+
+		if (MCDI_CMD_DWORD_FIELD(capabilities,
+		    CAPABILITIES_TURBO_ACTIVE))
+			encp->enc_clk_mult = 2;
+	}
+
+	encp->enc_evq_timer_quantum_ns =
+		EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
+	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
+		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
+
+	/* Resource limits */
+	req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS;
+	EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN;
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc == 0) {
+		if (req.emr_out_length_used <
+		    MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) {
+			rc = EMSGSIZE;
+			goto fail3;
+		}
+
+		encp->enc_evq_limit = MCDI_OUT_DWORD(req,
+		    GET_RESOURCE_LIMITS_OUT_EVQ);
+		encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET,
+		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ));
+		encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET,
+		    MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ));
+	} else if (req.emr_rc == ENOTSUP) {
+		encp->enc_evq_limit = 1024;
+		encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
+		encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
+	} else {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
+	    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
+	    (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+siena_phy_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_mcdi_req_t req;
+	uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
+	int rc;
+
+	req.emr_cmd = MC_CMD_GET_PHY_CFG;
+	EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = sizeof (outbuf);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE);
+#if EFSYS_OPT_NAMES
+	(void) strncpy(encp->enc_phy_name,
+		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME),
+		MIN(sizeof (encp->enc_phy_name) - 1,
+		    MC_CMD_GET_PHY_CFG_OUT_NAME_LEN));
+#endif	/* EFSYS_OPT_NAMES */
+	(void) memset(encp->enc_phy_revision, 0,
+	    sizeof (encp->enc_phy_revision));
+	memcpy(encp->enc_phy_revision,
+		MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION),
+		MIN(sizeof (encp->enc_phy_revision) - 1,
+		    MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN));
+#if EFSYS_OPT_PHY_LED_CONTROL
+	encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) |
+			    (1 << EFX_PHY_LED_OFF) |
+			    (1 << EFX_PHY_LED_ON));
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+#if EFSYS_OPT_PHY_PROPS
+	encp->enc_phy_nprops  = 0;
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+	/* Get the media type of the fixed port, if recognised. */
+	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI);
+	EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4);
+	EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4);
+	EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP);
+	EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS);
+	EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T);
+	epp->ep_fixed_port_type =
+		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE);
+	if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES)
+		epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID;
+
+	epp->ep_phy_cap_mask =
+		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP);
+#if EFSYS_OPT_PHY_FLAGS
+	encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS);
+#endif	/* EFSYS_OPT_PHY_FLAGS */
+
+	encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT);
+
+	/* Populate internal state */
+	encp->enc_siena_channel =
+		(uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL);
+
+#if EFSYS_OPT_PHY_STATS
+	encp->enc_siena_phy_stat_mask =
+		MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK);
+
+	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
+	siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask,
+			    NULL, &encp->enc_phy_stat_mask, NULL);
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_BIST
+	encp->enc_bist_mask = 0;
+	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
+	    GET_PHY_CFG_OUT_BIST_CABLE_SHORT))
+		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT);
+	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
+	    GET_PHY_CFG_OUT_BIST_CABLE_LONG))
+		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG);
+	if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
+	    GET_PHY_CFG_OUT_BIST))
+		encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL);
+#endif  /* EFSYS_OPT_PHY_BIST */
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_LOOPBACK
+
+static	__checkReturn	int
+siena_loopback_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_mcdi_req_t req;
+	uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN];
+	int rc;
+
+	req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
+	EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = sizeof (outbuf);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	/*
+	 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
+	 * in siena_phy.c:siena_phy_get_link()
+	 */
+	encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK &
+	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) &
+	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
+	encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK &
+	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) &
+	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
+	encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK &
+	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) &
+	    MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
+	encp->enc_loopback_types[EFX_LINK_UNKNOWN] =
+	    (1 << EFX_LOOPBACK_OFF) |
+	    encp->enc_loopback_types[EFX_LINK_100FDX] |
+	    encp->enc_loopback_types[EFX_LINK_1000FDX] |
+	    encp->enc_loopback_types[EFX_LINK_10000FDX];
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+#if EFSYS_OPT_MON_STATS
+
+static	__checkReturn	int
+siena_monitor_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_mcdi_req_t req;
+	uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX];
+	int rc;
+
+	req.emr_cmd = MC_CMD_SENSOR_INFO;
+	EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = sizeof (outbuf);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	encp->enc_siena_mon_stat_mask =
+		MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
+	encp->enc_mon_type = EFX_MON_SFC90X0;
+
+	siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask,
+			    NULL, &(encp->enc_mon_stat_mask), NULL);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_MON_STATS */
+
+	__checkReturn	int
+siena_nic_probe(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	siena_link_state_t sls;
+	unsigned int mask;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+
+	/* Read clear any assertion state */
+	if ((rc = siena_nic_read_assertion(enp)) != 0)
+		goto fail1;
+
+	/* Exit the assertion handler */
+	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
+		goto fail2;
+
+	/* Wrestle control from the BMC */
+	if ((rc = siena_nic_attach(enp, B_TRUE)) != 0)
+		goto fail3;
+
+	if ((rc = siena_board_cfg(enp)) != 0)
+		goto fail4;
+
+	if ((rc = siena_phy_cfg(enp)) != 0)
+		goto fail5;
+
+	/* Obtain the default PHY advertised capabilities */
+	if ((rc = siena_nic_reset(enp)) != 0)
+		goto fail6;
+	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
+		goto fail7;
+	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
+	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
+
+#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
+	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
+		goto fail8;
+	enp->en_u.siena.enu_partn_mask = mask;
+#endif
+
+#if EFSYS_OPT_MAC_STATS
+	/* Wipe the MAC statistics */
+	if ((rc = siena_mac_stats_clear(enp)) != 0)
+		goto fail9;
+#endif
+
+#if EFSYS_OPT_LOOPBACK
+	if ((rc = siena_loopback_cfg(enp)) != 0)
+		goto fail10;
+#endif
+
+#if EFSYS_OPT_MON_STATS
+	if ((rc = siena_monitor_cfg(enp)) != 0)
+		goto fail11;
+#endif
+
+	encp->enc_features = enp->en_features;
+
+	return (0);
+
+#if EFSYS_OPT_MON_STATS
+fail11:
+	EFSYS_PROBE(fail11);
+#endif
+#if EFSYS_OPT_LOOPBACK
+fail10:
+	EFSYS_PROBE(fail10);
+#endif
+#if EFSYS_OPT_MAC_STATS
+fail9:
+	EFSYS_PROBE(fail9);
+#endif
+#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
+fail8:
+	EFSYS_PROBE(fail8);
+#endif
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+siena_nic_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_mcdi_req_t req;
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+
+	/* siena_nic_reset() is called to recover from BADASSERT failures. */
+	if ((rc = siena_nic_read_assertion(enp)) != 0)
+		goto fail1;
+	if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
+		goto fail2;
+
+	req.emr_cmd = MC_CMD_PORT_RESET;
+	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (0);
+}
+
+static	__checkReturn	int
+siena_nic_logging(
+	__in		efx_nic_t *enp)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN];
+	int rc;
+
+	req.emr_cmd = MC_CMD_LOG_CTRL;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST,
+		    MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ);
+	MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static			void
+siena_nic_rx_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t oword;
+
+	/*
+	 * RX_INGR_EN is always enabled on Siena, because we rely on
+	 * the RX parser to be resiliant to missing SOP/EOP.
+	 */
+	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
+
+	/* Disable parsing of additional 802.1Q in Q packets */
+	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
+	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
+}
+
+static			void
+siena_nic_usrev_dis(
+	__in		efx_nic_t *enp)
+{
+	efx_oword_t	oword;
+
+	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
+	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
+}
+
+	__checkReturn	int
+siena_nic_init(
+	__in		efx_nic_t *enp)
+{
+	int rc;
+
+	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
+
+	if ((rc = siena_nic_logging(enp)) != 0)
+		goto fail1;
+
+	siena_sram_init(enp);
+
+	/* Configure Siena's RX block */
+	siena_nic_rx_cfg(enp);
+
+	/* Disable USR_EVents for now */
+	siena_nic_usrev_dis(enp);
+
+	/* bug17057: Ensure set_link is called */
+	if ((rc = siena_phy_reconfigure(enp)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+			void
+siena_nic_fini(
+	__in		efx_nic_t *enp)
+{
+	_NOTE(ARGUNUSED(enp))
+}
+
+			void
+siena_nic_unprobe(
+	__in		efx_nic_t *enp)
+{
+	(void) siena_nic_attach(enp, B_FALSE);
+}
+
+#if EFSYS_OPT_DIAG
+
+static efx_register_set_t __cs	__siena_registers[] = {
+	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
+	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
+	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
+	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
+	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
+	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
+	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
+	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
+	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
+	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
+	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
+	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
+	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
+};
+
+static const uint32_t __cs	__siena_register_masks[] = {
+	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
+	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
+	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
+	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
+	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
+	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
+	0x00000003, 0x00000000, 0x00000000, 0x00000000,
+	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
+	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
+};
+
+static efx_register_set_t __cs	__siena_tables[] = {
+	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
+	    FR_AZ_RX_FILTER_TBL0_ROWS },
+	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
+	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
+	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
+	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
+	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
+	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
+	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
+	{ FR_CZ_TX_FILTER_TBL0_OFST,
+	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
+	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
+	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
+};
+
+static const uint32_t __cs	__siena_table_masks[] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
+	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
+	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
+	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
+	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
+	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
+};
+
+	__checkReturn	int
+siena_nic_register_test(
+	__in		efx_nic_t *enp)
+{
+	efx_register_set_t *rsp;
+	const uint32_t *dwordp;
+	unsigned int nitems;
+	unsigned int count;
+	int rc;
+
+	/* Fill out the register mask entries */
+	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
+		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
+
+	nitems = EFX_ARRAY_SIZE(__siena_registers);
+	dwordp = __siena_register_masks;
+	for (count = 0; count < nitems; ++count) {
+		rsp = __siena_registers + count;
+		rsp->mask.eo_u32[0] = *dwordp++;
+		rsp->mask.eo_u32[1] = *dwordp++;
+		rsp->mask.eo_u32[2] = *dwordp++;
+		rsp->mask.eo_u32[3] = *dwordp++;
+	}
+
+	/* Fill out the register table entries */
+	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
+		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
+
+	nitems = EFX_ARRAY_SIZE(__siena_tables);
+	dwordp = __siena_table_masks;
+	for (count = 0; count < nitems; ++count) {
+		rsp = __siena_tables + count;
+		rsp->mask.eo_u32[0] = *dwordp++;
+		rsp->mask.eo_u32[1] = *dwordp++;
+		rsp->mask.eo_u32[2] = *dwordp++;
+		rsp->mask.eo_u32[3] = *dwordp++;
+	}
+
+	if ((rc = efx_nic_test_registers(enp, __siena_registers,
+	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
+		goto fail1;
+
+	if ((rc = efx_nic_test_tables(enp, __siena_tables,
+	    EFX_PATTERN_BYTE_ALTERNATE,
+	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
+		goto fail2;
+
+	if ((rc = efx_nic_test_tables(enp, __siena_tables,
+	    EFX_PATTERN_BYTE_CHANGING,
+	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
+		goto fail3;
+
+	if ((rc = efx_nic_test_tables(enp, __siena_tables,
+	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
+		goto fail4;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_DIAG */
+
+#endif	/* EFSYS_OPT_SIENA */
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/siena_nvram.c	2013-08-22 18:57:35.654176762 -0400
@@ -0,0 +1,996 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_SIENA
+
+#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
+
+	__checkReturn		int
+siena_nvram_partn_size(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__out			size_t *sizep)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
+			    MC_CMD_NVRAM_INFO_OUT_LEN)];
+	int rc;
+
+	if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_NVRAM_INFO;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_NVRAM_INFO_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail3;
+	}
+
+	*sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_nvram_partn_lock(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_NVRAM_UPDATE_START_IN_LEN];
+	int rc;
+
+	req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_NVRAM_UPDATE_START_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_nvram_partn_read(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_LEN,
+			    MC_CMD_NVRAM_READ_OUT_LEN(SIENA_NVRAM_CHUNK))];
+	size_t chunk;
+	int rc;
+
+	while (size > 0) {
+		chunk = MIN(size, SIENA_NVRAM_CHUNK);
+
+		req.emr_cmd = MC_CMD_NVRAM_READ;
+		req.emr_in_buf = payload;
+		req.emr_in_length = MC_CMD_NVRAM_READ_IN_LEN;
+		req.emr_out_buf = payload;
+		req.emr_out_length =
+			MC_CMD_NVRAM_READ_OUT_LEN(SIENA_NVRAM_CHUNK);
+
+		MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_TYPE, partn);
+		MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_OFFSET, offset);
+		MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_LENGTH, chunk);
+
+		efx_mcdi_execute(enp, &req);
+
+		if (req.emr_rc != 0) {
+			rc = req.emr_rc;
+			goto fail1;
+		}
+
+		if (req.emr_out_length_used <
+		    MC_CMD_NVRAM_READ_OUT_LEN(chunk)) {
+			rc = EMSGSIZE;
+			goto fail2;
+		}
+
+		memcpy(data,
+		    MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
+		    chunk);
+
+		size -= chunk;
+		data += chunk;
+		offset += chunk;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_nvram_partn_erase(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__in			unsigned int offset,
+	__in			size_t size)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_NVRAM_ERASE_IN_LEN];
+	int rc;
+
+	req.emr_cmd = MC_CMD_NVRAM_ERASE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_NVRAM_ERASE_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
+	MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
+	MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_nvram_partn_write(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_NVRAM_WRITE_IN_LEN(SIENA_NVRAM_CHUNK)];
+	size_t chunk;
+	int rc;
+
+	while (size > 0) {
+		chunk = MIN(size, SIENA_NVRAM_CHUNK);
+
+		req.emr_cmd = MC_CMD_NVRAM_WRITE;
+		req.emr_in_buf = payload;
+		req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(chunk);
+		EFX_STATIC_ASSERT(MC_CMD_NVRAM_WRITE_OUT_LEN == 0);
+		req.emr_out_buf = NULL;
+		req.emr_out_length = 0;
+
+		MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
+		MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
+		MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, chunk);
+
+		memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
+		    data, chunk);
+
+		efx_mcdi_execute(enp, &req);
+
+		if (req.emr_rc != 0) {
+			rc = req.emr_rc;
+			goto fail1;
+		}
+
+		size -= chunk;
+		data += chunk;
+		offset += chunk;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+				void
+siena_nvram_partn_unlock(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN];
+	uint32_t reboot;
+	int rc;
+
+	req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	/*
+	 * Reboot into the new image only for PHYs. The driver has to
+	 * explicitly cope with an MC reboot after a firmware update.
+	 */
+	reboot = (partn == MC_CMD_NVRAM_TYPE_PHY_PORT0 ||
+		    partn == MC_CMD_NVRAM_TYPE_PHY_PORT1 ||
+		    partn == MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO);
+
+	MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn);
+	MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return;
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+}
+
+#endif	/* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
+
+#if EFSYS_OPT_NVRAM
+
+typedef struct siena_parttbl_entry_s {
+	unsigned int		partn;
+	unsigned int		port;
+	efx_nvram_type_t	nvtype;
+} siena_parttbl_entry_t;
+
+static siena_parttbl_entry_t siena_parttbl[] = {
+	{MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO,	1, EFX_NVRAM_NULLPHY},
+	{MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO,	2, EFX_NVRAM_NULLPHY},
+	{MC_CMD_NVRAM_TYPE_MC_FW,		1, EFX_NVRAM_MC_FIRMWARE},
+	{MC_CMD_NVRAM_TYPE_MC_FW,		2, EFX_NVRAM_MC_FIRMWARE},
+	{MC_CMD_NVRAM_TYPE_MC_FW_BACKUP,	1, EFX_NVRAM_MC_GOLDEN},
+	{MC_CMD_NVRAM_TYPE_MC_FW_BACKUP,	2, EFX_NVRAM_MC_GOLDEN},
+	{MC_CMD_NVRAM_TYPE_EXP_ROM,		1, EFX_NVRAM_BOOTROM},
+	{MC_CMD_NVRAM_TYPE_EXP_ROM,		2, EFX_NVRAM_BOOTROM},
+	{MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0,	1, EFX_NVRAM_BOOTROM_CFG},
+	{MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1,	2, EFX_NVRAM_BOOTROM_CFG},
+	{MC_CMD_NVRAM_TYPE_PHY_PORT0,		1, EFX_NVRAM_PHY},
+	{MC_CMD_NVRAM_TYPE_PHY_PORT1,		2, EFX_NVRAM_PHY},
+	{MC_CMD_NVRAM_TYPE_FPGA,		1, EFX_NVRAM_FPGA},
+	{MC_CMD_NVRAM_TYPE_FPGA,		2, EFX_NVRAM_FPGA},
+	{0, 0, 0},
+};
+
+static	__checkReturn		siena_parttbl_entry_t *
+siena_parttbl_entry(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	siena_parttbl_entry_t *entry;
+
+	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+
+	for (entry = siena_parttbl; entry->port > 0; ++entry) {
+		if (entry->port == emip->emi_port && entry->nvtype == type)
+			return (entry);
+	}
+
+	return (NULL);
+}
+
+#if EFSYS_OPT_DIAG
+
+	__checkReturn		int
+siena_nvram_test(
+	__in			efx_nic_t *enp)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	siena_parttbl_entry_t *entry;
+	efx_mcdi_req_t req;
+	uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
+			    MC_CMD_NVRAM_TEST_OUT_LEN)];
+	int result;
+	int rc;
+
+	req.emr_cmd = MC_CMD_NVRAM_TEST;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
+
+	/*
+	 * Iterate over the list of supported partition types
+	 * applicable to *this* port
+	 */
+	for (entry = siena_parttbl; entry->port > 0; ++entry) {
+		if (entry->port != emip->emi_port ||
+		    !(enp->en_u.siena.enu_partn_mask & (1 << entry->partn)))
+			continue;
+
+		MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, entry->partn);
+
+		efx_mcdi_execute(enp, &req);
+
+		if (req.emr_rc != 0) {
+			rc = req.emr_rc;
+			goto fail1;
+		}
+
+		if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
+			rc = EMSGSIZE;
+			goto fail2;
+		}
+
+		result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
+		if (result == MC_CMD_NVRAM_TEST_FAIL) {
+
+			EFSYS_PROBE1(nvram_test_failure, int, entry->partn);
+
+			rc = (EINVAL);
+			goto fail3;
+		}
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_DIAG */
+
+	__checkReturn		int
+siena_nvram_size(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *sizep)
+{
+	siena_parttbl_entry_t *entry;
+	int rc;
+
+	if ((entry = siena_parttbl_entry(enp, type)) == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = siena_nvram_partn_size(enp, entry->partn, sizep)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	*sizep = 0;
+
+	return (rc);
+}
+
+#define	SIENA_DYNAMIC_CFG_SIZE(_nitems)					\
+	(sizeof (siena_mc_dynamic_config_hdr_t) + ((_nitems) *		\
+	sizeof (((siena_mc_dynamic_config_hdr_t *)NULL)->fw_version[0])))
+
+	__checkReturn		int
+siena_nvram_get_dynamic_cfg(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__in			boolean_t vpd,
+	__out			siena_mc_dynamic_config_hdr_t **dcfgp,
+	__out			size_t *sizep)
+{
+	siena_mc_dynamic_config_hdr_t *dcfg;
+	size_t size;
+	uint8_t cksum;
+	unsigned int vpd_offset;
+	unsigned int vpd_length;
+	unsigned int hdr_length;
+	unsigned int nversions;
+	unsigned int pos;
+	unsigned int region;
+	int rc;
+
+	EFSYS_ASSERT(partn == MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 ||
+		    partn == MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1);
+
+	/*
+	 * Allocate sufficient memory for the entire dynamiccfg area, even
+	 * if we're not actually going to read in the VPD.
+	 */
+	if ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0)
+		goto fail1;
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, size, dcfg);
+	if (dcfg == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	if ((rc = siena_nvram_partn_read(enp, partn, 0,
+	    (caddr_t)dcfg, SIENA_NVRAM_CHUNK)) != 0)
+		goto fail3;
+
+	/* Verify the magic */
+	if (EFX_DWORD_FIELD(dcfg->magic, EFX_DWORD_0)
+	    != SIENA_MC_DYNAMIC_CONFIG_MAGIC)
+		goto invalid1;
+
+	/* All future versions of the structure must be backwards compatable */
+	EFX_STATIC_ASSERT(SIENA_MC_DYNAMIC_CONFIG_VERSION == 0);
+
+	hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);
+	nversions = EFX_DWORD_FIELD(dcfg->num_fw_version_items, EFX_DWORD_0);
+	vpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0);
+	vpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0);
+
+	/* Verify the hdr doesn't overflow the partn size */
+	if (hdr_length > size || vpd_offset > size || vpd_length > size ||
+	    vpd_length + vpd_offset > size)
+		goto invalid2;
+
+	/* Verify the header has room for all it's versions */
+	if (hdr_length < SIENA_DYNAMIC_CFG_SIZE(0) ||
+	    hdr_length < SIENA_DYNAMIC_CFG_SIZE(nversions))
+		goto invalid3;
+
+	/*
+	 * Read the remaining portion of the dcfg, either including
+	 * the whole of VPD (there is no vpd length in this structure,
+	 * so we have to parse each tag), or just the dcfg header itself
+	 */
+	region = vpd ? vpd_offset + vpd_length : hdr_length;
+	if (region > SIENA_NVRAM_CHUNK) {
+		if ((rc = siena_nvram_partn_read(enp, partn, SIENA_NVRAM_CHUNK,
+		    (caddr_t)dcfg + SIENA_NVRAM_CHUNK,
+		    region - SIENA_NVRAM_CHUNK)) != 0)
+			goto fail4;
+	}
+
+	/* Verify checksum */
+	cksum = 0;
+	for (pos = 0; pos < hdr_length; pos++)
+		cksum += ((uint8_t *)dcfg)[pos];
+	if (cksum != 0)
+		goto invalid4;
+
+	goto done;
+
+invalid4:
+	EFSYS_PROBE(invalid4);
+invalid3:
+	EFSYS_PROBE(invalid3);
+invalid2:
+	EFSYS_PROBE(invalid2);
+invalid1:
+	EFSYS_PROBE(invalid1);
+
+	/*
+	 * Construct a new "null" dcfg, with an empty version vector,
+	 * and an empty VPD chunk trailing. This has the neat side effect
+	 * of testing the exception paths in the write path.
+	 */
+	EFX_POPULATE_DWORD_1(dcfg->magic,
+			    EFX_DWORD_0, SIENA_MC_DYNAMIC_CONFIG_MAGIC);
+	EFX_POPULATE_WORD_1(dcfg->length, EFX_WORD_0, sizeof (*dcfg));
+	EFX_POPULATE_BYTE_1(dcfg->version, EFX_BYTE_0,
+			    SIENA_MC_DYNAMIC_CONFIG_VERSION);
+	EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset,
+			    EFX_DWORD_0, sizeof (*dcfg));
+	EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_length, EFX_DWORD_0, 0);
+	EFX_POPULATE_DWORD_1(dcfg->num_fw_version_items, EFX_DWORD_0, 0);
+
+done:
+	*dcfgp = dcfg;
+	*sizep = size;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+
+	EFSYS_KMEM_FREE(enp->en_esip, size, dcfg);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		int
+siena_nvram_get_subtype(
+	__in			efx_nic_t *enp,
+	__in			unsigned int partn,
+	__out			uint32_t *subtypep)
+{
+	efx_mcdi_req_t req;
+	uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LENMAX];
+	efx_word_t *fw_list;
+	int rc;
+
+	req.emr_cmd = MC_CMD_GET_BOARD_CFG;
+	EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = sizeof (outbuf);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	if (req.emr_out_length_used <
+	    MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST +
+	    (partn + 1) * sizeof (efx_word_t)) {
+		rc = ENOENT;
+		goto fail3;
+	}
+
+	fw_list = MCDI_OUT2(req, efx_word_t,
+			    GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST);
+	*subtypep = EFX_WORD_FIELD(fw_list[partn], EFX_WORD_0);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_nvram_get_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint32_t *subtypep,
+	__out_ecount(4)		uint16_t version[4])
+{
+	siena_mc_dynamic_config_hdr_t *dcfg;
+	siena_parttbl_entry_t *entry;
+	unsigned int dcfg_partn;
+	unsigned int partn;
+	int rc;
+
+	if ((entry = siena_parttbl_entry(enp, type)) == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+	partn = entry->partn;
+
+	if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) {
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if ((rc = siena_nvram_get_subtype(enp, partn, subtypep)) != 0)
+		goto fail3;
+
+	/*
+	 * Some partitions are accessible from both ports (for instance BOOTROM)
+	 * Find the highest version reported by all dcfg structures on ports
+	 * that have access to this partition.
+	 */
+	version[0] = version[1] = version[2] = version[3] = 0;
+	for (entry = siena_parttbl; entry->port > 0; ++entry) {
+		unsigned int nitems;
+		uint16_t temp[4];
+		size_t length;
+
+		if (entry->partn != partn)
+			continue;
+
+		dcfg_partn = (entry->port == 1)
+			? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
+			: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
+		/*
+		 * Ingore missing partitions on port 2, assuming they're due
+		 * to to running on a single port part.
+		 */
+		if ((1 << dcfg_partn) &  ~enp->en_u.siena.enu_partn_mask) {
+			if (entry->port == 2)
+				continue;
+		}
+
+		if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
+		    B_FALSE, &dcfg, &length)) != 0)
+			goto fail4;
+
+		nitems = EFX_DWORD_FIELD(dcfg->num_fw_version_items,
+			    EFX_DWORD_0);
+		if (nitems < entry->partn)
+			goto done;
+
+		temp[0] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_w,
+			    EFX_WORD_0);
+		temp[1] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_x,
+			    EFX_WORD_0);
+		temp[2] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_y,
+			    EFX_WORD_0);
+		temp[3] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_z,
+			    EFX_WORD_0);
+		if (memcmp(version, temp, sizeof (temp)) < 0)
+			memcpy(version, temp, sizeof (temp));
+
+	done:
+		EFSYS_KMEM_FREE(enp->en_esip, length, dcfg);
+	}
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_nvram_rw_start(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			size_t *chunk_sizep)
+{
+	siena_parttbl_entry_t *entry;
+	int rc;
+
+	if ((entry = siena_parttbl_entry(enp, type)) == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = siena_nvram_partn_lock(enp, entry->partn)) != 0)
+		goto fail2;
+
+	if (chunk_sizep != NULL)
+		*chunk_sizep = SIENA_NVRAM_CHUNK;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_nvram_read_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	siena_parttbl_entry_t *entry;
+	int rc;
+
+	if ((entry = siena_parttbl_entry(enp, type)) == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = siena_nvram_partn_read(enp, entry->partn,
+	    offset, data, size)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_nvram_erase(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type)
+{
+	siena_parttbl_entry_t *entry;
+	size_t size;
+	int rc;
+
+	if ((entry = siena_parttbl_entry(enp, type)) == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = siena_nvram_partn_size(enp, entry->partn, &size)) != 0)
+		goto fail2;
+
+	if ((rc = siena_nvram_partn_erase(enp, entry->partn, 0, size)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_nvram_write_chunk(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__in			unsigned int offset,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	siena_parttbl_entry_t *entry;
+	int rc;
+
+	if ((entry = siena_parttbl_entry(enp, type)) == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = siena_nvram_partn_write(enp, entry->partn,
+	    offset, data, size)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+				void
+siena_nvram_rw_finish(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type)
+{
+	siena_parttbl_entry_t *entry;
+
+	if ((entry = siena_parttbl_entry(enp, type)) != NULL)
+		siena_nvram_partn_unlock(enp, entry->partn);
+}
+
+	__checkReturn		int
+siena_nvram_set_version(
+	__in			efx_nic_t *enp,
+	__in			efx_nvram_type_t type,
+	__out			uint16_t version[4])
+{
+	siena_mc_dynamic_config_hdr_t *dcfg = NULL;
+	siena_parttbl_entry_t *entry;
+	unsigned int dcfg_partn;
+	size_t partn_size;
+	unsigned int hdr_length;
+	unsigned int vpd_length;
+	unsigned int vpd_offset;
+	unsigned int nitems;
+	unsigned int required_hdr_length;
+	unsigned int pos;
+	uint8_t cksum;
+	uint32_t subtype;
+	size_t length;
+	int rc;
+
+	if ((entry = siena_parttbl_entry(enp, type)) == NULL) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	dcfg_partn = (entry->port == 1)
+		? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
+		: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
+
+	if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &partn_size)) != 0)
+		goto fail2;
+
+	if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0)
+		goto fail2;
+
+	if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
+	    B_TRUE, &dcfg, &length)) != 0)
+		goto fail3;
+
+	hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);
+	nitems = EFX_DWORD_FIELD(dcfg->num_fw_version_items, EFX_DWORD_0);
+	vpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0);
+	vpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0);
+
+	/*
+	 * NOTE: This function will blatt any fields trailing the version
+	 * vector, or the VPD chunk.
+	 */
+	required_hdr_length = SIENA_DYNAMIC_CFG_SIZE(entry->partn + 1);
+	if (required_hdr_length + vpd_length > length) {
+		rc = ENOSPC;
+		goto fail4;
+	}
+
+	if (vpd_offset < required_hdr_length) {
+		(void) memmove((caddr_t)dcfg + required_hdr_length,
+			(caddr_t)dcfg + vpd_offset, vpd_length);
+		vpd_offset = required_hdr_length;
+		EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset,
+				    EFX_DWORD_0, vpd_offset);
+	}
+
+	if (hdr_length < required_hdr_length) {
+		(void) memset((caddr_t)dcfg + hdr_length, 0,
+			required_hdr_length - hdr_length);
+		hdr_length = required_hdr_length;
+		EFX_POPULATE_WORD_1(dcfg->length,
+				    EFX_WORD_0, hdr_length);
+	}
+
+	/* Get the subtype to insert into the fw_subtype array */
+	if ((rc = siena_nvram_get_subtype(enp, entry->partn, &subtype)) != 0)
+		goto fail5;
+
+	/* Fill out the new version */
+	EFX_POPULATE_DWORD_1(dcfg->fw_version[entry->partn].fw_subtype,
+			    EFX_DWORD_0, subtype);
+	EFX_POPULATE_WORD_1(dcfg->fw_version[entry->partn].version_w,
+			    EFX_WORD_0, version[0]);
+	EFX_POPULATE_WORD_1(dcfg->fw_version[entry->partn].version_x,
+			    EFX_WORD_0, version[1]);
+	EFX_POPULATE_WORD_1(dcfg->fw_version[entry->partn].version_y,
+			    EFX_WORD_0, version[2]);
+	EFX_POPULATE_WORD_1(dcfg->fw_version[entry->partn].version_z,
+			    EFX_WORD_0, version[3]);
+
+	/* Update the version count */
+	if (nitems < entry->partn + 1) {
+		nitems = entry->partn + 1;
+		EFX_POPULATE_DWORD_1(dcfg->num_fw_version_items,
+				    EFX_DWORD_0, nitems);
+	}
+
+	/* Update the checksum */
+	cksum = 0;
+	for (pos = 0; pos < hdr_length; pos++)
+		cksum += ((uint8_t *)dcfg)[pos];
+	dcfg->csum.eb_u8[0] -= cksum;
+
+	/* Erase and write the new partition */
+	if ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, partn_size)) != 0)
+		goto fail6;
+
+	/* Write out the new structure to nvram */
+	if ((rc = siena_nvram_partn_write(enp, dcfg_partn, 0,
+	    (caddr_t)dcfg, vpd_offset + vpd_length)) != 0)
+		goto fail7;
+
+	EFSYS_KMEM_FREE(enp->en_esip, length, dcfg);
+
+	siena_nvram_partn_unlock(enp, dcfg_partn);
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+
+	EFSYS_KMEM_FREE(enp->en_esip, length, dcfg);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_NVRAM */
+
+#endif	/* EFSYS_OPT_SIENA */
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/siena_phy.c	2013-08-22 18:57:35.746184280 -0400
@@ -0,0 +1,857 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "efsys.h"
+#include "efx.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_SIENA
+
+static			void
+siena_phy_decode_cap(
+	__in		uint32_t mcdi_cap,
+	__out		uint32_t *maskp)
+{
+	uint32_t mask;
+
+	mask = 0;
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
+		mask |= (1 << EFX_PHY_CAP_10HDX);
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN))
+		mask |= (1 << EFX_PHY_CAP_10FDX);
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN))
+		mask |= (1 << EFX_PHY_CAP_100HDX);
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN))
+		mask |= (1 << EFX_PHY_CAP_100FDX);
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN))
+		mask |= (1 << EFX_PHY_CAP_1000HDX);
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
+		mask |= (1 << EFX_PHY_CAP_1000FDX);
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
+		mask |= (1 << EFX_PHY_CAP_10000FDX);
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
+		mask |= (1 << EFX_PHY_CAP_PAUSE);
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
+		mask |= (1 << EFX_PHY_CAP_ASYM);
+	if (mcdi_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
+		mask |= (1 << EFX_PHY_CAP_AN);
+
+	*maskp = mask;
+}
+
+static			void
+siena_phy_decode_link_mode(
+	__in		efx_nic_t *enp,
+	__in		uint32_t link_flags,
+	__in		unsigned int speed,
+	__in		unsigned int fcntl,
+	__out		efx_link_mode_t *link_modep,
+	__out		unsigned int *fcntlp)
+{
+	boolean_t fd = !!(link_flags &
+		    (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
+	boolean_t up = !!(link_flags &
+		    (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
+
+	_NOTE(ARGUNUSED(enp))
+
+	if (!up)
+		*link_modep = EFX_LINK_DOWN;
+	else if (speed == 10000 && fd)
+		*link_modep = EFX_LINK_10000FDX;
+	else if (speed == 1000)
+		*link_modep = fd ? EFX_LINK_1000FDX : EFX_LINK_1000HDX;
+	else if (speed == 100)
+		*link_modep = fd ? EFX_LINK_100FDX : EFX_LINK_100HDX;
+	else if (speed == 10)
+		*link_modep = fd ? EFX_LINK_10FDX : EFX_LINK_10HDX;
+	else
+		*link_modep = EFX_LINK_UNKNOWN;
+
+	if (fcntl == MC_CMD_FCNTL_OFF)
+		*fcntlp = 0;
+	else if (fcntl == MC_CMD_FCNTL_RESPOND)
+		*fcntlp = EFX_FCNTL_RESPOND;
+	else if (fcntl == MC_CMD_FCNTL_BIDIR)
+		*fcntlp = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
+	else {
+		EFSYS_PROBE1(mc_pcol_error, int, fcntl);
+		*fcntlp = 0;
+	}
+}
+
+			void
+siena_phy_link_ev(
+	__in		efx_nic_t *enp,
+	__in		efx_qword_t *eqp,
+	__out		efx_link_mode_t *link_modep)
+{
+	efx_port_t *epp = &(enp->en_port);
+	unsigned int link_flags;
+	unsigned int speed;
+	unsigned int fcntl;
+	efx_link_mode_t link_mode;
+	uint32_t lp_cap_mask;
+
+	/*
+	 * Convert the LINKCHANGE speed enumeration into mbit/s, in the
+	 * same way as GET_LINK encodes the speed
+	 */
+	switch (MCDI_EV_FIELD(eqp, LINKCHANGE_SPEED)) {
+	case MCDI_EVENT_LINKCHANGE_SPEED_100M:
+		speed = 100;
+		break;
+	case MCDI_EVENT_LINKCHANGE_SPEED_1G:
+		speed = 1000;
+		break;
+	case MCDI_EVENT_LINKCHANGE_SPEED_10G:
+		speed = 10000;
+		break;
+	default:
+		speed = 0;
+		break;
+	}
+
+	link_flags = MCDI_EV_FIELD(eqp, LINKCHANGE_LINK_FLAGS);
+	siena_phy_decode_link_mode(enp, link_flags, speed,
+				    MCDI_EV_FIELD(eqp, LINKCHANGE_FCNTL),
+				    &link_mode, &fcntl);
+	siena_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP),
+			    &lp_cap_mask);
+
+	/*
+	 * It's safe to update ep_lp_cap_mask without the driver's port lock
+	 * because presumably any concurrently running efx_port_poll() is
+	 * only going to arrive at the same value.
+	 *
+	 * ep_fcntl has two meanings. It's either the link common fcntl
+	 * (if the PHY supports AN), or it's the forced link state. If
+	 * the former, it's safe to update the value for the same reason as
+	 * for ep_lp_cap_mask. If the latter, then just ignore the value,
+	 * because we can race with efx_mac_fcntl_set().
+	 */
+	epp->ep_lp_cap_mask = lp_cap_mask;
+	if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
+		epp->ep_fcntl = fcntl;
+
+	*link_modep = link_mode;
+}
+
+	__checkReturn	int
+siena_phy_power(
+	__in		efx_nic_t *enp,
+	__in		boolean_t power)
+{
+	int rc;
+
+	if (!power)
+		return (0);
+
+	/* Check if the PHY is a zombie */
+	if ((rc = siena_phy_verify(enp)) != 0)
+		goto fail1;
+
+	enp->en_reset_flags |= EFX_RESET_PHY;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+siena_phy_get_link(
+	__in		efx_nic_t *enp,
+	__out		siena_link_state_t *slsp)
+{
+	efx_mcdi_req_t req;
+	uint8_t outbuf[MC_CMD_GET_LINK_OUT_LEN];
+	int rc;
+
+	req.emr_cmd = MC_CMD_GET_LINK;
+	EFX_STATIC_ASSERT(MC_CMD_GET_LINK_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = sizeof (outbuf);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	siena_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP),
+			    &slsp->sls_adv_cap_mask);
+	siena_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP),
+			    &slsp->sls_lp_cap_mask);
+
+	siena_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS),
+			    MCDI_OUT_DWORD(req, GET_LINK_OUT_LINK_SPEED),
+			    MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL),
+			    &slsp->sls_link_mode, &slsp->sls_fcntl);
+
+#if EFSYS_OPT_LOOPBACK
+	/* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);
+	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);
+
+	slsp->sls_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE);
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	slsp->sls_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+siena_phy_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_mcdi_req_t req;
+	uint8_t payload[MAX(MC_CMD_SET_ID_LED_IN_LEN,
+			    MC_CMD_SET_LINK_IN_LEN)];
+	uint32_t cap_mask;
+	unsigned int led_mode;
+	unsigned int speed;
+	int rc;
+
+	req.emr_cmd = MC_CMD_SET_LINK;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_SET_LINK_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_SET_LINK_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	cap_mask = epp->ep_adv_cap_mask;
+	MCDI_IN_POPULATE_DWORD_10(req, SET_LINK_IN_CAP,
+		PHY_CAP_10HDX, (cap_mask >> EFX_PHY_CAP_10HDX) & 0x1,
+		PHY_CAP_10FDX, (cap_mask >> EFX_PHY_CAP_10FDX) & 0x1,
+		PHY_CAP_100HDX, (cap_mask >> EFX_PHY_CAP_100HDX) & 0x1,
+		PHY_CAP_100FDX, (cap_mask >> EFX_PHY_CAP_100FDX) & 0x1,
+		PHY_CAP_1000HDX, (cap_mask >> EFX_PHY_CAP_1000HDX) & 0x1,
+		PHY_CAP_1000FDX, (cap_mask >> EFX_PHY_CAP_1000FDX) & 0x1,
+		PHY_CAP_10000FDX, (cap_mask >> EFX_PHY_CAP_10000FDX) & 0x1,
+		PHY_CAP_PAUSE, (cap_mask >> EFX_PHY_CAP_PAUSE) & 0x1,
+		PHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1,
+		PHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1);
+
+#if EFSYS_OPT_LOOPBACK
+	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE,
+		    epp->ep_loopback_type);
+	switch (epp->ep_loopback_link_mode) {
+	case EFX_LINK_100FDX:
+		speed = 100;
+		break;
+	case EFX_LINK_1000FDX:
+		speed = 1000;
+		break;
+	case EFX_LINK_10000FDX:
+		speed = 10000;
+		break;
+	default:
+		speed = 0;
+	}
+#else
+	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);
+	speed = 0;
+#endif	/* EFSYS_OPT_LOOPBACK */
+	MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);
+
+#if EFSYS_OPT_PHY_FLAGS
+	MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, epp->ep_phy_flags);
+#else
+	MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, 0);
+#endif	/* EFSYS_OPT_PHY_FLAGS */
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	/* And set the blink mode */
+	req.emr_cmd = MC_CMD_SET_ID_LED;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_SET_ID_LED_IN_LEN;
+	EFX_STATIC_ASSERT(MC_CMD_SET_ID_LED_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+#if EFSYS_OPT_PHY_LED_CONTROL
+	switch (epp->ep_phy_led_mode) {
+	case EFX_PHY_LED_DEFAULT:
+		led_mode = MC_CMD_LED_DEFAULT;
+		break;
+	case EFX_PHY_LED_OFF:
+		led_mode = MC_CMD_LED_OFF;
+		break;
+	case EFX_PHY_LED_ON:
+		led_mode = MC_CMD_LED_ON;
+		break;
+	default:
+		EFSYS_ASSERT(0);
+		led_mode = MC_CMD_LED_DEFAULT;
+	}
+
+	MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, led_mode);
+#else
+	MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, MC_CMD_LED_DEFAULT);
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+siena_phy_verify(
+	__in		efx_nic_t *enp)
+{
+	efx_mcdi_req_t req;
+	uint8_t outbuf[MC_CMD_GET_PHY_STATE_OUT_LEN];
+	uint32_t state;
+	int rc;
+
+	req.emr_cmd = MC_CMD_GET_PHY_STATE;
+	EFX_STATIC_ASSERT(MC_CMD_GET_PHY_STATE_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = outbuf;
+	req.emr_out_length = sizeof (outbuf);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_GET_PHY_STATE_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	state = MCDI_OUT_DWORD(req, GET_PHY_STATE_OUT_STATE);
+	if (state != MC_CMD_PHY_STATE_OK) {
+		if (state != MC_CMD_PHY_STATE_ZOMBIE)
+			EFSYS_PROBE1(mc_pcol_error, int, state);
+		rc = ENOTACTIVE;
+		goto fail3;
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+siena_phy_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip)
+{
+	_NOTE(ARGUNUSED(enp, ouip))
+
+	return (ENOTSUP);
+}
+
+#if EFSYS_OPT_PHY_STATS
+
+#define	SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat,		\
+			    _mc_record, _efx_record)			\
+	if ((_vmask) & (1ULL << (_mc_record))) {			\
+		(_smask) |= (1ULL << (_efx_record));			\
+		if ((_stat) != NULL && !EFSYS_MEM_IS_NULL(_esmp)) {	\
+			efx_dword_t dword;				\
+			EFSYS_MEM_READD(_esmp, (_mc_record) * 4, &dword);\
+			(_stat)[_efx_record] =				\
+				EFX_DWORD_FIELD(dword, EFX_DWORD_0);	\
+		}							\
+	}
+
+#define	SIENA_SIMPLE_STAT_SET2(_vmask, _esmp, _smask, _stat, _record)	\
+	SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat, 		\
+			    MC_CMD_ ## _record,				\
+			    EFX_PHY_STAT_ ## _record)
+
+						void
+siena_phy_decode_stats(
+	__in					efx_nic_t *enp,
+	__in					uint32_t vmask,
+	__in_opt				efsys_mem_t *esmp,
+	__out_opt				uint64_t *smaskp,
+	__out_ecount_opt(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	uint64_t smask = 0;
+
+	_NOTE(ARGUNUSED(enp))
+
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, OUI);
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_LINK_UP);
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_RX_FAULT);
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_TX_FAULT);
+
+	if (vmask & (1 << MC_CMD_PMA_PMD_SIGNAL)) {
+		smask |=   ((1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_A) |
+			    (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_B) |
+			    (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_C) |
+			    (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_D));
+		if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
+			efx_dword_t dword;
+			uint32_t sig;
+			EFSYS_MEM_READD(esmp, 4 * MC_CMD_PMA_PMD_SIGNAL,
+					&dword);
+			sig = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_A] = (sig >> 1) & 1;
+			stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_B] = (sig >> 2) & 1;
+			stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_C] = (sig >> 3) & 1;
+			stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_D] = (sig >> 4) & 1;
+		}
+	}
+
+	SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_A,
+			    EFX_PHY_STAT_SNR_A);
+	SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_B,
+			    EFX_PHY_STAT_SNR_B);
+	SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_C,
+			    EFX_PHY_STAT_SNR_C);
+	SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_D,
+			    EFX_PHY_STAT_SNR_D);
+
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_LINK_UP);
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_RX_FAULT);
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_TX_FAULT);
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_BER);
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_BLOCK_ERRORS);
+
+	SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_LINK_UP,
+			    EFX_PHY_STAT_PHY_XS_LINK_UP);
+	SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_RX_FAULT,
+			    EFX_PHY_STAT_PHY_XS_RX_FAULT);
+	SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_TX_FAULT,
+			    EFX_PHY_STAT_PHY_XS_TX_FAULT);
+	SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_ALIGN,
+			    EFX_PHY_STAT_PHY_XS_ALIGN);
+
+	if (vmask & (1 << MC_CMD_PHYXS_SYNC)) {
+		smask |=   ((1 << EFX_PHY_STAT_PHY_XS_SYNC_A) |
+			    (1 << EFX_PHY_STAT_PHY_XS_SYNC_B) |
+			    (1 << EFX_PHY_STAT_PHY_XS_SYNC_C) |
+			    (1 << EFX_PHY_STAT_PHY_XS_SYNC_D));
+		if (stat != NULL && !EFSYS_MEM_IS_NULL(esmp)) {
+			efx_dword_t dword;
+			uint32_t sync;
+			EFSYS_MEM_READD(esmp, 4 * MC_CMD_PHYXS_SYNC, &dword);
+			sync = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			stat[EFX_PHY_STAT_PHY_XS_SYNC_A] = (sync >> 0) & 1;
+			stat[EFX_PHY_STAT_PHY_XS_SYNC_B] = (sync >> 1) & 1;
+			stat[EFX_PHY_STAT_PHY_XS_SYNC_C] = (sync >> 2) & 1;
+			stat[EFX_PHY_STAT_PHY_XS_SYNC_D] = (sync >> 3) & 1;
+		}
+	}
+
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, AN_LINK_UP);
+	SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, AN_COMPLETE);
+
+	SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_CL22_LINK_UP,
+			    EFX_PHY_STAT_CL22EXT_LINK_UP);
+
+	if (smaskp != NULL)
+		*smaskp = smask;
+}
+
+	__checkReturn				int
+siena_phy_stats_update(
+	__in					efx_nic_t *enp,
+	__in					efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)		uint32_t *stat)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint32_t vmask = encp->enc_siena_phy_stat_mask;
+	uint8_t payload[MC_CMD_PHY_STATS_IN_LEN];
+	uint64_t smask;
+	efx_mcdi_req_t req;
+	int rc;
+
+	req.emr_cmd = MC_CMD_PHY_STATS;
+	req.emr_in_buf = payload;
+	req.emr_in_length = sizeof (payload);
+	EFX_STATIC_ASSERT(MC_CMD_PHY_STATS_OUT_DMA_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	MCDI_IN_SET_DWORD(req, PHY_STATS_IN_DMA_ADDR_LO,
+			    EFSYS_MEM_ADDR(esmp) & 0xffffffff);
+	MCDI_IN_SET_DWORD(req, PHY_STATS_IN_DMA_ADDR_HI,
+			    EFSYS_MEM_ADDR(esmp) >> 32);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+	EFSYS_ASSERT3U(req.emr_out_length, ==, MC_CMD_PHY_STATS_OUT_DMA_LEN);
+
+	siena_phy_decode_stats(enp, vmask, esmp, &smask, stat);
+	EFSYS_ASSERT(smask == encp->enc_phy_stat_mask);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (0);
+}
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+siena_phy_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	_NOTE(ARGUNUSED(enp, id))
+
+	return (NULL);
+}
+
+#endif	/* EFSYS_OPT_NAMES */
+
+extern	__checkReturn	int
+siena_phy_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp)
+{
+	_NOTE(ARGUNUSED(enp, id, flags, valp))
+
+	return (ENOTSUP);
+}
+
+extern	__checkReturn	int
+siena_phy_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val)
+{
+	_NOTE(ARGUNUSED(enp, id, val))
+
+	return (ENOTSUP);
+}
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#if EFSYS_OPT_PHY_BIST
+
+	__checkReturn		int
+siena_phy_bist_start(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type)
+{
+	uint8_t payload[MC_CMD_START_BIST_IN_LEN];
+	efx_mcdi_req_t req;
+	int rc;
+
+	req.emr_cmd = MC_CMD_START_BIST;
+	req.emr_in_buf = payload;
+	req.emr_in_length = sizeof (payload);
+	EFX_STATIC_ASSERT(MC_CMD_START_BIST_OUT_LEN == 0);
+	req.emr_out_buf = NULL;
+	req.emr_out_length = 0;
+
+	switch (type) {
+	case EFX_PHY_BIST_TYPE_NORMAL:
+		MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, MC_CMD_PHY_BIST);
+		break;
+	case EFX_PHY_BIST_TYPE_CABLE_SHORT:
+		MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE,
+		    MC_CMD_PHY_BIST_CABLE_SHORT);
+		break;
+	case EFX_PHY_BIST_TYPE_CABLE_LONG:
+		MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE,
+		    MC_CMD_PHY_BIST_CABLE_LONG);
+		break;
+	default:
+		EFSYS_ASSERT(0);
+	}
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		unsigned long
+siena_phy_sft9001_bist_status(
+	__in			uint16_t code)
+{
+	switch (code) {
+	case MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY:
+		return (EFX_PHY_CABLE_STATUS_BUSY);
+	case MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT:
+		return (EFX_PHY_CABLE_STATUS_INTERPAIRSHORT);
+	case MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT:
+		return (EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT);
+	case MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN:
+		return (EFX_PHY_CABLE_STATUS_OPEN);
+	case MC_CMD_POLL_BIST_SFT9001_PAIR_OK:
+		return (EFX_PHY_CABLE_STATUS_OK);
+	default:
+		return (EFX_PHY_CABLE_STATUS_INVALID);
+	}
+}
+
+	__checkReturn		int
+siena_phy_bist_poll(
+	__in			efx_nic_t *enp,
+	__in			efx_phy_bist_type_t type,
+	__out			efx_phy_bist_result_t *resultp,
+	__out_opt __drv_when(count > 0, __notnull)
+	uint32_t *value_maskp,
+	__out_ecount_opt(count)	__drv_when(count > 0, __notnull)
+	unsigned long *valuesp,
+	__in			size_t count)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint8_t payload[MCDI_CTL_SDU_LEN_MAX];
+	uint32_t value_mask = 0;
+	efx_mcdi_req_t req;
+	uint32_t result;
+	int rc;
+
+	req.emr_cmd = MC_CMD_POLL_BIST;
+	_NOTE(CONSTANTCONDITION)
+	EFSYS_ASSERT(MC_CMD_POLL_BIST_IN_LEN == 0);
+	req.emr_in_buf = NULL;
+	req.emr_in_length = 0;
+	req.emr_out_buf = payload;
+	req.emr_out_length = sizeof (payload);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_POLL_BIST_OUT_RESULT_OFST + 4) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	if (count > 0)
+		(void) memset(valuesp, '\0', count * sizeof (unsigned long));
+
+	result = MCDI_OUT_DWORD(req, POLL_BIST_OUT_RESULT);
+
+	/* Extract PHY specific results */
+	if (result == MC_CMD_POLL_BIST_PASSED &&
+	    encp->enc_phy_type == EFX_PHY_SFT9001B &&
+	    req.emr_out_length_used >= MC_CMD_POLL_BIST_OUT_SFT9001_LEN &&
+	    (type == EFX_PHY_BIST_TYPE_CABLE_SHORT ||
+	    type == EFX_PHY_BIST_TYPE_CABLE_LONG)) {
+		uint16_t word;
+
+		if (count > EFX_PHY_BIST_CABLE_LENGTH_A) {
+			if (valuesp != NULL)
+				valuesp[EFX_PHY_BIST_CABLE_LENGTH_A] =
+				    MCDI_OUT_DWORD(req,
+				    POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A);
+			value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_A);
+		}
+
+		if (count > EFX_PHY_BIST_CABLE_LENGTH_B) {
+			if (valuesp != NULL)
+				valuesp[EFX_PHY_BIST_CABLE_LENGTH_B] =
+				    MCDI_OUT_DWORD(req,
+				    POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B);
+			value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_B);
+		}
+
+		if (count > EFX_PHY_BIST_CABLE_LENGTH_C) {
+			if (valuesp != NULL)
+				valuesp[EFX_PHY_BIST_CABLE_LENGTH_C] =
+				    MCDI_OUT_DWORD(req,
+				    POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C);
+			value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_C);
+		}
+
+		if (count > EFX_PHY_BIST_CABLE_LENGTH_D) {
+			if (valuesp != NULL)
+				valuesp[EFX_PHY_BIST_CABLE_LENGTH_D] =
+				    MCDI_OUT_DWORD(req,
+				    POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D);
+			value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_D);
+		}
+
+		if (count > EFX_PHY_BIST_CABLE_STATUS_A) {
+			if (valuesp != NULL) {
+				word = MCDI_OUT_WORD(req,
+				    POLL_BIST_OUT_SFT9001_CABLE_STATUS_A);
+				valuesp[EFX_PHY_BIST_CABLE_STATUS_A] =
+				    siena_phy_sft9001_bist_status(word);
+			}
+			value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_A);
+		}
+
+		if (count > EFX_PHY_BIST_CABLE_STATUS_B) {
+			if (valuesp != NULL) {
+				word = MCDI_OUT_WORD(req,
+				    POLL_BIST_OUT_SFT9001_CABLE_STATUS_B);
+				valuesp[EFX_PHY_BIST_CABLE_STATUS_B] =
+				    siena_phy_sft9001_bist_status(word);
+			}
+			value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_B);
+		}
+
+		if (count > EFX_PHY_BIST_CABLE_STATUS_C) {
+			if (valuesp != NULL) {
+				word = MCDI_OUT_WORD(req,
+				    POLL_BIST_OUT_SFT9001_CABLE_STATUS_C);
+				valuesp[EFX_PHY_BIST_CABLE_STATUS_C] =
+				    siena_phy_sft9001_bist_status(word);
+			}
+			value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_C);
+		}
+
+		if (count > EFX_PHY_BIST_CABLE_STATUS_D) {
+			if (valuesp != NULL) {
+				word = MCDI_OUT_WORD(req,
+				    POLL_BIST_OUT_SFT9001_CABLE_STATUS_D);
+				valuesp[EFX_PHY_BIST_CABLE_STATUS_D] =
+				    siena_phy_sft9001_bist_status(word);
+			}
+			value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_D);
+		}
+
+	} else if (result == MC_CMD_POLL_BIST_FAILED &&
+		    encp->enc_phy_type == EFX_PHY_QLX111V &&
+		    req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MRSFP_LEN &&
+		    count > EFX_PHY_BIST_FAULT_CODE) {
+		if (valuesp != NULL)
+			valuesp[EFX_PHY_BIST_FAULT_CODE] =
+			    MCDI_OUT_DWORD(req, POLL_BIST_OUT_MRSFP_TEST);
+		value_mask |= 1 << EFX_PHY_BIST_FAULT_CODE;
+	}
+
+	if (value_maskp != NULL)
+		*value_maskp = value_mask;
+
+	EFSYS_ASSERT(resultp != NULL);
+	if (result == MC_CMD_POLL_BIST_RUNNING)
+		*resultp = EFX_PHY_BIST_RESULT_RUNNING;
+	else if (result == MC_CMD_POLL_BIST_PASSED)
+		*resultp = EFX_PHY_BIST_RESULT_PASSED;
+	else
+		*resultp = EFX_PHY_BIST_RESULT_FAILED;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+			void
+siena_phy_bist_stop(
+	__in		efx_nic_t *enp,
+	__in		efx_phy_bist_type_t type)
+{
+	/* There is no way to stop BIST on Siena */
+	_NOTE(ARGUNUSED(enp, type))
+}
+
+#endif	/* EFSYS_OPT_PHY_BIST */
+
+#endif	/* EFSYS_OPT_SIENA */
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/siena_sram.c	2013-08-22 18:57:35.837911966 -0400
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "efsys.h"
+#include "efx.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_SIENA
+
+			void
+siena_sram_init(
+	__in		efx_nic_t *enp)
+{
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	efx_oword_t oword;
+	uint32_t rx_base, tx_base;
+
+	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	rx_base = encp->enc_buftbl_limit;
+	tx_base = rx_base + (encp->enc_rxq_limit *
+	    EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
+
+	/* Initialize the transmit descriptor cache */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_TX_DC_BASE_ADR, tx_base);
+	EFX_BAR_WRITEO(enp, FR_AZ_SRM_TX_DC_CFG_REG, &oword);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DC_SIZE, EFX_TXQ_DC_SIZE);
+	EFX_BAR_WRITEO(enp, FR_AZ_TX_DC_CFG_REG, &oword);
+
+	/* Initialize the receive descriptor cache */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_RX_DC_BASE_ADR, rx_base);
+	EFX_BAR_WRITEO(enp, FR_AZ_SRM_RX_DC_CFG_REG, &oword);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DC_SIZE, EFX_RXQ_DC_SIZE);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_DC_CFG_REG, &oword);
+
+	/* Set receive descriptor pre-fetch low water mark */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DC_PF_LWM, 56);
+	EFX_BAR_WRITEO(enp, FR_AZ_RX_DC_PF_WM_REG, &oword);
+
+	/* Set the event queue to use for SRAM updates */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_UPD_EVQ_ID, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_SRM_UPD_EVQ_REG, &oword);
+}
+
+#if EFSYS_OPT_DIAG
+
+	__checkReturn	int
+siena_sram_test(
+	__in		efx_nic_t *enp,
+	__in		efx_sram_pattern_fn_t func)
+{
+	efx_oword_t oword;
+	efx_qword_t qword;
+	efx_qword_t verify;
+	size_t rows;
+	unsigned int wptr;
+	unsigned int rptr;
+	int rc;
+
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	/* Reconfigure into HALF buffer table mode */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 0);
+	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);
+
+	/*
+	 * Move the descriptor caches up to the top of SRAM, and test
+	 * all of SRAM below them. We only miss out one row here.
+	 */
+	rows = SIENA_SRAM_ROWS - 1;
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_RX_DC_BASE_ADR, rows);
+	EFX_BAR_WRITEO(enp, FR_AZ_SRM_RX_DC_CFG_REG, &oword);
+
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_SRM_TX_DC_BASE_ADR, rows + 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_SRM_TX_DC_CFG_REG, &oword);
+
+	/*
+	 * Write the pattern through BUF_HALF_TBL. Write
+	 * in 64 entry batches, waiting 1us in between each batch
+	 * to guarantee not to overflow the SRAM fifo
+	 */
+	for (wptr = 0, rptr = 0; wptr < rows; ++wptr) {
+		func(wptr, B_FALSE, &qword);
+		EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_HALF_TBL, wptr, &qword);
+
+		if ((wptr - rptr) < 64 && wptr < rows - 1)
+			continue;
+
+		EFSYS_SPIN(1);
+
+		for (; rptr <= wptr; ++rptr) {
+			func(rptr, B_FALSE, &qword);
+			EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_HALF_TBL, rptr,
+			    &verify);
+
+			if (!EFX_QWORD_IS_EQUAL(verify, qword)) {
+				rc = EFAULT;
+				goto fail1;
+			}
+		}
+	}
+
+	/* And do the same negated */
+	for (wptr = 0, rptr = 0; wptr < rows; ++wptr) {
+		func(wptr, B_TRUE, &qword);
+		EFX_BAR_TBL_WRITEQ(enp, FR_AZ_BUF_HALF_TBL, wptr, &qword);
+
+		if ((wptr - rptr) < 64 && wptr < rows - 1)
+			continue;
+
+		EFSYS_SPIN(1);
+
+		for (; rptr <= wptr; ++rptr) {
+			func(rptr, B_TRUE, &qword);
+			EFX_BAR_TBL_READQ(enp, FR_AZ_BUF_HALF_TBL, rptr,
+			    &verify);
+
+			if (!EFX_QWORD_IS_EQUAL(verify, qword)) {
+				rc = EFAULT;
+				goto fail2;
+			}
+		}
+	}
+
+	/* Restore back to FULL buffer table mode */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);
+
+	/*
+	 * We don't need to reconfigure SRAM again because the API
+	 * requires efx_nic_fini() to be called after an sram test.
+	 */
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	/* Restore back to FULL buffer table mode */
+	EFX_POPULATE_OWORD_1(oword, FRF_AZ_BUF_TBL_MODE, 1);
+	EFX_BAR_WRITEO(enp, FR_AZ_BUF_TBL_CFG_REG, &oword);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_DIAG */
+
+#endif	/* EFSYS_OPT_SIENA */
--- /dev/null	2013-08-22 18:57:35.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/siena_vpd.c	2013-08-22 18:57:35.923914792 -0400
@@ -0,0 +1,602 @@
+/*
+ * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_VPD
+
+#if EFSYS_OPT_SIENA
+
+static	__checkReturn			int
+siena_vpd_get_static(
+	__in				efx_nic_t *enp,
+	__in				unsigned int partn,
+	__deref_out_bcount_opt(*sizep)	caddr_t *svpdp,
+	__out				size_t *sizep)
+{
+	siena_mc_static_config_hdr_t *scfg;
+	caddr_t svpd;
+	size_t size;
+	uint8_t cksum;
+	unsigned int vpd_offset;
+	unsigned int vpd_length;
+	unsigned int hdr_length;
+	unsigned int pos;
+	unsigned int region;
+	int rc;
+
+	EFSYS_ASSERT(partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 ||
+		    partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1);
+
+	/* Allocate sufficient memory for the entire static cfg area */
+	if ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0)
+		goto fail1;
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, size, scfg);
+	if (scfg == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	if ((rc = siena_nvram_partn_read(enp, partn, 0,
+	    (caddr_t)scfg, SIENA_NVRAM_CHUNK)) != 0)
+		goto fail3;
+
+	/* Verify the magic number */
+	if (EFX_DWORD_FIELD(scfg->magic, EFX_DWORD_0) !=
+	    SIENA_MC_STATIC_CONFIG_MAGIC) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	/* All future versions of the structure must be backwards compatable */
+	EFX_STATIC_ASSERT(SIENA_MC_STATIC_CONFIG_VERSION == 0);
+
+	hdr_length = EFX_WORD_FIELD(scfg->length, EFX_WORD_0);
+	vpd_offset = EFX_DWORD_FIELD(scfg->static_vpd_offset, EFX_DWORD_0);
+	vpd_length = EFX_DWORD_FIELD(scfg->static_vpd_length, EFX_DWORD_0);
+
+	/* Verify the hdr doesn't overflow the sector size */
+	if (hdr_length > size || vpd_offset > size || vpd_length > size ||
+	    vpd_length + vpd_offset > size) {
+		rc = EINVAL;
+		goto fail5;
+	}
+
+	/* Read the remainder of scfg + static vpd */
+	region = vpd_offset + vpd_length;
+	if (region > SIENA_NVRAM_CHUNK) {
+		if ((rc = siena_nvram_partn_read(enp, partn, SIENA_NVRAM_CHUNK,
+		    (caddr_t)scfg + SIENA_NVRAM_CHUNK,
+		    region - SIENA_NVRAM_CHUNK)) != 0)
+			goto fail6;
+	}
+
+	/* Verify checksum */
+	cksum = 0;
+	for (pos = 0; pos < hdr_length; pos++)
+		cksum += ((uint8_t *)scfg)[pos];
+	if (cksum != 0) {
+		rc = EINVAL;
+		goto fail7;
+	}
+
+	if (vpd_length == 0)
+		svpd = NULL;
+	else {
+		/* Copy the vpd data out */
+		EFSYS_KMEM_ALLOC(enp->en_esip, vpd_length, svpd);
+		if (svpd == NULL) {
+			rc = ENOMEM;
+			goto fail8;
+		}
+		memcpy(svpd, (caddr_t)scfg + vpd_offset, vpd_length);
+	}
+
+	EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
+
+	*svpdp = svpd;
+	*sizep = vpd_length;
+
+	return (0);
+
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+
+	EFSYS_KMEM_FREE(enp->en_esip, size, scfg);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_vpd_init(
+	__in			efx_nic_t *enp)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	caddr_t svpd = NULL;
+	unsigned partn;
+	size_t size = 0;
+	int rc;
+
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	partn = (emip->emi_port == 1)
+		? MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0
+		: MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1;
+
+	/*
+	 * We need the static VPD sector to present a unified static+dynamic
+	 * VPD, that is, basically on every read, write, verify cycle. Since
+	 * it should *never* change we can just cache it here.
+	 */
+	if ((rc = siena_vpd_get_static(enp, partn, &svpd, &size)) != 0)
+		goto fail1;
+
+	if (svpd != NULL && size > 0) {
+		if ((rc = efx_vpd_hunk_verify(svpd, size, NULL)) != 0)
+			goto fail2;
+	}
+
+	enp->en_u.siena.enu_svpd = svpd;
+	enp->en_u.siena.enu_svpd_length = size;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+
+	EFSYS_KMEM_FREE(enp->en_esip, size, svpd);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_vpd_size(
+	__in			efx_nic_t *enp,
+	__out			size_t *sizep)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	unsigned int partn;
+	int rc;
+
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	/*
+	 * This function returns the total size the user should allocate
+	 * for all VPD operations. We've already cached the static vpd,
+	 * so we just need to return an upper bound on the dynamic vpd.
+	 * Since the dynamic_config structure can change under our feet,
+	 * (as version numbers are inserted), just be safe and return the
+	 * total size of the dynamic_config *sector*
+	 */
+	partn = (emip->emi_port == 1)
+		? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
+		: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
+
+	if ((rc = siena_nvram_partn_size(enp, partn, sizep)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_vpd_read(
+	__in			efx_nic_t *enp,
+	__out_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	siena_mc_dynamic_config_hdr_t *dcfg;
+	unsigned int vpd_length;
+	unsigned int vpd_offset;
+	unsigned int dcfg_partn;
+	size_t dcfg_size;
+	int rc;
+
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	dcfg_partn = (emip->emi_port == 1)
+		? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
+		: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
+
+	if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
+	    B_TRUE, &dcfg, &dcfg_size)) != 0)
+		goto fail1;
+
+	vpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0);
+	vpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0);
+
+	if (vpd_length > size) {
+		rc = EFAULT;	/* Invalid dcfg: header bigger than sector */
+		goto fail2;
+	}
+
+	EFSYS_ASSERT3U(vpd_length, <=, size);
+	memcpy(data, (caddr_t)dcfg + vpd_offset, vpd_length);
+
+	/* Pad data with all-1s, consistent with update operations */
+	memset(data + vpd_length, 0xff, size - vpd_length);
+
+	EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+
+	EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_vpd_verify(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_vpd_tag_t stag;
+	efx_vpd_tag_t dtag;
+	efx_vpd_keyword_t skey;
+	efx_vpd_keyword_t dkey;
+	unsigned int scont;
+	unsigned int dcont;
+
+	int rc;
+
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	/*
+	 * Strictly you could take the view that dynamic vpd is optional.
+	 * Instead, to conform more closely to the read/verify/reinit()
+	 * paradigm, we require dynamic vpd. siena_vpd_reinit() will
+	 * reinitialize it as required.
+	 */
+	if ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0)
+		goto fail1;
+
+	/*
+	 * Verify that there is no duplication between the static and
+	 * dynamic cfg sectors.
+	 */
+	if (enp->en_u.siena.enu_svpd_length == 0)
+		goto done;
+
+	dcont = 0;
+	_NOTE(CONSTANTCONDITION)
+	while (1) {
+		if ((rc = efx_vpd_hunk_next(data, size, &dtag,
+		    &dkey, NULL, NULL, &dcont)) != 0)
+			goto fail2;
+		if (dcont == 0)
+			break;
+
+		scont = 0;
+		_NOTE(CONSTANTCONDITION)
+		while (1) {
+			if ((rc = efx_vpd_hunk_next(
+			    enp->en_u.siena.enu_svpd,
+			    enp->en_u.siena.enu_svpd_length, &stag, &skey,
+			    NULL, NULL, &scont)) != 0)
+				goto fail3;
+			if (scont == 0)
+				break;
+
+			if (stag == dtag && skey == dkey) {
+				rc = EEXIST;
+				goto fail4;
+			}
+		}
+	}
+
+done:
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_vpd_reinit(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	boolean_t wantpid;
+	int rc;
+
+	/*
+	 * Only create a PID if the dynamic cfg doesn't have one
+	 */
+	if (enp->en_u.siena.enu_svpd_length == 0)
+		wantpid = B_TRUE;
+	else {
+		unsigned int offset;
+		uint8_t length;
+
+		rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
+				    enp->en_u.siena.enu_svpd_length,
+				    EFX_VPD_ID, 0, &offset, &length);
+		if (rc == 0)
+			wantpid = B_FALSE;
+		else if (rc == ENOENT)
+			wantpid = B_TRUE;
+		else
+			goto fail1;
+	}
+
+	if ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_vpd_get(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__inout			efx_vpd_value_t *evvp)
+{
+	unsigned int offset;
+	uint8_t length;
+	int rc;
+
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	/* Attempt to satisfy the request from svpd first */
+	if (enp->en_u.siena.enu_svpd_length > 0) {
+		if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
+		    enp->en_u.siena.enu_svpd_length, evvp->evv_tag,
+		    evvp->evv_keyword, &offset, &length)) == 0) {
+			evvp->evv_length = length;
+			memcpy(evvp->evv_value,
+			    enp->en_u.siena.enu_svpd + offset, length);
+			return (0);
+		} else if (rc != ENOENT)
+			goto fail1;
+	}
+
+	/* And then from the provided data buffer */
+	if ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag,
+	    evvp->evv_keyword, &offset, &length)) != 0)
+		goto fail2;
+
+	evvp->evv_length = length;
+	memcpy(evvp->evv_value, data + offset, length);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_vpd_set(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__in			efx_vpd_value_t *evvp)
+{
+	int rc;
+
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	/* If the provided (tag,keyword) exists in svpd, then it is readonly */
+	if (enp->en_u.siena.enu_svpd_length > 0) {
+		unsigned int offset;
+		uint8_t length;
+
+		if ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,
+		    enp->en_u.siena.enu_svpd_length, evvp->evv_tag,
+		    evvp->evv_keyword, &offset, &length)) == 0) {
+			rc = EACCES;
+			goto fail1;
+		}
+	}
+
+	if ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn		int
+siena_vpd_next(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size,
+	__out			efx_vpd_value_t *evvp,
+	__inout			unsigned int *contp)
+{
+	_NOTE(ARGUNUSED(enp, data, size, evvp, contp))
+
+	return (ENOTSUP);
+}
+
+	__checkReturn		int
+siena_vpd_write(
+	__in			efx_nic_t *enp,
+	__in_bcount(size)	caddr_t data,
+	__in			size_t size)
+{
+	efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
+	siena_mc_dynamic_config_hdr_t *dcfg;
+	unsigned int vpd_offset;
+	unsigned int dcfg_partn;
+	unsigned int hdr_length;
+	unsigned int pos;
+	uint8_t cksum;
+	size_t partn_size, dcfg_size;
+	size_t vpd_length;
+	int rc;
+
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	/* Determine total length of all tags */
+	if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)
+		goto fail1;
+
+	/* Lock dynamic config sector for write, and read structure only */
+	dcfg_partn = (emip->emi_port == 1)
+		? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
+		: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
+
+	if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &partn_size)) != 0)
+		goto fail2;
+
+	if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0)
+		goto fail2;
+
+	if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
+	    B_FALSE, &dcfg, &dcfg_size)) != 0)
+		goto fail3;
+
+	hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);
+
+	/* Allocated memory should have room for the new VPD */
+	if (hdr_length + vpd_length > dcfg_size) {
+		rc = ENOSPC;
+		goto fail3;
+	}
+
+	/* Copy in new vpd and update header */
+	vpd_offset = dcfg_size - vpd_length;
+	EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset, EFX_DWORD_0, vpd_offset);
+	memcpy((caddr_t)dcfg + vpd_offset, data, vpd_length);
+	EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_length,
+			    EFX_DWORD_0, vpd_length);
+
+	/* Update the checksum */
+	cksum = 0;
+	for (pos = 0; pos < hdr_length; pos++)
+		cksum += ((uint8_t *)dcfg)[pos];
+	dcfg->csum.eb_u8[0] -= cksum;
+
+	/* Erase and write the new sector */
+	if ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, partn_size)) != 0)
+		goto fail4;
+
+	/* Write out the new structure to nvram */
+	if ((rc = siena_nvram_partn_write(enp, dcfg_partn, 0, (caddr_t)dcfg,
+	    vpd_offset + vpd_length)) != 0)
+		goto fail5;
+
+	EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
+
+	siena_nvram_partn_unlock(enp, dcfg_partn);
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+
+	EFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);
+fail2:
+	EFSYS_PROBE(fail2);
+
+	siena_nvram_partn_unlock(enp, dcfg_partn);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+				void
+siena_vpd_fini(
+	__in			efx_nic_t *enp)
+{
+	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+	if (enp->en_u.siena.enu_svpd_length > 0) {
+		EFSYS_KMEM_FREE(enp->en_esip, enp->en_u.siena.enu_svpd_length,
+				enp->en_u.siena.enu_svpd);
+
+		enp->en_u.siena.enu_svpd = NULL;
+		enp->en_u.siena.enu_svpd_length = 0;
+	}
+}
+
+#endif	/* EFSYS_OPT_SIENA */
+
+#endif	/* EFSYS_OPT_VPD */
--- /dev/null	2013-08-22 18:57:36.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/txc43128.c	2013-08-22 18:57:36.013476356 -0400
@@ -0,0 +1,1035 @@
+/*
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "txc43128.h"
+#include "txc43128_impl.h"
+#include "xphy.h"
+
+#if EFSYS_OPT_PHY_TXC43128
+
+static	__checkReturn	int
+txc43128_bist_run(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int count;
+	int rc;
+
+	/* Set the BIST type */
+	EFX_POPULATE_WORD_1(word, BTYPE, TSDET_DECODE);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL,
+	    &word)) != 0)
+		goto fail1;
+
+	/* Enable BIST */
+	EFX_SET_WORD_FIELD(word, BSTEN, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL,
+	    &word)) != 0)
+		goto fail2;
+
+	/* Start BIST */
+	EFX_SET_WORD_FIELD(word, BSTRT, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL,
+	    &word)) != 0)
+		goto fail3;
+
+	EFX_SET_WORD_FIELD(word, BSTRT, 0);
+
+	/* Spin for 100 us */
+	EFSYS_SPIN(100);
+
+	/* Stop BIST */
+	EFX_SET_WORD_FIELD(word, BSTOP, 1);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL,
+	    &word)) != 0)
+		goto fail4;
+
+	/* Wait until BIST has stopped */
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 10 us */
+		EFSYS_SPIN(10);
+
+		/* Check whether the reset bit has cleared */
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    BCTL, &word)) != 0)
+			goto fail5;
+
+		if (EFX_WORD_FIELD(word, BSTOP) == 0)
+			goto done;
+
+	} while (++count < 20);
+
+	rc = ETIMEDOUT;
+	goto fail6;
+
+done:
+	/* Disable BIST */
+	EFX_ZERO_WORD(word);
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL,
+	    &word)) != 0)
+		goto fail7;
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+txc43128_bist_check(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* Check lane 0 frame count */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX0FRMCNT,
+	    &word)) != 0)
+		goto fail1;
+
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) == 0)
+		goto fail2;
+
+	/* Check lane 0 error count */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX0ERRCNT,
+	    &word)) != 0)
+		goto fail3;
+
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0)
+		goto fail4;
+
+	/* Check lane 1 frame count */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX1FRMCNT,
+	    &word)) != 0)
+		goto fail5;
+
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) == 0)
+		goto fail6;
+
+	/* Check lane 1 error count */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX1ERRCNT,
+	    &word)) != 0)
+		goto fail7;
+
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0)
+		goto fail8;
+
+	/* Check lane 2 frame count */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX2FRMCNT,
+	    &word)) != 0)
+		goto fail9;
+
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) == 0)
+		goto fail10;
+
+	/* Check lane 2 error count */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX2ERRCNT,
+	    &word)) != 0)
+		goto fail11;
+
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0)
+		goto fail12;
+
+	/* Check lane 3 frame count */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX3FRMCNT,
+	    &word)) != 0)
+		goto fail13;
+
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) == 0)
+		goto fail14;
+
+	/* Check lane 3 error count */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX3ERRCNT,
+	    &word)) != 0)
+		goto fail15;
+
+	if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0)
+		goto fail16;
+
+	return (0);
+
+fail16:
+	EFSYS_PROBE(fail16);
+fail15:
+	EFSYS_PROBE(fail15);
+fail14:
+	EFSYS_PROBE(fail14);
+fail13:
+	EFSYS_PROBE(fail13);
+fail12:
+	EFSYS_PROBE(fail12);
+fail11:
+	EFSYS_PROBE(fail11);
+fail10:
+	EFSYS_PROBE(fail10);
+fail9:
+	EFSYS_PROBE(fail9);
+fail8:
+	EFSYS_PROBE(fail8);
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+txc43128_bist(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* Set PMA into loopback */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, MNDBLCFG,
+	    &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, LNALPBK, 1);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, MNDBLCFG,
+	    &word)) != 0)
+		goto fail2;
+
+	/* Run BIST */
+	if ((rc = txc43128_bist_run(enp)) != 0)
+		goto fail3;
+
+	/* Check BIST */
+	if ((rc = txc43128_bist_check(enp)) != 0)
+		goto fail4;
+
+	/* Turn off loopback */
+	EFX_SET_WORD_FIELD(word, LNALPBK, 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, MNDBLCFG,
+	    &word)) != 0)
+		goto fail5;
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+txc43128_led_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* PIO11 allows us to control the red LED */
+
+	EFX_POPULATE_WORD_1(word, PIO11FNC, PIOFNC_GPIO_DECODE);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+	    PIOCFG, &word)) != 0)
+		goto fail1;
+
+	EFX_POPULATE_WORD_1(word, PIO11DIR, PIODIR_OUT_DECODE);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+	    PIODIR, &word)) != 0)
+		goto fail2;
+
+
+#if EFSYS_OPT_PHY_LED_CONTROL
+
+	switch (epp->ep_phy_led_mode) {
+	case EFX_PHY_LED_DEFAULT:
+	case EFX_PHY_LED_OFF:
+		EFX_POPULATE_WORD_1(word, PIO11OUT, 0);
+		break;
+
+	case EFX_PHY_LED_ON:
+		EFX_POPULATE_WORD_1(word, PIO11OUT, 1);
+		break;
+
+	default:
+		EFSYS_ASSERT(B_FALSE);
+		break;
+	}
+
+#else	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	EFX_POPULATE_WORD_1(word, PIO11OUT, 0);
+
+#endif	/* EFSYS_OPT_PHY_LED_CONTROL */
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+	    PIODO, &word)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+txc43128_preemphasis_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* XAUI settings */
+	EFX_POPULATE_WORD_2(word, TXPRE02, 0, TXPRE13, 0);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+	    ATXPRE0, &word)) != 0)
+		goto fail1;
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+	    ATXPRE1, &word)) != 0)
+		goto fail2;
+
+	/* Line settings */
+	EFX_POPULATE_WORD_2(word, TXPRE02, 2, TXPRE13, 2);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    ATXPRE0, &word)) != 0)
+		goto fail3;
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    ATXPRE1, &word)) != 0)
+		goto fail4;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn	int
+txc43128_amplitude_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	/* XAUI settings */
+	EFX_POPULATE_WORD_2(word, TXAMP02, 25, TXAMP13, 25);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+	    ATXAMP0, &word)) != 0)
+		goto fail1;
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+	    ATXAMP1, &word)) != 0)
+		goto fail2;
+
+	/* Line settings */
+	EFX_POPULATE_WORD_2(word, TXAMP02, 12, TXAMP13, 12);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    ATXAMP0, &word)) != 0)
+		goto fail3;
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
+	    ATXAMP1, &word)) != 0)
+		goto fail4;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_LOOPBACK
+static	__checkReturn	int
+txc43128_loopback_cfg(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS:
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+		    MNDBLCFG, &word)) != 0)
+			goto fail1;
+
+		EFX_SET_WORD_FIELD(word, PXS8BLPBK, 1);
+
+		if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD,
+		    MNDBLCFG, &word)) != 0)
+			goto fail2;
+
+		break;
+
+	case EFX_LOOPBACK_PCS:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PCS_MMD,
+		    B_TRUE)) != 0)
+			goto fail1;
+
+		break;
+
+	case EFX_LOOPBACK_PMA_PMD:
+		if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PMA_PMD_MMD,
+		    B_TRUE)) != 0)
+			goto fail1;
+
+		break;
+
+	default:
+		break;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_PHY_LOOPBACK */
+
+static	__checkReturn	int
+txc43128_logic_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int count;
+	int rc;
+
+	EFSYS_PROBE(logic_reset);
+
+	/* Set the reset bit in the global command register */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, GLCMD,
+	    &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, LMTSWRST, 1);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, GLCMD,
+	    &word)) != 0)
+		goto fail2;
+
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 10 us */
+		EFSYS_SPIN(10);
+
+		/* Check whether the reset bit has cleared */
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+		    GLCMD, &word)) != 0)
+			goto fail3;
+
+		if (EFX_WORD_FIELD(word, LMTSWRST) == 0)
+			goto done;
+
+	} while (++count < 1000);
+
+	rc = ETIMEDOUT;
+	goto fail4;
+
+done:
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+txc43128_reset(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	unsigned int count;
+	int rc;
+
+	/* Set the reset bit in the main control register */
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, MNCTL,
+	    &word)) != 0)
+		goto fail1;
+
+	EFX_SET_WORD_FIELD(word, MRST, 1);
+
+	if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, MNCTL,
+	    &word)) != 0)
+		goto fail2;
+
+	count = 0;
+	do {
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Spin for 10 us */
+		EFSYS_SPIN(10);
+
+		/* Check whether the reset bit has cleared */
+		if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+		    MNCTL, &word)) != 0)
+			goto fail3;
+
+		if (EFX_WORD_FIELD(word, MRST) == 0)
+			goto done;
+
+	} while (++count < 1000);
+
+	rc = ETIMEDOUT;
+	goto fail4;
+
+done:
+	/*
+	 * Despite the global reset having completed, we will still be unable
+	 * to get sensible values out of the 802.3ae registers for some
+	 * unknown time. 250 ms seems to cover it but this is empirically
+	 * determined.
+	 */
+	EFSYS_SLEEP(250000);
+
+	enp->en_reset_flags |= EFX_RESET_PHY;
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+txc43128_reconfigure(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_pkg_wait(enp, epp->ep_port, TXC43128_MMD_MASK)) != 0)
+		goto fail1;
+
+	if ((rc = txc43128_bist(enp)) != 0)
+		goto fail2;
+
+	if ((rc = txc43128_led_cfg(enp)) != 0)
+		goto fail3;
+
+	if ((rc = txc43128_preemphasis_cfg(enp)) != 0)
+		goto fail4;
+
+	if ((rc = txc43128_amplitude_cfg(enp)) != 0)
+		goto fail5;
+
+	EFSYS_ASSERT3U(epp->ep_adv_cap_mask, ==, TXC43128_ADV_CAP_MASK);
+
+#if EFSYS_OPT_LOOPBACK
+	if ((rc = txc43128_loopback_cfg(enp)) != 0)
+		goto fail6;
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+	if ((rc = txc43128_logic_reset(enp)) != 0)
+		goto fail7;
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+
+#if EFSYS_OPT_LOOPBACK
+fail6:
+	EFSYS_PROBE(fail6);
+#endif	/* EFSYS_OPT_LOOPBACK */
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+txc43128_verify(
+	__in		efx_nic_t *enp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_pkg_verify(enp, epp->ep_port, TXC43128_MMD_MASK)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+txc43128_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if (epp->ep_mac_type != EFX_MAC_FALCON_XMAC) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail2;
+
+	*upp = ((EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) &&
+	    ((EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) ||
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) ||
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) ||
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0)));
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+txc43128_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp)
+{
+	efx_port_t *epp = &(enp->en_port);
+	boolean_t up;
+	int rc;
+
+#if EFSYS_OPT_LOOPBACK
+	switch (epp->ep_loopback_type) {
+	case EFX_LOOPBACK_PHY_XS:
+		rc = xphy_mmd_fault(enp, epp->ep_port, &up);
+		if (rc != 0)
+			goto fail1;
+
+		*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+		goto done;
+
+	case EFX_LOOPBACK_PCS:
+		rc = xphy_mmd_check(enp, epp->ep_port, PHY_XS_MMD, &up);
+		if (rc != 0)
+			goto fail1;
+
+		*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+		goto done;
+
+	default:
+		break;
+	}
+#endif /* EFSYS_OPT_LOOPBACK */
+
+	if ((rc = xphy_mmd_check(enp, epp->ep_port, PCS_MMD, &up)) != 0)
+		goto fail1;
+
+	/* bug10934: Reset the controller if the PCS block is stuck down */
+	if (up)
+		epp->ep_txc43128.bug10934_count = 0;
+	else if (++(epp->ep_txc43128.bug10934_count) > 10) {
+		(void) txc43128_logic_reset(enp);
+		epp->ep_txc43128.bug10934_count = 0;
+	}
+
+	*modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
+
+#if EFSYS_OPT_LOOPBACK
+done:
+#endif
+	*fcntlp = epp->ep_fcntl;
+	*lp_cap_maskp = epp->ep_lp_cap_mask;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+txc43128_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip)
+{
+	efx_port_t *epp = &(enp->en_port);
+	int rc;
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD,
+	    ouip)) != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#if EFSYS_OPT_PHY_STATS
+
+#define	TXC43128_STAT_SET(_stat, _mask, _id, _val)			\
+	do {								\
+		(_mask) |= (1ULL << (_id));				\
+		(_stat)[_id] = (uint32_t)(_val);			\
+	_NOTE(CONSTANTCONDITION)					\
+	} while (B_FALSE)
+
+static	__checkReturn			int
+txc43128_pma_pmd_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_LINK_UP,
+	    (EFX_WORD_FIELD(word, PMA_PMD_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
+	    PMA_PMD_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_RX_FAULT) != 0) ? 1 : 0);
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PMA_PMD_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD, SIGDET,
+	    &word)) != 0)
+		goto fail3;
+
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_SIGNAL_A,
+	    (EFX_WORD_FIELD(word, RX0SIGDET) != 0));
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_SIGNAL_B,
+	    (EFX_WORD_FIELD(word, RX1SIGDET) != 0));
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_SIGNAL_C,
+	    (EFX_WORD_FIELD(word, RX2SIGDET) != 0));
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_SIGNAL_D,
+	    (EFX_WORD_FIELD(word, RX3SIGDET) != 0));
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+txc43128_pcs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PCS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
+	    PCS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_RX_FAULT) != 0) ? 1 : 0);
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PCS_TX_FAULT) != 0) ? 1 : 0);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+static	__checkReturn			int
+txc43128_phy_xs_stats_update(
+	__in				efx_nic_t *enp,
+	__inout				uint64_t *maskp,
+	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS1_REG, &word)) != 0)
+		goto fail1;
+
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_LINK_UP,
+	    (EFX_WORD_FIELD(word, PHY_XS_LINK_UP) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_STATUS2_REG, &word)) != 0)
+		goto fail2;
+
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_RX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_RX_FAULT) != 0) ? 1 : 0);
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_TX_FAULT,
+	    (EFX_WORD_FIELD(word, PHY_XS_TX_FAULT) != 0) ? 1 : 0);
+
+	if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
+	    PHY_XS_LANE_STATUS_REG, &word)) != 0)
+		goto fail3;
+
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_ALIGN,
+	    (EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) ? 1 : 0);
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_A,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) ? 1 : 0);
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_B,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) ? 1 : 0);
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_C,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) ? 1 : 0);
+	TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_D,
+	    (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0) ? 1 : 0);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn			int
+txc43128_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
+{
+	efx_port_t *epp = &(enp->en_port);
+	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+	uint64_t mask = 0;
+	uint32_t oui;
+	int rc;
+
+	_NOTE(ARGUNUSED(esmp))
+
+	if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, &oui)) != 0)
+		goto fail1;
+
+	TXC43128_STAT_SET(stat, mask, EFX_PHY_STAT_OUI, oui);
+
+	if ((rc = txc43128_pma_pmd_stats_update(enp, &mask, stat)) != 0)
+		goto fail2;
+
+	if ((rc = txc43128_pcs_stats_update(enp, &mask, stat)) != 0)
+		goto fail3;
+
+	if ((rc = txc43128_phy_xs_stats_update(enp, &mask, stat)) != 0)
+		goto fail4;
+
+	/* Ensure all the supported statistics are up to date */
+	EFSYS_ASSERT(mask == encp->enc_phy_stat_mask);
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+		const char __cs *
+txc43128_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id)
+{
+	_NOTE(ARGUNUSED(enp, id))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (NULL);
+}
+#endif	/* EFSYS_OPT_NAMES */
+
+	__checkReturn	int
+txc43128_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp)
+{
+	_NOTE(ARGUNUSED(enp, id, flags, valp))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+
+	__checkReturn	int
+txc43128_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val)
+{
+	_NOTE(ARGUNUSED(enp, id, val))
+
+	EFSYS_ASSERT(B_FALSE);
+
+	return (ENOTSUP);
+}
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#endif	/* EFSYS_OPT_PHY_TXC43128 */
--- /dev/null	2013-08-22 18:57:36.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/txc43128.h	2013-08-22 18:57:36.111313543 -0400
@@ -0,0 +1,152 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_TXC43128_H
+#define	_SYS_TXC43128_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_TXC43128
+
+#define	TXC43128_LOOPBACK_MASK						\
+	    ((1 << EFX_LOOPBACK_PHY_XS) |				\
+	    (1 << EFX_LOOPBACK_PCS) |					\
+	    (1 << EFX_LOOPBACK_PMA_PMD) |				\
+	    FALCON_XMAC_LOOPBACK_MASK)
+
+#define	TXC43128_LED_MASK						\
+	    ((1 << EFX_PHY_LED_OFF) |					\
+	    (1 << EFX_PHY_LED_ON))
+
+#define	TXC43128_NPROPS		0
+
+#define	TXC43128_ADV_CAP_MASK						\
+	    ((1 << EFX_PHY_CAP_10000FDX) |				\
+	    (1 << EFX_PHY_CAP_PAUSE))
+
+#define	TXC43128_ADV_CAP_PERM	0
+
+#define	TXC43128_BIST_MASK	0
+
+extern	__checkReturn	int
+txc43128_reset(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+txc43128_reconfigure(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+txc43128_verify(
+	__in		efx_nic_t *enp);
+
+extern	__checkReturn	int
+txc43128_uplink_check(
+	__in		efx_nic_t *enp,
+	__out		boolean_t *upp);
+
+extern	__checkReturn	int
+txc43128_downlink_check(
+	__in		efx_nic_t *enp,
+	__out		efx_link_mode_t *modep,
+	__out		unsigned int *fcntlp,
+	__out		uint32_t *lp_cap_maskp);
+
+extern	__checkReturn	int
+txc43128_oui_get(
+	__in		efx_nic_t *enp,
+	__out		uint32_t *ouip);
+
+#if EFSYS_OPT_PHY_STATS
+
+/* START MKCONFIG GENERATED Txc43128PhyHeaderStatsMask 0bd778c521babfec */
+#define	TXC43128_STAT_MASK \
+	(1ULL << EFX_PHY_STAT_OUI) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_A) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_B) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_C) | \
+	(1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_D) | \
+	(1ULL << EFX_PHY_STAT_PCS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PCS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PCS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_LINK_UP) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_RX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_TX_FAULT) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_ALIGN) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_A) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_B) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_C) | \
+	(1ULL << EFX_PHY_STAT_PHY_XS_SYNC_D)
+
+/* END MKCONFIG GENERATED Txc43128PhyHeaderStatsMask */
+
+extern	__checkReturn			int
+txc43128_stats_update(
+	__in				efx_nic_t *enp,
+	__in				efsys_mem_t *esmp,
+	__out_ecount(EFX_PHY_NSTATS)	uint32_t *stat);
+
+#endif	/* EFSYS_OPT_PHY_STATS */
+
+#if EFSYS_OPT_PHY_PROPS
+
+#if EFSYS_OPT_NAMES
+
+extern		const char __cs *
+txc43128_prop_name(
+	__in	efx_nic_t *enp,
+	__in	unsigned int id);
+
+#endif
+
+extern	__checkReturn	int
+txc43128_prop_get(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t flags,
+	__out		uint32_t *valp);
+
+extern	__checkReturn	int
+txc43128_prop_set(
+	__in		efx_nic_t *enp,
+	__in		unsigned int id,
+	__in		uint32_t val);
+
+#endif	/* EFSYS_OPT_PHY_PROPS */
+
+#endif	/* EFSYS_OPT_PHY_TXC43128 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_TXC43128_H */
--- /dev/null	2013-08-22 18:57:36.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/txc43128_impl.h	2013-08-22 18:57:36.198337735 -0400
@@ -0,0 +1,172 @@
+/*-
+ * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_TXC43128_IMPL_H
+#define	_SYS_TXC43128_IMPL_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if EFSYS_OPT_PHY_TXC43128
+
+#define	TXC43128_MMD_MASK						\
+	((1 << PMA_PMD_MMD) |						\
+	(1 << PCS_MMD) |						\
+	(1 << PHY_XS_MMD))
+
+#define	SIGDET	0x000a
+#define	RX0SIGDET_LBN 1
+#define	RX0SIGDET_WIDTH 1
+#define	RX1SIGDET_LBN 2
+#define	RX1SIGDET_WIDTH 1
+#define	RX2SIGDET_LBN 3
+#define	RX2SIGDET_WIDTH 1
+#define	RX3SIGDET_LBN 4
+#define	RX3SIGDET_WIDTH 1
+
+#define	GLCMD 0xc004
+#define	LMTSWRST_LBN 14
+#define	LMTSWRST_WIDTH 1
+
+#define	ATXPRE0 0xc043
+#define	ATXPRE1 0xc044
+#define	TXPRE02_LBN 3
+#define	TXPRE02_WIDTH 5
+#define	TXPRE13_LBN 11
+#define	TXPRE13_WIDTH 5
+
+#define	ATXAMP0 0xc041
+#define	ATXAMP1 0xc042
+#define	TXAMP02_LBN 3
+#define	TXAMP02_WIDTH 5
+#define	TXAMP13_LBN 11
+#define	TXAMP13_WIDTH 5
+
+#define	BCTL 0xc280
+#define	BSTRT_LBN 15
+#define	BSTRT_WIDTH 1
+#define	BSTOP_LBN 14
+#define	BSTOP_WIDTH 1
+#define	BSTEN_LBN 13
+#define	BSTEN_WIDTH 1
+#define	B10EN_LBN 12
+#define	B10EN_WIDTH 1
+#define	BTYPE_LBN 10
+#define	BTYPE_WIDTH 2
+#define	TSDET_DECODE 0
+#define	CRPAT_DECODE 1
+#define	CJPAT_DECODE 2
+#define	TSRND_DECODE 3
+
+#define	BTXFRMCNT 0xc281
+#define	BRX0FRMCNT 0xc282
+#define	BRX1FRMCNT 0xc283
+#define	BRX2FRMCNT 0xc284
+#define	BRX3FRMCNT 0xc285
+#define	BRX0ERRCNT 0xc286
+#define	BRX1ERRCNT 0xc287
+#define	BRX2ERRCNT 0xc288
+#define	BRX3ERRCNT 0xc289
+
+#define	MNCTL 0xc340
+#define	MRST_LBN 15
+#define	MRST_WIDTH 1
+#define	ALG2TXALED_LBN 14
+#define	ALG2TXALED_WIDTH 1
+#define	ALG2RXALED_LBN 13
+#define	ALG2RXALED_WIDTH 1
+
+#define	PIOCFG 0xc345
+#define	PIO15FNC_LBN 15
+#define	PIO15FNC_WIDTH 1
+#define	PIO14FNC_LBN 14
+#define	PIO14FNC_WIDTH 1
+#define	PIO13FNC_LBN 13
+#define	PIO13FNC_WIDTH 1
+#define	PIO12FNC_LBN 12
+#define	PIO12FNC_WIDTH 1
+#define	PIO11FNC_LBN 11
+#define	PIO11FNC_WIDTH 1
+#define	PIO10FNC_LBN 10
+#define	PIO10FNC_WIDTH 1
+#define	PIO9FNC_LBN 9
+#define	PIO9FNC_WIDTH 1
+#define	PIO8FNC_LBN 8
+#define	PIO8FNC_WIDTH 1
+#define	PIOFNC_LED_DECODE 0
+#define	PIOFNC_GPIO_DECODE 1
+
+#define	PIODO 0xc346
+#define	PIO15OUT_LBN 15
+#define	PIO15OUT_WIDTH 1
+#define	PIO14OUT_LBN 14
+#define	PIO14OUT_WIDTH 1
+#define	PIO13OUT_LBN 13
+#define	PIO13OUT_WIDTH 1
+#define	PIO12OUT_LBN 12
+#define	PIO12OUT_WIDTH 1
+#define	PIO11OUT_LBN 11
+#define	PIO11OUT_WIDTH 1
+#define	PIO10OUT_LBN 10
+#define	PIO10OUT_WIDTH 1
+#define	PIO9OUT_LBN 9
+#define	PIO9OUT_WIDTH 1
+#define	PIO8OUT_LBN 8
+#define	PIO8OUT_WIDTH 1
+
+#define	PIODIR 0xc348
+#define	PIO15DIR_LBN 15
+#define	PIO15DIR_WIDTH 1
+#define	PIO14DIR_LBN 14
+#define	PIO14DIR_WIDTH 1
+#define	PIO13DIR_LBN 13
+#define	PIO13DIR_WIDTH 1
+#define	PIO12DIR_LBN 12
+#define	PIO12DIR_WIDTH 1
+#define	PIO11DIR_LBN 11
+#define	PIO11DIR_WIDTH 1
+#define	PIO10DIR_LBN 10
+#define	PIO10DIR_WIDTH 1
+#define	PIO9DIR_LBN 9
+#define	PIO9DIR_WIDTH 1
+#define	PIO8DIR_LBN 8
+#define	PIO8DIR_WIDTH 1
+#define	PIODIR_IN_DECODE 0
+#define	PIODIR_OUT_DECODE 1
+
+#define	MNDBLCFG 0xc34f
+#define	PXS8BLPBK_LBN 11
+#define	PXS8BLPBK_WIDTH 1
+#define	LNALPBK_LBN 10
+#define	LNALPBK_WIDTH 1
+
+#endif	/* EFSYS_OPT_PHY_TXC43128 */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_TXC43128_IMPL_H */
--- /dev/null	2013-08-22 18:57:36.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/version.h	2013-08-22 18:57:36.283928416 -0400
@@ -0,0 +1,3 @@
+#ifndef CI_VERSION_STRING
+#define CI_VERSION_STRING "v3.2.4.6137-c"
+#endif
--- /dev/null	2013-08-22 18:57:36.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/xphy.c	2013-08-22 18:57:36.369557276 -0400
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2006-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "efsys.h"
+#include "efx.h"
+#include "efx_types.h"
+#include "efx_regs.h"
+#include "efx_impl.h"
+#include "xphy.h"
+
+#if EFSYS_OPT_FALCON
+
+static	__checkReturn	int
+xphy_mmd_reset_wait(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd)
+{
+	unsigned int count;
+	int rc;
+
+	/* The Clause 22 extenion MMD does not implement IEEE registers */
+	if (mmd == CL22EXT_MMD) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	count = 0;
+	do {
+		efx_word_t word;
+
+		EFSYS_PROBE1(wait, unsigned int, count);
+
+		/* Sleep for 100 ms */
+		EFSYS_SLEEP(100000);
+
+		/* Read control 1 register and check reset state */
+		if ((rc = falcon_mdio_read(enp, port, mmd,
+		    MMD_CONTROL1_REG, &word)) != 0)
+			goto fail2;
+
+		if (EFX_WORD_FIELD(word, MMD_RESET) == 0)
+			goto done;
+
+	} while (++count < 100);
+
+	rc = ETIMEDOUT;
+	goto fail3;
+
+done:
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+xphy_pkg_wait(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint32_t mask)
+{
+	uint8_t mmd;
+	int rc;
+
+	for (mmd = 0; mmd <= MAXMMD; mmd++) {
+		/* Only check MMDs in the mask */
+		if (((1 << mmd) & mask) == 0)
+			continue;
+
+		/*
+		 * The Clause 22 extenion MMD does not implement IEEE
+		 * registers.
+		 */
+		if (mmd == CL22EXT_MMD)
+			continue;
+
+		/* Wait for the MMD to come out of reset */
+		if ((rc = xphy_mmd_reset_wait(enp, port, mmd)) != 0)
+			goto fail1;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+xphy_pkg_verify(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint32_t mask)
+{
+	uint8_t mmd;
+	efx_word_t word;
+	int rc;
+
+	/* Find the first MMD */
+	for (mmd = 0; mmd <= MAXMMD; mmd++) {
+		uint32_t devices;
+
+		if (((1 << mmd) & mask) == 0)
+			continue;
+
+		/*
+		 * The Clause 22 extenion MMD does not implement IEEE
+		 * registers.
+		 */
+		if (mmd == CL22EXT_MMD)
+			continue;
+
+		if ((rc = falcon_mdio_read(enp, port, mmd,
+		    MMD_DEVICES2_REG, &word)) != 0)
+			goto fail1;
+
+		devices = (uint32_t)EFX_WORD_FIELD(word, EFX_WORD_0) << 16;
+
+		if ((rc = falcon_mdio_read(enp, port, mmd,
+		    MMD_DEVICES1_REG, &word)) != 0)
+			goto fail2;
+
+		devices |= (uint32_t)EFX_WORD_FIELD(word, EFX_WORD_0);
+
+		EFSYS_PROBE1(devices, uint32_t, devices);
+
+		/* Check that all the specified MMDs are present */
+		if ((devices & mask) != mask) {
+			rc = EFAULT;
+			goto fail3;
+		}
+
+		goto done;
+	}
+
+	rc = ENODEV;
+	goto fail4;
+
+done:
+	for (mmd = 0; mmd <= MAXMMD; mmd++) {
+		/* Only check MMDs in the mask */
+		if (((1 << mmd) & mask) == 0)
+			continue;
+
+		/*
+		 * The Clause 22 extenion MMD does not implement IEEE
+		 * registers.
+		 */
+		if (mmd == CL22EXT_MMD)
+			continue;
+
+		/* Check the MMD is responding */
+		if ((rc = falcon_mdio_read(enp, port, mmd,
+		    MMD_STATUS2_REG, &word)) != 0)
+			goto fail5;
+
+		if (EFX_WORD_FIELD(word, MMD_RESPONDING) !=
+		    MMD_RESPONDING_DECODE)
+			goto fail6;
+
+	}
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+xphy_mmd_oui_get(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__out		uint32_t *ouip)
+{
+	efx_word_t word;
+	int rc;
+
+	/* The Clause 22 extenion MMD does not implement IEEE registers */
+	if (mmd == CL22EXT_MMD) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = falcon_mdio_read(enp, port, mmd, MMD_IDH_REG,
+	    &word)) != 0)
+		goto fail2;
+
+	*ouip = (uint32_t)EFX_WORD_FIELD(word, MMD_IDH) << 16;
+
+	if ((rc = falcon_mdio_read(enp, port, mmd, MMD_IDL_REG,
+	    &word)) != 0)
+		goto fail3;
+
+	*ouip |= (uint32_t)EFX_WORD_FIELD(word, MMD_IDL) & 0x0000ffff;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+xphy_mmd_check(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__out		boolean_t *upp)
+{
+	efx_word_t word;
+	int rc;
+
+	/* Reset the latched status and fault flags */
+	if ((rc = falcon_mdio_read(enp, port, mmd, MMD_STATUS1_REG,
+	    &word)) != 0)
+		goto fail1;
+
+	if (mmd == PMA_PMD_MMD || mmd == PCS_MMD || mmd == PHY_XS_MMD) {
+		if ((rc = falcon_mdio_read(enp, port, mmd,
+		    MMD_STATUS2_REG, &word)) != 0)
+			goto fail2;
+	}
+
+	/* Check the current status and fault flags */
+	if ((rc = falcon_mdio_read(enp, port, mmd, MMD_STATUS1_REG,
+	    &word)) != 0)
+		goto fail3;
+
+	*upp = (EFX_WORD_FIELD(word, MMD_LINK_UP) != 0 &&
+		EFX_WORD_FIELD(word, MMD_FAULT) == 0);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+xphy_mmd_fault(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__out		boolean_t *upp)
+{
+	efx_word_t word;
+	int rc;
+
+	if ((rc = falcon_mdio_read(enp, port, PHY_XS_MMD,
+	    MMD_STATUS2_REG, &word)) != 0)
+		goto fail1;
+
+	*upp = (EFX_WORD_FIELD(word, MMD_RX_FAULT) == 0);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+	__checkReturn	int
+xphy_mmd_loopback_set(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__in		boolean_t on)
+{
+	efx_word_t word;
+	int rc;
+
+	/* The Clause 22 extenion MMD does not implement IEEE registers */
+	if (mmd == CL22EXT_MMD) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((rc = falcon_mdio_read(enp, port, mmd, MMD_CONTROL1_REG,
+	    &word)) != 0)
+		goto fail2;
+
+	if (mmd == PMA_PMD_MMD)
+		EFX_SET_WORD_FIELD(word, MMD_PMA_LOOPBACK, (on) ? 1 : 0);
+	else
+		EFX_SET_WORD_FIELD(word, MMD_LOOPBACK, (on) ? 1 : 0);
+
+	if ((rc = falcon_mdio_write(enp, port, mmd, MMD_CONTROL1_REG,
+	    &word)) != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, int, rc);
+
+	return (rc);
+}
+
+#endif	/* EFSYS_OPT_FALCON */
--- /dev/null	2013-08-22 18:57:36.000000000 -0400
+++ new/usr/src/uts/common/io/sfxge/xphy.h	2013-08-22 18:57:36.457675510 -0400
@@ -0,0 +1,500 @@
+/*-
+ * Copyright 2006-2013 Solarflare Communications Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_XPHY_H
+#define	_SYS_XPHY_H
+
+#include "efx.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Common
+ */
+
+/* control register 1 */
+#define	MMD_CONTROL1_REG 0x00
+#define	MMD_PMA_LOOPBACK_LBN 0
+#define	MMD_PMA_LOOPBACK_WIDTH 1
+#define	MMD_LOOPBACK_LBN 14
+#define	MMD_LOOPBACK_WIDTH 1
+#define	MMD_RESET_LBN 15
+#define	MMD_RESET_WIDTH 1
+
+/* status register 1 */
+#define	MMD_STATUS1_REG 0x01
+#define	MMD_LINK_UP_LBN 2
+#define	MMD_LINK_UP_WIDTH 1
+#define	MMD_FAULT_LBN 7
+#define	MMD_FAULT_WIDTH 1
+
+/* identifier registers */
+#define	MMD_IDH_REG 0x02
+#define	MMD_IDH_LBN 0
+#define	MMD_IDH_WIDTH 16
+
+#define	MMD_IDL_REG 0x03
+#define	MMD_IDL_LBN 0
+#define	MMD_IDL_WIDTH 16
+
+/* devices in package registers */
+#define	MMD_DEVICES1_REG 0x05
+#define	PMA_PMD_PRESENT_LBN 1
+#define	PMA_PMD_PRESENT_WIDTH 1
+#define	WIS_PRESENT_LBN 2
+#define	WIS_PRESENT_WIDTH 1
+#define	PCS_PRESENT_LBN 3
+#define	PCS_PRESENT_WIDTH 1
+#define	PHY_XS_PRESENT_LBN 4
+#define	PHY_XS_PRESENT_WIDTH 1
+#define	DTE_XS_PRESENT_LBN 5
+#define	DTE_XS_PRESENT_WIDTH 1
+#define	TC_PRESENT_LBN 6
+#define	TC_PRESENT_WIDTH 1
+#define	AN_PRESENT_LBN 7
+#define	AN_PRESENT_WIDTH 1
+
+#define	MMD_DEVICES2_REG 0x06
+#define	CL22EXT_PRESENT_LBN 13
+#define	CL22EXT_PRESENT_WIDTH 1
+#define	VENDOR_DEVICE1_PRESENT_LBN 14
+#define	VENDOR_DEVICE1_PRESENT_WIDTH 1
+#define	VENDOR_DEVICE2_PRESENT_LBN 15
+#define	VENDOR_DEVICE2_PRESENT_WIDTH 1
+
+#define	MMD_STATUS2_REG 0x08
+#define	MMD_RX_FAULT_LBN 10
+#define	MMD_RX_FAULT_WIDTH 1
+#define	MMD_TX_FAULT_LBN 11
+#define	MMD_TX_FAULT_WIDTH 1
+#define	MMD_RESPONDING_LBN 14
+#define	MMD_RESPONDING_WIDTH 2
+#define	MMD_RESPONDING_DECODE 0x2	/* 10 */
+
+/*
+ * PMA/PMD
+ */
+
+/* control register 1 */
+#define	PMA_PMD_CONTROL1_REG 0x00
+#define	PMA_PMD_LOOPBACK_EN_LBN 0
+#define	PMA_PMD_LOOPBACK_EN_WIDTH 1
+#define	PMA_PMD_LOW_POWER_EN_LBN 11
+#define	PMA_PMD_LOW_POWER_EN_WIDTH 1
+#define	PMA_PMD_RESET_LBN 15
+#define	PMA_PMD_RESET_WIDTH 1
+
+/* status register 1 */
+#define	PMA_PMD_STATUS1_REG 0x01
+#define	PMA_PMD_POWER_CAP_LBN 1
+#define	PMA_PMD_POWER_CAP_WIDTH 1
+#define	PMA_PMD_LINK_UP_LBN 2
+#define	PMA_PMD_LINK_UP_WIDTH 1
+#define	PMA_PMD_FAULT_LBN 7
+#define	PMA_PMD_FAULT_WIDTH 1
+
+/* control register 2 */
+#define	PMA_PMD_CONTROL2_REG 0x07
+#define	PMA_PMD_TYPE_LBN 0
+#define	PMA_PMD_TYPE_WIDTH 4
+#define	PMA_PMD_10BASE_T_DECODE 0xf	/* 1111 */
+#define	PMA_PMD_100BASE_TX_DECODE 0xe	/* 1110 */
+#define	PMA_PMD_1000BASE_KX_DECODE 0xd	/* 1101 */
+#define	PMA_PMD_1000BASE_T_DECODE 0xc	/* 1100 */
+#define	PMA_PMD_10GBASE_KR_DECODE 0xb	/* 1011 */
+#define	PMA_PMD_10GBASE_KX4_DECODE 0xa	/* 1010 */
+#define	PMA_PMD_10GBASE_T_DECODE 0x9	/* 1001 */
+#define	PMA_PMD_10GBASE_LRM_DECODE 0x8	/* 1001 */
+#define	PMA_PMD_10GBASE_SR_DECODE 0x7	/* 0111 */
+#define	PMA_PMD_10GBASE_LR_DECODE 0x6	/* 0110 */
+#define	PMA_PMD_10GBASE_ER_DECODE 0x5	/* 0101 */
+#define	PMA_PMD_10GBASE_SW_DECODE 0x3	/* 0011 */
+#define	PMA_PMD_10GBASE_LW_DECODE 0x2	/* 0010 */
+#define	PMA_PMD_10GBASE_EW_DECODE 0x1	/* 0001 */
+
+/* status register 2 */
+#define	PMA_PMD_STATUS2_REG 0x08
+#define	PMA_PMD_LOOPBACK_CAP_LBN 0
+#define	PMA_PMD_LOOPBACK_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_EW_CAP_LBN 1
+#define	PMA_PMD_10GBASE_EW_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_LW_CAP_LBN 2
+#define	PMA_PMD_10GBASE_LW_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_SW_CAP_LBN 3
+#define	PMA_PMD_10GBASE_SW_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_ER_CAP_LBN 5
+#define	PMA_PMD_10GBASE_ER_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_LR_CAP_LBN 6
+#define	PMA_PMD_10GBASE_LR_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_SR_CAP_LBN 7
+#define	PMA_PMD_10GBASE_SR_CAP_WIDTH 1
+#define	PMA_PMD_TX_DISABLE_CAP_LBN 8
+#define	PMA_PMD_TX_DISABLE_CAP_WIDTH 1
+#define	PMA_PMD_EXT_CAP_LBN 9
+#define	PMA_PMD_EXT_CAP_WIDTH 1
+#define	PMA_PMD_RX_FAULT_LBN 10
+#define	PMA_PMD_RX_FAULT_WIDTH 1
+#define	PMA_PMD_TX_FAULT_LBN 11
+#define	PMA_PMD_TX_FAULT_WIDTH 1
+#define	PMA_PMD_RX_FAULT_CAP_LBN 12
+#define	PMA_PMD_RX_FAULT_CAP_WIDTH 1
+#define	PMA_PMD_TX_FAULT_CAP_LBN 13
+#define	PMA_PMD_TX_FAULT_CAP_WIDTH 1
+#define	PMA_PMD_RESPONDING_LBN 14
+#define	PMA_PMD_RESPONDING_WIDTH 2
+#define	PMA_PMD_RESPONDING_DECODE 0x2	/* 10 */
+
+/* extended capabilities register */
+#define	PMA_PMD_EXT_CAP_REG 0x0b
+#define	PMA_PMD_10GBASE_CX4_CAP_LBN 0
+#define	PMA_PMD_10GBASE_CX4_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_LRM_CAP_LBN 1
+#define	PMA_PMD_10GBASE_LRM_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_T_CAP_LBN 2
+#define	PMA_PMD_10GBASE_T_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_KX4_CAP_LBN 3
+#define	PMA_PMD_10GBASE_KX4_CAP_WIDTH 1
+#define	PMA_PMD_10GBASE_KR_CAP_LBN 4
+#define	PMA_PMD_10GBASE_KR_CAP_WIDTH 1
+#define	PMA_PMD_1000BASE_T_CAP_LBN 5
+#define	PMA_PMD_1000BASE_T_CAP_WIDTH 1
+#define	PMA_PMD_1000BASE_KX_CAP_LBN 6
+#define	PMA_PMD_1000BASE_KX_CAP_WIDTH 1
+#define	PMA_PMD_100BASE_TX_CAP_LBN 7
+#define	PMA_PMD_100BASE_TX_CAP_WIDTH 1
+#define	PMA_PMD_10BASE_T_CAP_LBN 8
+#define	PMA_PMD_10BASE_T_CAP_WIDTH 1
+
+/* channel A-D signal/noise ratio registers */
+#define	PMA_PMD_CHANNELA_SNR_REG 0x85
+#define	PMA_PMD_CHANNELB_SNR_REG 0x86
+#define	PMA_PMD_CHANNELC_SNR_REG 0x87
+#define	PMA_PMD_CHANNELD_SNR_REG 0x88
+#define	PMA_PMD_CHANNELA_MIN_SNR_REG 0x89
+#define	PMA_PMD_CHANNELB_MIN_SNR_REG 0x8a
+#define	PMA_PMD_CHANNELC_MIN_SNR_REG 0x8b
+#define	PMA_PMD_CHANNELD_MIN_SNR_REG 0x8c
+#define	PMA_PMD_SNR_LBN 0
+#define	PMA_PMD_SNR_WIDTH 16
+
+/* LASI control register */
+#define	PMA_PMD_LASI_CONTROL_REG 0x9002
+#define	PMA_PMD_LS_ALARM_EN_LBN 0
+#define	PMA_PMD_LS_ALARM_EN_WIDTH 1
+#define	PMA_PMD_TX_ALARM_EN_LBN 1
+#define	PMA_PMD_TX_ALARM_EN_WIDTH 1
+#define	PMA_PMD_RX_ALARM_EN_LBN 2
+#define	PMA_PMD_RX_ALARM_EN_WIDTH 1
+
+/* LASI status register */
+#define	PMA_PMD_LASI_STATUS_REG 0x9005
+#define	PMA_PMD_LS_ALARM_LBN 0
+#define	PMA_PMD_LS_ALARM_WIDTH 1
+#define	PMA_PMD_TX_ALARM_LBN 1
+#define	PMA_PMD_TX_ALARM_WIDTH 1
+#define	PMA_PMD_RX_ALARM_LBN 2
+#define	PMA_PMD_RX_ALARM_WIDTH 1
+
+/*
+ * PCS
+ */
+
+/* control register 1 */
+#define	PCS_CONTROL1_REG 0x00
+#define	PCS_LOW_POWER_EN_LBN 11
+#define	PCS_LOW_POWER_EN_WIDTH 1
+#define	PCS_LOOPBACK_EN_LBN 14
+#define	PCS_LOOPBACK_EN_WIDTH 1
+#define	PCS_RESET_LBN 15
+#define	PCS_RESET_WIDTH 1
+
+/* status register 1 */
+#define	PCS_STATUS1_REG 0x01
+#define	PCS_POWER_CAP_LBN 1
+#define	PCS_POWER_CAP_WIDTH 1
+#define	PCS_LINK_UP_LBN 2
+#define	PCS_LINK_UP_WIDTH 1
+#define	PCS_FAULT_LBN 7
+#define	PCS_FAULT_WIDTH 1
+
+/* control register 2 */
+#define	PCS_CONTROL2_REG 0x07
+#define	PCS_TYPE_LBN 0
+#define	PCS_TYPE_WIDTH 2
+#define	PCS_10GBASE_T_DECODE 0x3	/* 11 */
+#define	PCS_10GBASE_W_DECODE 0x2	/* 10 */
+#define	PCS_10GBASE_X_DECODE 0x1	/* 01 */
+#define	PCS_10GBASE_R_DECODE 0x0	/* 00 */
+
+/* 10G status register 2 */
+#define	PCS_STATUS2_REG 0x08
+#define	PCS_10GBASE_R_CAP_LBN 0
+#define	PCS_10GBASE_R_CAP_WIDTH 1
+#define	PCS_10GBASE_X_CAP_LBN 1
+#define	PCS_10GBASE_X_CAP_WIDTH 1
+#define	PCS_10GBASE_W_CAP_LBN 2
+#define	PCS_10GBASE_W_CAP_WIDTH 1
+#define	PCS_10GBASE_T_CAP_LBN 3
+#define	PCS_10GBASE_T_CAP_WIDTH 1
+#define	PCS_RX_FAULT_LBN 10
+#define	PCS_RX_FAULT_WIDTH 1
+#define	PCS_TX_FAULT_LBN 11
+#define	PCS_TX_FAULT_WIDTH 1
+#define	PCS_RESPONDING_LBN 14
+#define	PCS_RESPONDING_WIDTH 2
+#define	PCS_RESPONDING_DECODE 0x2	/* 10 */
+
+/* 10G-BASE-T/R status register 2 */
+#define	PCS_10GBASE_T_STATUS2_REG 0x21
+#define	PCS_10GBASE_R_STATUS2_REG 0x21
+#define	PCS_ERR_LBN 0
+#define	PCS_ERR_WIDTH 7
+#define	PCS_BER_LBN 8
+#define	PCS_BER_WIDTH 6
+#define	PCS_HIGH_BER_LBN 14
+#define	PCS_HIGH_BER_WIDTH 1
+#define	PCS_BLOCK_LOCK_LBN 15
+#define	PCS_BLOCK_LOCK_WIDTH 1
+
+/*
+ * PHY_XS
+ */
+
+/* control register 1 */
+#define	PHY_XS_CONTROL1_REG 0x00
+#define	PHY_XS_LOW_POWER_EN_LBN 11
+#define	PHY_XS_LOW_POWER_EN_WIDTH 1
+#define	PHY_XS_LOOPBACK_EN_LBN 14
+#define	PHY_XS_LOOPBACK_EN_WIDTH 1
+#define	PHY_XS_RESET_LBN 15
+#define	PHY_XS_RESET_WIDTH 1
+
+/* status register 1 */
+#define	PHY_XS_STATUS1_REG 0x01
+#define	PHY_XS_POWER_CAP_LBN 1
+#define	PHY_XS_POWER_CAP_WIDTH 1
+#define	PHY_XS_LINK_UP_LBN 2
+#define	PHY_XS_LINK_UP_WIDTH 1
+#define	PHY_XS_FAULT_LBN 7
+#define	PHY_XS_FAULT_WIDTH 1
+
+/* no control register 2 */
+
+/* status register 2 */
+#define	PHY_XS_STATUS2_REG 0x08
+#define	PHY_XS_RX_FAULT_LBN 10
+#define	PHY_XS_RX_FAULT_WIDTH 1
+#define	PHY_XS_TX_FAULT_LBN 11
+#define	PHY_XS_TX_FAULT_WIDTH 1
+#define	PHY_XS_RESPONDING_LBN 14
+#define	PHY_XS_RESPONDING_WIDTH 2
+#define	PHY_XS_RESPONDING_DECODE 0x2	/* 10 */
+
+/* lane status register */
+#define	PHY_XS_LANE_STATUS_REG 0x18
+#define	PHY_XS_ALIGNED_LBN 12
+#define	PHY_XS_ALIGNED_WIDTH 1
+#define	PHY_XS_LANE0_SYNC_LBN 0
+#define	PHY_XS_LANE0_SYNC_WIDTH 1
+#define	PHY_XS_LANE1_SYNC_LBN 1
+#define	PHY_XS_LANE1_SYNC_WIDTH 1
+#define	PHY_XS_LANE2_SYNC_LBN 2
+#define	PHY_XS_LANE2_SYNC_WIDTH 1
+#define	PHY_XS_LANE3_SYNC_LBN 3
+#define	PHY_XS_LANE3_SYNC_WIDTH 1
+
+/*
+ * DTE_XS
+ */
+
+/* control register 1 */
+#define	DTE_XS_CONTROL1_REG 0x00
+#define	DTE_XS_LOW_POWER_EN_LBN 11
+#define	DTE_XS_LOW_POWER_EN_WIDTH 1
+#define	DTE_XS_LOOPBACK_EN_LBN 14
+#define	DTE_XS_LOOPBACK_EN_WIDTH 1
+#define	DTE_XS_RESET_LBN 15
+#define	DTE_XS_RESET_WIDTH 1
+
+/* status register 1 */
+#define	DTE_XS_STATUS1_REG 0x01
+#define	DTE_XS_POWER_CAP_LBN 1
+#define	DTE_XS_POWER_CAP_WIDTH 1
+#define	DTE_XS_LINK_UP_LBN 2
+#define	DTE_XS_LINK_UP_WIDTH 1
+#define	DTE_XS_FAULT_LBN 7
+#define	DTE_XS_FAULT_WIDTH 1
+
+/* no control register 2 */
+
+/* status register 2 */
+#define	DTE_XS_STATUS2_REG 0x08
+#define	DTE_XS_RX_FAULT_LBN 10
+#define	DTE_XS_RX_FAULT_WIDTH 1
+#define	DTE_XS_TX_FAULT_LBN 11
+#define	DTE_XS_TX_FAULT_WIDTH 1
+#define	DTE_XS_RESPONDING_LBN 14
+#define	DTE_XS_RESPONDING_WIDTH 2
+#define	DTE_XS_RESPONDING_DECODE 0x2	/* 10 */
+
+/* lane status register */
+#define	DTE_XS_LANE_STATUS_REG 0x18
+#define	DTE_XS_ALIGNED_LBN 12
+#define	DTE_XS_ALIGNED_WIDTH 1
+#define	DTE_XS_LANE0_SYNC_LBN 0
+#define	DTE_XS_LANE0_SYNC_WIDTH 1
+#define	DTE_XS_LANE1_SYNC_LBN 1
+#define	DTE_XS_LANE1_SYNC_WIDTH 1
+#define	DTE_XS_LANE2_SYNC_LBN 2
+#define	DTE_XS_LANE2_SYNC_WIDTH 1
+#define	DTE_XS_LANE3_SYNC_LBN 3
+#define	DTE_XS_LANE3_SYNC_WIDTH 1
+
+/*
+ * AN
+ */
+
+/* control register 1 */
+#define	AN_CONTROL1_REG	0x00
+#define	AN_RESTART_LBN 9
+#define	AN_RESTART_WIDTH 1
+#define	AN_ENABLE_LBN 12
+#define	AN_ENABLE_WIDTH 1
+#define	AN_RESET_LBN 15
+#define	AN_RESET_WIDTH 1
+
+/* status register 1 */
+#define	AN_STATUS1_REG 0x01
+#define	AN_LP_CAP_LBN 0
+#define	AN_LP_CAP_WIDTH 1
+#define	AN_LINK_UP_LBN 2
+#define	AN_LINK_UP_WIDTH 1
+#define	AN_FAULT_LBN 4
+#define	AN_FAULT_WIDTH 1
+#define	AN_COMPLETE_LBN 5
+#define	AN_COMPLETE_WIDTH 1
+#define	AN_PAGE_RCVD_LBN 6
+#define	AN_PAGE_RCVD_WIDTH 1
+#define	AN_XNP_CAP_LBN 7
+#define	AN_XNP_CAP_WIDTH 1
+
+/* advertised capabilities register */
+#define	AN_ADV_BP_CAP_REG 0x10
+#define	AN_ADV_TA_10BASE_T_LBN 5
+#define	AN_ADV_TA_10BASE_T_WIDTH 1
+#define	AN_ADV_TA_10BASE_T_FDX_LBN 6
+#define	AN_ADV_TA_10BASE_T_FDX_WIDTH 1
+#define	AN_ADV_TA_100BASE_TX_LBN 7
+#define	AN_ADV_TA_100BASE_TX_WIDTH 1
+#define	AN_ADV_TA_100BASE_TX_FDX_LBN 8
+#define	AN_ADV_TA_100BASE_TX_FDX_WIDTH 1
+#define	AN_ADV_TA_100BASE_T4_LBN 9
+#define	AN_ADV_TA_100BASE_T4_WIDTH 1
+#define	AN_ADV_TA_PAUSE_LBN 10
+#define	AN_ADV_TA_PAUSE_WIDTH 1
+#define	AN_ADV_TA_ASM_DIR_LBN 11
+#define	AN_ADV_TA_ASM_DIR_WIDTH 1
+
+/* link partner base page capabilities register */
+#define	AN_LP_BP_CAP_REG 0x13
+#define	AN_LP_TA_10BASE_T_LBN 5
+#define	AN_LP_TA_10BASE_T_WIDTH 1
+#define	AN_LP_TA_10BASE_T_FDX_LBN 6
+#define	AN_LP_TA_10BASE_T_FDX_WIDTH 1
+#define	AN_LP_TA_100BASE_TX_LBN 7
+#define	AN_LP_TA_100BASE_TX_WIDTH 1
+#define	AN_LP_TA_100BASE_TX_FDX_LBN 8
+#define	AN_LP_TA_100BASE_TX_FDX_WIDTH 1
+#define	AN_LP_TA_100BASE_T4_LBN 9
+#define	AN_LP_TA_100BASE_T4_WIDTH 1
+#define	AN_LP_TA_PAUSE_LBN 10
+#define	AN_LP_TA_PAUSE_WIDTH 1
+#define	AN_LP_TA_ASM_DIR_LBN 11
+#define	AN_LP_TA_ASM_DIR_WIDTH 1
+
+/* 10GBASE-T control register */
+#define	AN_10G_BASE_T_CONTROL_REG 0x20
+#define	AN_10G_BASE_T_ADV_LBN 12
+#define	AN_10G_BASE_T_ADV_WIDTH 1
+
+/* 10GBASE-T status register */
+#define	AN_10G_BASE_T_STATUS_REG 0x21
+#define	AN_10G_BASE_T_LP_LBN 11
+#define	AN_10G_BASE_T_LP_WIDTH 1
+#define	AN_CONFIG_FAULT_LBN 15
+#define	AN_CONFIG_FAULT_WIDTH 1
+#define	AN_MASTER_LBN 14
+#define	AN_MASTER_WIDTH 1
+#define	AN_LOCAL_RX_OK_LBN 13
+#define	AN_LOCAL_RX_OK_WIDTH 1
+#define	AN_REMOTE_RX_OK_LBN 12
+#define	AN_REMOTE_RX_OK_WIDTH 1
+
+extern	__checkReturn	int
+xphy_pkg_verify(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint32_t mask);
+
+extern	__checkReturn	int
+xphy_pkg_wait(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint32_t mask);
+
+extern	__checkReturn	int
+xphy_mmd_oui_get(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__out		uint32_t *ouip);
+
+extern	__checkReturn	int
+xphy_mmd_check(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__out		boolean_t *upp);
+
+extern	__checkReturn	int
+xphy_mmd_fault(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__out		boolean_t *upp);
+
+extern	__checkReturn	int
+xphy_mmd_loopback_set(
+	__in		efx_nic_t *enp,
+	__in		uint8_t port,
+	__in		uint8_t mmd,
+	__in		boolean_t on);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _SYS_XPHY_H */
--- old/usr/src/uts/intel/Makefile.intel.shared	2013-08-22 18:57:36.541061753 -0400
+++ new/usr/src/uts/intel/Makefile.intel.shared	2013-08-22 18:57:36.547136317 -0400
@@ -402,6 +402,7 @@
 DRV_KMODS	+= ipmi
 DRV_KMODS	+= iprb
 DRV_KMODS	+= ixgbe
+DRV_KMODS	+= sfxge
 DRV_KMODS	+= vr
 $(CLOSED_BUILD)CLOSED_DRV_KMODS	+= ixgb
 
--- /dev/null	2013-08-22 18:57:36.000000000 -0400
+++ new/usr/src/uts/intel/sfxge/Makefile	2013-08-22 18:57:36.739295986 -0400
@@ -0,0 +1,108 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# 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.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# uts/intel/sfxge/Makefile
+#
+#	This makefile drives the production of the sfxge
+#	network driver kernel module.
+#
+#	intel architecture dependent
+#
+
+#
+#	Paths to the base of the uts directory trees
+#
+UTSBASE = ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= sfxge
+OBJECTS		= $(SFXGE_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(SFXGE_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
+CONF_SRCDIR	= $(UTSBASE)/common/io/sfxge
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+CERRWARN	+= -_gcc=-Wno-parentheses
+CERRWARN	+= -_gcc=-Wno-switch
+CERRWARN	+= -_gcc=-Wno-uninitialized
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY) $(CONFMOD)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
+
+#
+# Driver depends on MAC and IP
+#
+LDFLAGS		+= -dy -N misc/mac -N drv/ip
+
+#
+# CFLAGS for Sol11-based target
+#
+CFLAGS	  += -D_USE_DESBALLOC
+CFLAGS    += -U_USE_XESBALLOC
+CFLAGS    += -U_USE_CPU_PHYSID
+CFLAGS	  += -U_USE_GLD_V2
+CFLAGS    += -D_USE_GLD_V3
+CFLAGS    += -D_USE_GLD_V3_SOL10
+CFLAGS    += -D_USE_GLD_V3_SOL11
+CFLAGS	  += -D_USE_MAC_PRIV_PROP
+CFLAGS    += -D_USE_GLD_V3_PROPS
+CFLAGS    += -U_USE_MTU_UPDATE
+CFLAGS    += -D_USE_NDD_PROPS
+
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
