Module Name:    src
Committed By:   pgoyette
Date:           Sat Jun 13 16:08:25 UTC 2009

Modified Files:
        src/share/man/man4: envsys.4
        src/share/man/man9: sysmon_envsys.9
        src/sys/dev/sysmon: sysmon_envsys.c sysmon_envsys_events.c
            sysmon_envsysvar.h sysmonvar.h
        src/sys/sys: envsys.h

Log Message:
Add capability to send sensor limit values to the driver so they can
be programmed into device registers.  This way we can let the hardware
help us out instead of having to always compare the value against each
limit.  (Driver updates for some sensors to take advantage of this
capability will be forthcoming.)


To generate a diff of this commit:
cvs rdiff -u -r1.42 -r1.43 src/share/man/man4/envsys.4
cvs rdiff -u -r1.24 -r1.25 src/share/man/man9/sysmon_envsys.9
cvs rdiff -u -r1.87 -r1.88 src/sys/dev/sysmon/sysmon_envsys.c
cvs rdiff -u -r1.66 -r1.67 src/sys/dev/sysmon/sysmon_envsys_events.c
cvs rdiff -u -r1.29 -r1.30 src/sys/dev/sysmon/sysmon_envsysvar.h
cvs rdiff -u -r1.27 -r1.28 src/sys/dev/sysmon/sysmonvar.h
cvs rdiff -u -r1.25 -r1.26 src/sys/sys/envsys.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man4/envsys.4
diff -u src/share/man/man4/envsys.4:1.42 src/share/man/man4/envsys.4:1.43
--- src/share/man/man4/envsys.4:1.42	Sun Mar 15 12:33:53 2009
+++ src/share/man/man4/envsys.4	Sat Jun 13 16:08:25 2009
@@ -1,4 +1,4 @@
-.\"	$NetBSD: envsys.4,v 1.42 2009/03/15 12:33:53 joerg Exp $
+.\"	$NetBSD: envsys.4,v 1.43 2009/06/13 16:08:25 pgoyette Exp $
 .\"
 .\" Copyright (c) 2007 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd November 13, 2007
+.Dd June 12, 2009
 .Dt ENVSYS 4
 .Os
 .Sh NAME
@@ -135,6 +135,12 @@
 		\&\*[Lt]string\&\*[Gt]Ampere hour\&\*[Lt]\&/string\&\*[Gt]
 		\&\*[Lt]key\&\*[Gt]want-percentage\&\*[Lt]\&/key\&\*[Gt]
 		\&\*[Lt]true\&/\&\*[Gt]
+		\&\*[Lt]key\&\*[Gt]warning-capacity\&\*[Lt]\&/key\&\*[Gt]
+		\&\*[Lt]integer\&\*[Gt]19234\&\*[Lt]\&/integer\&\*[Gt]
+		\&\*[Lt]key\&\*[Gt]warning-max\&\*[Lt]\&/key\&\*[Gt]
+		\&\*[Lt]integer\&\*[Gt]323150000\&\*[Lt]\&/integer\&\*[Gt]
+		\&\*[Lt]key\&\*[Gt]warning-min\&\*[Lt]\&/key\&\*[Gt]
+		\&\*[Lt]integer\&\*[Gt]298150000\&\*[Lt]\&/integer\&\*[Gt]
 	\&\*[Lt]\&/dict\&\*[Gt]
 	\&\*[Lt]dict\&\*[Gt]
 		\&\*[Lt]key\&\*[Gt]device-properties\&\*[Lt]\&/key\&\*[Gt]
@@ -184,19 +190,14 @@
 Current min value in the sensor.
 .It Fa monitoring-state-critical
 If true, the driver has enabled the flag to monitor a critical state.
-.It Fa monitoring-state-critical-over
-If true, the driver has enabled the flag to monitor a critical over state.
-.It Fa monitoring-state-critical-under
-If true, the driver has enabled the flag to monitor a critical under state.
+.It Fa monitoring-state-hw-range-limits
+If true, the driver has enabled the flag to monitor warning or critical
+limits.
 .It Fa monitoring-state-state-changed
 If true, the driver has enabled the flag to monitor for state changes in
 a drive or Battery state sensor.
-.It Fa monitoring-state-warning-over
-If true, the driver has enabled the flag to monitor a warning over state.
-.It Fa monitoring-state-warning-under
-If true, the driver has enabled the flag to monitor a warning under state.
 .It Fa monitoring-supported
-If true, critical capacity/max/min limits may be set by the
+If true, critical/warning capacity/max/min limits may be set by the
 .Dv ENVSYS_SETDICTIONARY
 .Xr ioctl 2 .
 .It Fa state
@@ -209,6 +210,21 @@
 and
 .Em cur-value
 are valid and a percentage may be computed from them.
+.It Fa warning-capacity
+Warning capacity set previously by the
+.Dv ENVSYS_SETDICTIONARY
+.Xr ioctl 2 .
+Only available on sensors with the
+.Em want-percentage
+object enabled.
+.It Fa warning-max
+Warning max limit set previously by the
+.Dv ENVSYS_SETDICTIONARY
+.Xr ioctl 2 .
+.It Fa warning-min
+Warning min limit set previously by the
+.Dv ENVSYS_SETDICTIONARY
+.Xr ioctl 2 .
 .El
 .It Dv ENVSYS_REMOVEPROPS Pq prop_dictionary_t
 .Pp
