--- /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 */