@@ -251,6 +267,12 @@
 	\&\*[Lt]integer\&\*[Gt]3400\&\*[Lt]\&/integer\&\*[Gt]
 	\&\*[Lt]key\&\*[Gt]critical-min\&\*[Lt]\&/key\&\*[Gt]
 	\&\*[Lt]integer\&\*[Gt]2800\&\*[Lt]\&/integer\&\*[Gt]
+	\&\*[Lt]key\&\*[Gt]warning-capacity\&\*[Lt]\&/key\&\*[Gt]
+	\&\*[Lt]integer\&\*[Gt]15\&\*[Lt]\&/integer\&\*[Gt]
+	\&\*[Lt]key\&\*[Gt]warning-max\&\*[Lt]\&/key\&\*[Gt]
+	\&\*[Lt]integer\&\*[Gt]3200\&\*[Lt]\&/integer\&\*[Gt]
+	\&\*[Lt]key\&\*[Gt]warning-min\&\*[Lt]\&/key\&\*[Gt]
+	\&\*[Lt]integer\&\*[Gt]2900\&\*[Lt]\&/integer\&\*[Gt]
 \&\*[Lt]\&/dict\&\*[Gt]
 .Ed
 .Pp
@@ -305,12 +327,12 @@
 If an unknown object was sent with the dictionary,
 .Er EINVAL
 will be returned, or if the sensor does not support changing
-rfact (voltage sensors) or critical/capacity limits,
+rfact (voltage sensors) or critical/warning/capacity limits,
 .Er ENOTSUP
 will be returned.
 .El
 .Sh NOTES
-When setting a critical max or min limit with the
+When setting a critical/warning max or min limit with the
 .Dv ENVSYS_SETDICTIONARY
 .Xr ioctl 2 ,
 the user must be aware that
@@ -320,7 +342,7 @@
 .Xr sysmon_envsys 9
 for more information.
 .Pp
-Also when setting a critical capacity limit, the formula to send a
+Also when setting a critical or warning capacity limit, the formula to send a
 proper value to
 .Xr sysmon_envsys 9
 is the following:

Index: src/share/man/man9/sysmon_envsys.9
diff -u src/share/man/man9/sysmon_envsys.9:1.24 src/share/man/man9/sysmon_envsys.9:1.25
--- src/share/man/man9/sysmon_envsys.9:1.24	Mon Jun  1 20:08:44 2009
+++ src/share/man/man9/sysmon_envsys.9	Sat Jun 13 16:08:25 2009
@@ -1,4 +1,4 @@
-.\"	$NetBSD: sysmon_envsys.9,v 1.24 2009/06/01 20:08:44 pgoyette Exp $
+.\"	$NetBSD: sysmon_envsys.9,v 1.25 2009/06/13 16:08:25 pgoyette Exp $
 .\"
 .\" Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd June 1, 2009
+.Dd June 13, 2009
 .Dt SYSMON_ENVSYS 9
 .Os
 .Sh NAME
@@ -104,6 +104,8 @@
 	uint64_t	sme_events_timeout;
 	void 		*sme_cookie;
 	void (*sme_refresh)(struct sysmon_envsys *, envsys_data_t *);
+	void (*sme_set_limits)(struct sysmon_envsys *, sysmon_envsys_lim_t *);
+	void (*sme_get_limits)(struct sysmon_envsys *, sysmon_envsys_lim_t *); 
 };
 .Ed
 .Pp
@@ -126,14 +128,10 @@
 If enabled, the
 .Ar sme_refresh
 function callback won't be used
-to refresh sensors data and the driver will use its own method.
-Hence
-.Ar sme_cookie
-won't be necessary either (OPTIONAL).
+to refresh sensors data and the driver will use its own method (OPTIONAL).
 .It Fa sme_events_timeout
-This is used to specify the default timeout value that will be used to
-check for critical events if any monitoring flag was set.
-The value is used as seconds (OPTIONAL).
+This is used to specify the default timeout value (in seconds) that will be
+used to check for critical events if any monitoring flag was set (OPTIONAL).
 .El
 .Pp
 If the driver wants to refresh sensors data via the
@@ -145,8 +143,11 @@
 Pointer to the device struct (also called
 .Dq softc ) .
 This may be used in the
-.Sy sme_refresh
-function callback.
+.Sy sme_refresh ,
+.Sy sme_get_limits ,
+or
+.Sy sme_set_limits
+function callbacks.
 .It Fa sme_refresh
 Pointer to a function that will be used to refresh sensor data in
 the device.
@@ -156,6 +157,19 @@
 .Em You don't have to refresh all sensors, only the sensor specified by the
 .Sy edata-\*[Gt]sensor
 .Em index .
+.It Fa sme_get_limits
+Pointer to a function that will be used to obtain from the driver the
+initial limits (or thresholds) used when monitoring a sensor's value.
+(See the
+.Sx SENSOR DETAILS
+section for more information.)
+.It Fa sme_set_limits
+Pointer to a function that alerts the device driver whenever monitoring
+limits (or thresholds) are updated by the user.
+Setting this function allows the device driver to reprogram hardware
+limits (if provided by the device), and gives the driver direct control
+over setting the sensor's state based on hardware status.
+XXXX
 .El
 .Pp
 Note that it's not necessary to refresh the sensors data before the
@@ -203,7 +217,7 @@
 This will be used to report its current state (on/off).
 .It SME_CLASS_BATTERY
 .Pp
-This class is for devices that want to act as an
+This class is for devices that want to act as a
 .Em Battery .
 The device writer must ensure that at least there are two sensors with
 units of
@@ -211,14 +225,14 @@
 and
 .Sy ENVSYS_BATTERY_CHARGE .
 .Pp
-These two sensors are used to ensure that the battery device won't
-never send a
+These two sensors are used to ensure that the battery device can
+send a
 .Em low-power
 event to the
 .Xr powerd 8
 daemon (if running) when all battery devices are in a critical state.
-The critical state means that a battery is not currently charging
-and its charge state is low or critical.
+(The critical state occurs when a battery is not currently charging
+and its charge state is low or critical).
 When the
 .Em low-power
 condition is met, an event is sent to the
@@ -241,7 +255,7 @@
 .Dv SME_CLASS_ACADAPTER
 or
 .Dv SME_CLASS_BATTERY
-class don't have the sensors required, the
+class device doesn't have the sensors required, the
 .Em low-power
 event will never be sent, and the graceful shutdown won't be possible.
 .Ss SENSOR DETAILS
@@ -301,10 +315,13 @@
 The monitoring event will be registered when this flag is
 .Dv true
 and one or more of the
-.Dv ENVSYS_FMONFOO
+.Dv ENVSYS_FMONxxx
 flags were set in the
 .Ar flags
 member.
+.Em NOTE
+.Em that limits (or thresholds) can be set at any time to enable
+.Em monitoring that the sensor's value remains within those limits.
 .It Fa desc
 Used to set the description string.
 .Em NOTE
@@ -445,11 +462,11 @@
 or
 .Ar ENVSYS_BATTERY_CAPACITY .
 .It ENVSYS_FMONNOTSUPP
-Disallows to set a critical limit via the
+Disallows setting of limits (or thresholds) via the
 .Dv ENVSYS_SETDICTIONARY
 .Xr ioctl 2 .
-This flag has not any effect for monitoring flags set in the driver and it's
-only meant to disable setting critical limits from userland.
+This flag has no effect on monitoring flags set in the driver and is
+only disables setting the limits from userland.
 .El
 .Pp
 .Em If the driver has to use any of the
@@ -464,10 +481,9 @@
 .Ar units
 is set to
 .Ar ENVSYS_DRIVE ,
-there are some predefined states that must be set (only one)
-to the
+the
 .Ar value_cur
-member:
+member must be set to one of the following predefined states:
 .Pp
 .Bl -tag -width "ENVSYS_DRIVE_POWERDOWNXX" -compact
 .It ENVSYS_DRIVE_EMPTY
@@ -505,10 +521,9 @@
 .Ar units
 is set to
 .Ar ENVSYS_BATTERY_CAPACITY ,
-there are some predefined capacity states that must be set (only one)
-to the
+the
 .Ar value_cur
-member:
+member must be set to one of the following predefined capacity states:
 .Pp
 .Bl -tag -width "ENVSYS_BATTERY_CAPACITY_CRITICAL" -compact
 .It ENVSYS_BATTERY_CAPACITY_NORMAL

Index: src/sys/dev/sysmon/sysmon_envsys.c
diff -u src/sys/dev/sysmon/sysmon_envsys.c:1.87 src/sys/dev/sysmon/sysmon_envsys.c:1.88
--- src/sys/dev/sysmon/sysmon_envsys.c:1.87	Mon Jun  8 00:55:35 2009
+++ src/sys/dev/sysmon/sysmon_envsys.c	Sat Jun 13 16:08:25 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysmon_envsys.c,v 1.87 2009/06/08 00:55:35 pgoyette Exp $	*/
+/*	$NetBSD: sysmon_envsys.c,v 1.88 2009/06/13 16:08:25 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008 Juan Romero Pardines.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.87 2009/06/08 00:55:35 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.88 2009/06/13 16:08:25 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -1633,6 +1633,76 @@
 			if (error)
 				break;
 		}
+
+#ifdef NOTYET
+		/*
+		 * Update limits from driver if they've been changed
+		 */
+		if ((edata->flags & ENVSYS_FLIMITS_CHANGED) == 0)
+			continue;
+
+		if (edata->upropset & PROP_DRVR_CRITMAX) {
+			error = sme_sensor_upint32(dict, "critical-max",
+						   edata->lim_critmax);
+			if (error)
+				break;
+			edata->upropset &= ~PROP_USER_CRITMAX;
+		} else if ((edata->upropset & PROP_USER_CRITMAX) == 0)
+			prop_dictionary_remove(dict, "critical-max");
+
+		if (edata->upropset & PROP_DRVR_WARNMAX) {
+			error = sme_sensor_upint32(dict, "warning-max",
+						   edata->lim_warnmax);
+			if (error)
+				break;
+			edata->upropset &= ~PROP_USER_WARNMAX;
+		} else if ((edata->upropset & PROP_USER_WARNMAX) == 0)
+			prop_dictionary_remove(dict, "warning-max");
+
+		if (edata->flags & ENVSYS_FPERCENT) {
+			if (edata->upropset & PROP_DRVR_BATTWARN) {
+				error = sme_sensor_upint32(dict,
+							   "warning-capacity",
+							   edata->lim_warnmin);
+				if (error)
+					break;
+				edata->upropset &= ~PROP_USER_BATTWARN;
+			} else if ((edata->upropset & PROP_USER_BATTWARN) == 0)
+				prop_dictionary_remove(dict,
+						       "warning-capacity");
+
+			if (edata->upropset & PROP_DRVR_BATTCAP) {
+				error = sme_sensor_upint32(dict,
+							   "critical-capacity",
+							   edata->lim_critmin);
+				if (error)
+					break;
+				edata->upropset &= ~PROP_USER_BATTCAP;
+			} else if ((edata->upropset & PROP_USER_BATTCAP) == 0)
+				prop_dictionary_remove(dict,
+						       "critical-capacity");
+		} else {
+			if (edata->upropset & PROP_DRVR_WARNMIN) {
+				error = sme_sensor_upint32(dict,
+							   "warning-min",
+							   edata->lim_warnmin);
+				if (error)
+					break;
+				edata->upropset &= ~PROP_USER_WARNMIN;
+			} else if ((edata->upropset & PROP_USER_WARNMIN) == 0)
+				prop_dictionary_remove(dict, "warning-min");
+
+			if (edata->upropset & PROP_DRVR_CRITMIN) {
+				error = sme_sensor_upint32(dict,
+							   "critical-min",
+							   edata->lim_critmin);
+				if (error)
+					break;
+				edata->upropset &= ~PROP_USER_CRITMIN;
+			} else if ((edata->upropset & PROP_USER_CRITMIN) == 0)
+				prop_dictionary_remove(dict, "critical-min");
+		}
+#endif
 	}
 
 	return error;
@@ -1653,8 +1723,7 @@
 	prop_dictionary_t dict, tdict = NULL;
 	prop_object_t obj, obj1, obj2, tobj = NULL;
 	uint64_t refresh_timo = 0;
-	int32_t critmax = 0, warnmax = 0, warnmin = 0, critmin = 0;
-	int props = 0;
+	sysmon_envsys_lim_t lims;
 	int i, error = 0;
 	const char *blah;
 	bool targetfound = false;
@@ -1718,6 +1787,8 @@
 		if (!prop_string_equals(obj1, obj))
 			continue;
 
+		lims.sel_flags = 0;
+
 		/*
 		 * Check if a new description operation was
 		 * requested by the user and set new description.
@@ -1796,8 +1867,8 @@
 				goto out;
 			}
 
-			critmin = prop_number_integer_value(obj2);
-			props |= PROP_BATTCAP;
+			lims.sel_critmin = prop_number_integer_value(obj2);
+			lims.sel_flags |= PROP_BATTCAP;
 		}
 
 		/* 
@@ -1812,8 +1883,8 @@
 				goto out;
 			}
 
-			warnmin = prop_number_integer_value(obj2);
-			props |= PROP_BATTWARN;
+			lims.sel_warnmin = prop_number_integer_value(obj2);
+			lims.sel_flags |= PROP_BATTWARN;
 		}
 
 		/* 
@@ -1829,8 +1900,8 @@
 				goto out;
 			}
 
-			critmax = prop_number_integer_value(obj2);
-			props |= PROP_CRITMAX;
+			lims.sel_critmax = prop_number_integer_value(obj2);
+			lims.sel_flags |= PROP_CRITMAX;
 		}
 
 		/* 
@@ -1846,8 +1917,8 @@
 				goto out;
 			}
 
-			warnmax = prop_number_integer_value(obj2);
-			props |= PROP_WARNMAX;
+			lims.sel_warnmax = prop_number_integer_value(obj2);
+			lims.sel_flags |= PROP_WARNMAX;
 		}
 
 		/* 
@@ -1863,8 +1934,8 @@
 				goto out;
 			}
 
-			critmin = prop_number_integer_value(obj2);
-			props |= PROP_CRITMIN;
+			lims.sel_critmin = prop_number_integer_value(obj2);
+			lims.sel_flags |= PROP_CRITMIN;
 		}
 
 		/* 
@@ -1880,16 +1951,12 @@
 				goto out;
 			}
 
-			warnmin = prop_number_integer_value(obj2);
-			props |= PROP_WARNMIN;
+			lims.sel_warnmin = prop_number_integer_value(obj2);
+			lims.sel_flags |= PROP_WARNMIN;
 		}
 
-		if (props) {
-			error = sme_event_register(dict,
-					      edata,
-					      sme,
-					      critmax, warnmax, warnmin,
-					      critmin, props,
+		if (lims.sel_flags) {
+			error = sme_event_register(dict, edata, sme, &lims,
 					      (edata->flags & ENVSYS_FPERCENT)?
 						PENVSYS_EVENT_CAPACITY:
 						PENVSYS_EVENT_LIMITS,
@@ -1900,7 +1967,7 @@
 				goto out;
 
 			mutex_enter(&sme->sme_mtx);
-			edata->upropset |= props;
+			edata->upropset |= lims.sel_flags;
 			mutex_exit(&sme->sme_mtx);
 		}
 

Index: src/sys/dev/sysmon/sysmon_envsys_events.c
diff -u src/sys/dev/sysmon/sysmon_envsys_events.c:1.66 src/sys/dev/sysmon/sysmon_envsys_events.c:1.67
--- src/sys/dev/sysmon/sysmon_envsys_events.c:1.66	Mon Jun  8 13:06:33 2009
+++ src/sys/dev/sysmon/sysmon_envsys_events.c	Sat Jun 13 16:08:25 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: sysmon_envsys_events.c,v 1.66 2009/06/08 13:06:33 pgoyette Exp $ */
+/* $NetBSD: sysmon_envsys_events.c,v 1.67 2009/06/13 16:08:25 pgoyette Exp $ */
 
 /*-
  * Copyright (c) 2007, 2008 Juan Romero Pardines.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.66 2009/06/08 13:06:33 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.67 2009/06/13 16:08:25 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -82,9 +82,8 @@
  */
 int
 sme_event_register(prop_dictionary_t sdict, envsys_data_t *edata,
-		   struct sysmon_envsys *sme, int32_t critmax,
-		   int32_t warnmax, int32_t warnmin, int32_t critmin,
-		   int lim_flags, int crittype, int powertype)
+		   struct sysmon_envsys *sme, sysmon_envsys_lim_t *lims,
+		   int crittype, int powertype)
 {
 	sme_event_t *see = NULL, *osee = NULL;
 	prop_object_t obj;
@@ -108,36 +107,36 @@
 		    __func__, sme->sme_name, edata->desc, lim_flags));
 
 		see = osee;
-		if (lim_flags & PROP_CRITMAX) {
-			if (critmax == see->see_critmax) {
+		if (lims->sel_flags & PROP_CRITMAX) {
+			if (lims->sel_critmax == see->see_lims.sel_critmax) {
 				DPRINTF(("%s: type=%d (critmax exists)\n",
 				    __func__, crittype));
 				error = EEXIST;
-				lim_flags &= ~PROP_CRITMAX;
+				lims->sel_flags &= ~PROP_CRITMAX;
 			}
 		}
-		if (lim_flags & PROP_WARNMAX) {
-			if (warnmax == see->see_warnmax) {
+		if (lims->sel_flags & PROP_WARNMAX) {
+			if (lims->sel_warnmax == see->see_lims.sel_warnmax) {
 				DPRINTF(("%s: type=%d (warnmax exists)\n",
 				    __func__, crittype));
 				error = EEXIST;
-				lim_flags &= ~PROP_WARNMAX;
+				lims->sel_flags &= ~PROP_WARNMAX;
 			}
 		}
-		if (lim_flags & (PROP_WARNMIN | PROP_BATTWARN)) {
-			if (warnmin == see->see_warnmin) {
+		if (lims->sel_flags & (PROP_WARNMIN | PROP_BATTWARN)) {
+			if (lims->sel_warnmin == see->see_lims.sel_warnmin) {
 				DPRINTF(("%s: type=%d (warnmin exists)\n",
 				    __func__, crittype));
 				error = EEXIST;
-				lim_flags &= ~(PROP_WARNMIN | PROP_BATTWARN);
+				lims->sel_flags &= ~(PROP_WARNMIN | PROP_BATTWARN);
 			}
 		}
-		if (lim_flags & (PROP_CRITMIN | PROP_BATTCAP)) {
-			if (critmin == see->see_critmin) {
+		if (lims->sel_flags & (PROP_CRITMIN | PROP_BATTCAP)) {
+			if (lims->sel_critmin == see->see_lims.sel_critmin) {
 				DPRINTF(("%s: type=%d (critmin exists)\n",
 				    __func__, crittype));
 				error = EEXIST;
-				lim_flags &= ~(PROP_CRITMIN | PROP_BATTCAP);
+				lims->sel_flags &= ~(PROP_CRITMIN | PROP_BATTCAP);
 			}
 		}
 		break;
@@ -192,7 +191,7 @@
 	/*
 	 * Limit operation requested.
 	 */
-	if (lim_flags & PROP_CRITMAX) {
+	if (lims->sel_flags & PROP_CRITMAX) {
 		objkey = "critical-max";
 		obj = prop_dictionary_get(sdict, objkey);
 		if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@@ -200,17 +199,19 @@
 			    __func__, sme->sme_name, objkey));
 			error = ENOTSUP;
 		} else {
-			see->see_critmax = critmax;
-			error = sme_sensor_upint32(sdict, objkey, critmax);
+			see->see_lims.sel_critmax = lims->sel_critmax;
+			error = sme_sensor_upint32(sdict, objkey,
+						   lims->sel_critmax);
 			DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
 			    "(%s updated)\n", __func__, sme->sme_name,
 			    edata->desc, crittype, objkey));
 		}
+		if (error && error != EEXIST)
+			goto out;
+		see->see_edata->upropset |= PROP_CRITMAX;
 	}
-	if (error && error != EEXIST)
-		goto out;
 
-	if (lim_flags & PROP_WARNMAX) {
+	if (lims->sel_flags & PROP_WARNMAX) {
 		objkey = "warning-max";
 		obj = prop_dictionary_get(sdict, objkey);
 		if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@@ -218,17 +219,19 @@
 			    __func__, sme->sme_name, objkey));
 			error = ENOTSUP;
 		} else {
-			see->see_warnmax = warnmax;
-			error = sme_sensor_upint32(sdict, objkey, warnmax);
+			see->see_lims.sel_warnmax = lims->sel_warnmax;
+			error = sme_sensor_upint32(sdict, objkey,
+						   lims->sel_warnmax);
 			DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
 			    "(%s updated)\n", __func__, sme->sme_name,
 			    edata->desc, crittype, objkey));
 		}
+		if (error && error != EEXIST)
+			goto out;
+		see->see_edata->upropset |= PROP_WARNMAX;
 	}
-	if (error && error != EEXIST)
-		goto out;
 
-	if (lim_flags & PROP_WARNMIN) {
+	if (lims->sel_flags & PROP_WARNMIN) {
 		objkey = "warning-min";
 		obj = prop_dictionary_get(sdict, objkey);
 		if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@@ -236,17 +239,19 @@
 			    __func__, sme->sme_name, objkey));
 			error = ENOTSUP;
 		} else {
-			see->see_warnmin = warnmin;
-			error = sme_sensor_upint32(sdict, objkey, warnmin);
+			see->see_lims.sel_warnmin = lims->sel_warnmin;
+			error = sme_sensor_upint32(sdict, objkey,
+						   lims->sel_warnmin);
 			DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
 			    "(%s updated)\n", __func__, sme->sme_name,
 			    edata->desc, crittype, objkey));
 		}
+		if (error && error != EEXIST)
+			goto out;
+		see->see_edata->upropset |= PROP_WARNMIN;
 	}
-	if (error && error != EEXIST)
-		goto out;
 
-	if (lim_flags & PROP_CRITMIN) {
+	if (lims->sel_flags & PROP_CRITMIN) {
 		objkey = "critical-min";
 		obj = prop_dictionary_get(sdict, objkey);
 		if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@@ -254,17 +259,19 @@
 			    __func__, sme->sme_name, objkey));
 			error = ENOTSUP;
 		} else {
-			see->see_critmin = critmin;
-			error = sme_sensor_upint32(sdict, objkey, critmin);
+			see->see_lims.sel_critmin = lims->sel_critmin;
+			error = sme_sensor_upint32(sdict, objkey,
+						   lims->sel_critmin);
 			DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
 			    "(%s updated)\n", __func__, sme->sme_name,
 			    edata->desc, crittype, objkey));
 		}
+		if (error && error != EEXIST)
+			goto out;
+		see->see_edata->upropset |= PROP_CRITMIN;
 	}
-	if (error && error != EEXIST)
-		goto out;
 
-	if (lim_flags & PROP_BATTWARN) {
+	if (lims->sel_flags & PROP_BATTWARN) {
 		objkey = "warning-capacity";
 		obj = prop_dictionary_get(sdict, objkey);
 		if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@@ -272,17 +279,19 @@
 			    __func__, sme->sme_name, objkey));
 			error = ENOTSUP;
 		} else {
-			see->see_warnmin = warnmin;
-			error = sme_sensor_upint32(sdict, objkey, warnmin);
+			see->see_lims.sel_warnmin = lims->sel_warnmin;
+			error = sme_sensor_upint32(sdict, objkey,
+						   lims->sel_warnmin);
 			DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
 			    "(%s updated)\n", __func__, sme->sme_name,
 			    edata->desc, crittype, objkey));
 		}
+		if (error && error != EEXIST)
+			goto out;
+		see->see_edata->upropset |= PROP_BATTWARN;
 	}
-	if (error && error != EEXIST)
-		goto out;
 
-	if (lim_flags & PROP_BATTCAP) {
+	if (lims->sel_flags & PROP_BATTCAP) {
 		objkey = "critical-capacity";
 		obj = prop_dictionary_get(sdict, objkey);
 		if (obj && prop_object_type(obj) != PROP_TYPE_NUMBER) {
@@ -290,28 +299,41 @@
 			    __func__, sme->sme_name, objkey));
 			error = ENOTSUP;
 		} else {
-			see->see_critmin = critmin;
-			error = sme_sensor_upint32(sdict, objkey, critmin);
+			see->see_lims.sel_critmin = lims->sel_critmin;
+			error = sme_sensor_upint32(sdict, objkey,
+						   lims->sel_critmin);
 			DPRINTF(("%s: (%s) event [sensor=%s type=%d] "
 			    "(%s updated)\n", __func__, sme->sme_name,
 			    edata->desc, crittype, objkey));
 		}
+		if (error && error != EEXIST)
+			goto out;
+		see->see_edata->upropset |= PROP_BATTCAP;
 	}
-	if (error && error != EEXIST)
-		goto out;
 
 	DPRINTF(("%s: (%s) event registered (sensor=%s snum=%d type=%d "
 	    "critmin=%" PRIu32 " warnmin=%" PRIu32 " warnmax=%" PRIu32
 	    " critmax=%" PRIu32 " props 0x%04x)\n", __func__,
 	    see->see_sme->sme_name, see->see_pes.pes_sensname,
-	    see->see_edata->sensor, see->see_type, see->see_critmin,
-	    see->see_warnmin, see->see_warnmax, see->see_critmax,
-	    see->see_edata->upropset));
+	    see->see_edata->sensor, see->see_type, see->see_lims.sel_critmin,
+	    see->see_lims.sel_warnmin, see->see_lims.sel_warnmax,
+	    see->see_lims.sel_critmax, see->see_edata->upropset));
 	/*
 	 * Initialize the events framework if it wasn't initialized before.
 	 */
 	if ((sme->sme_flags & SME_CALLOUT_INITIALIZED) == 0)
 		error = sme_events_init(sme);
+
+	/*
+	 * If driver requested notification, advise it of new
+	 * limit values
+	 */
+	if (sme->sme_set_limits) {
+		see->see_lims.sel_flags = see->see_edata->upropset &
+					  PROP_LIMITS;
+		(*sme->sme_set_limits)(sme, &(see->see_lims));
+	}
+
 out:
 	if ((error == 0 || error == EEXIST) && osee == NULL)
 		LIST_INSERT_HEAD(&sme->sme_events_list, see, see_list);
@@ -428,6 +450,7 @@
 sme_event_drvadd(void *arg)
 {
 	sme_event_drv_t *sed_t = arg;
+	sysmon_envsys_lim_t lims;
 	int error = 0;
 
 	KASSERT(sed_t != NULL);
@@ -440,7 +463,7 @@
 		error = sme_event_register(sed_t->sed_sdict,		\
 				      sed_t->sed_edata,			\
 				      sed_t->sed_sme,			\
-				      0, 0, 0, 0, 0,			\
+				      &lims,				\
 				      (b),				\
 				      sed_t->sed_powertype);		\
 		if (error && error != EEXIST)				\
@@ -457,18 +480,26 @@
 	}								\
 } while (/* CONSTCOND */ 0)
 
+	if (sed_t->sed_edata->flags & ENVSYS_FMONLIMITS) {
+		if (sed_t->sed_sme->sme_get_limits)
+			(*sed_t->sed_sme->sme_get_limits)(sed_t->sed_sme,
+							  &lims);
+		else
+			sed_t->sed_edata->flags &= ~ENVSYS_FMONLIMITS;
+	}
+
 	SEE_REGEVENT(ENVSYS_FMONCRITICAL,
 		     PENVSYS_EVENT_CRITICAL,
 		     "critical");
 
-	SEE_REGEVENT(ENVSYS_FMONLIMITS,
-		     PENVSYS_EVENT_LIMITS,
-		     "hw-range-limits");
-
 	SEE_REGEVENT(ENVSYS_FMONSTCHANGED,
 		     PENVSYS_EVENT_STATE_CHANGED,
 		     "state-changed");
 
+	SEE_REGEVENT(ENVSYS_FMONLIMITS,
+		     PENVSYS_EVENT_LIMITS,
+		     "hw-range-limits");
+
 	/* 
 	 * we are done, free memory now.
 	 */
@@ -604,24 +635,31 @@
 
 	switch (see->see_type) {
 	/*
-	 * For user range limits, calculate a new state first
-	 * State based on user limits will override any hardware
-	 * detected state.
+	 * For range limits, if the driver claims responsibility for
+	 * limit/range checking, just user driver-supplied status.
+	 * Else calculate our own status.  Note that driver must
+	 * relinquish responsibility for ALL limits if there is even
+	 * one limit that it cannot handle!
 	 */
 	case PENVSYS_EVENT_LIMITS:
 	case PENVSYS_EVENT_CAPACITY:
-#define __EXCEEDED_LIMIT(lim, rel) ((lim) && edata->value_cur rel (lim))
-		if __EXCEEDED_LIMIT(see->see_critmin, <)
-			edata->state = ENVSYS_SCRITUNDER;
-		else if __EXCEEDED_LIMIT(see->see_warnmin, <)
-			edata->state = ENVSYS_SWARNUNDER;
-		else if __EXCEEDED_LIMIT(see->see_warnmax, >)
-			edata->state = ENVSYS_SWARNOVER;
-		else if __EXCEEDED_LIMIT(see->see_critmax, >)
-			edata->state = ENVSYS_SCRITOVER;
+#define __EXCEED_LIM(lim, rel) ((lim) && edata->value_cur rel (lim))
+		if ((see->see_lims.sel_flags & PROP_DRIVER_LIMITS) == 0) {
+			if __EXCEED_LIM(see->see_lims.sel_critmin, <)
+				edata->state = ENVSYS_SCRITUNDER;
+			else if __EXCEED_LIM(see->see_lims.sel_warnmin, <)
+				edata->state = ENVSYS_SWARNUNDER;
+			else if __EXCEED_LIM(see->see_lims.sel_warnmax, >)
+				edata->state = ENVSYS_SWARNOVER;
+			else if __EXCEED_LIM(see->see_lims.sel_critmax, >)
+				edata->state = ENVSYS_SCRITOVER;
+		}
 		/* FALLTHROUGH */
-#undef __EXCEEDED_LIMIT
+#undef	__EXCEED_LIM
 
+		/*
+		 * Send event if state has changed
+		 */
 		if (edata->state == see->see_evsent)
 			break;
 

Index: src/sys/dev/sysmon/sysmon_envsysvar.h
diff -u src/sys/dev/sysmon/sysmon_envsysvar.h:1.29 src/sys/dev/sysmon/sysmon_envsysvar.h:1.30
--- src/sys/dev/sysmon/sysmon_envsysvar.h:1.29	Mon Jun  8 00:55:35 2009
+++ src/sys/dev/sysmon/sysmon_envsysvar.h	Sat Jun 13 16:08:25 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: sysmon_envsysvar.h,v 1.29 2009/06/08 00:55:35 pgoyette Exp $ */
+/* $NetBSD: sysmon_envsysvar.h,v 1.30 2009/06/13 16:08:25 pgoyette Exp $ */
 
 /*-
  * Copyright (c) 2007, 2008 Juan Romero Pardines.
@@ -73,10 +73,7 @@
 	struct sysmon_envsys	*see_sme;	/* device associated */
 	struct penvsys_state	see_pes;	/* our power envsys */
 	envsys_data_t		*see_edata;	/* our sensor data */
-	int32_t			see_critmin;	/* critical-min value set */
-	int32_t			see_warnmin;	/* warning-min value set */
-	int32_t			see_warnmax;	/* warning-max value set */
-	int32_t			see_critmax;	/* critical-max value set */
+	sysmon_envsys_lim_t	see_lims;	/* limit values */
 	int			see_type;	/* type of the event */
 	int			see_evsent;	/* event already sent */
 	int 			see_flags;	/* see above */
@@ -128,8 +125,8 @@
  * functions to handle sysmon envsys events.
  */
 int	sme_event_register(prop_dictionary_t, envsys_data_t *,
-			   struct sysmon_envsys *, int32_t, int32_t,
-			   int32_t, int32_t, int, int, int);
+			   struct sysmon_envsys *, sysmon_envsys_lim_t *,
+			   int, int);
 int	sme_event_unregister(struct sysmon_envsys *, const char *, int);
 void	sme_event_unregister_all(struct sysmon_envsys *);
 void	sme_event_drvadd(void *);

Index: src/sys/dev/sysmon/sysmonvar.h
diff -u src/sys/dev/sysmon/sysmonvar.h:1.27 src/sys/dev/sysmon/sysmonvar.h:1.28
--- src/sys/dev/sysmon/sysmonvar.h:1.27	Tue Jun  3 15:00:57 2008
+++ src/sys/dev/sysmon/sysmonvar.h	Sat Jun 13 16:08:25 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysmonvar.h,v 1.27 2008/06/03 15:00:57 jmcneill Exp $	*/
+/*	$NetBSD: sysmonvar.h,v 1.28 2009/06/13 16:08:25 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2000 Zembu Labs, Inc.
@@ -60,7 +60,6 @@
  *****************************************************************************/
 
 struct sme_event;
-struct sme_sensor_names;
 
 struct sysmon_envsys {
 	const char *sme_name;		/* envsys device name */
@@ -86,6 +85,13 @@
 	 */
 	void (*sme_refresh)(struct sysmon_envsys *, envsys_data_t *);
 
+	/*
+	 * Function callbacks to exchange limit/threshold values
+	 * with device
+	 */
+	void (*sme_set_limits)(struct sysmon_envsys *, sysmon_envsys_lim_t *);
+	void (*sme_get_limits)(struct sysmon_envsys *, sysmon_envsys_lim_t *);
+
 	struct workqueue *sme_wq;	/* the workqueue for the events */
 	struct callout sme_callout;	/* for the events */
 	uint64_t sme_events_timeout;	/* the timeout used in the callout */

Index: src/sys/sys/envsys.h
diff -u src/sys/sys/envsys.h:1.25 src/sys/sys/envsys.h:1.26
--- src/sys/sys/envsys.h:1.25	Mon Jun  8 00:55:35 2009
+++ src/sys/sys/envsys.h	Sat Jun 13 16:08:25 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: envsys.h,v 1.25 2009/06/08 00:55:35 pgoyette Exp $ */
+/* $NetBSD: envsys.h,v 1.26 2009/06/13 16:08:25 pgoyette Exp $ */
 
 /*-
  * Copyright (c) 1999, 2007 The NetBSD Foundation, Inc.
@@ -145,7 +145,8 @@
 #define ENVSYS_REMOVEPROPS	_IOWR('E', 2, struct plistref)
 
 /*
- * Properties that can be set in upropset
+ * Properties that can be set in upropset (and in the event_limit's
+ * flags field)
  */
 #define	PROP_CRITMAX		0x0001
 #define	PROP_CRITMIN		0x0002
@@ -156,6 +157,22 @@
 #define	PROP_DESC		0x0040
 #define	PROP_RFACT		0x0080
 
+#define	PROP_DRIVER_LIMITS	0x8000
+#define	PROP_LIMITS		0x003f
+
+/*
+ * Thresholds/limits that are being monitored
+ */
+struct sysmon_envsys_lim {
+	uint32_t	sel_flags;	/* Flag which limits are present */
+	int32_t		sel_critmax;
+	int32_t		sel_warnmax;
+	int32_t		sel_warnmin;
+	int32_t		sel_critmin;
+};
+
+typedef struct sysmon_envsys_lim sysmon_envsys_lim_t;
+
 /*
  * Compatibility with old interface. Only ENVSYS_GTREDATA
  * and ENVSYS_GTREINFO ioctls are supported.

Reply via email to