summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphitran <none@none>2008-05-07 15:12:21 -0700
committerphitran <none@none>2008-05-07 15:12:21 -0700
commitd2ec54f7875f7e05edd56195adbeb593c947763f (patch)
tree060ccb18e19011bfee2ea7c48b1bd98e442caeea
parent5b764efa67662f6a18a3eea7053aab98a9fbfebf (diff)
downloadillumos-joyent-d2ec54f7875f7e05edd56195adbeb593c947763f.tar.gz
PSARC/2008/021 HAL Power Management Support
6682365 Add power management support for lid, LCD brightness, and power button --HG-- rename : usr/src/cmd/hal/probing/battery/Makefile => usr/src/cmd/hal/probing/acpi/Makefile rename : usr/src/cmd/hal/probing/battery/probe-battery.c => usr/src/cmd/hal/probing/acpi/probe-acpi.c rename : usr/src/cmd/hal/utils/battery.c => usr/src/cmd/hal/utils/acpi.c rename : usr/src/cmd/hal/utils/battery.h => usr/src/cmd/hal/utils/acpi.h rename : usr/src/uts/common/sys/battery.h => usr/src/uts/common/sys/acpi_drv.h rename : usr/src/uts/common/sys/sysevent/acpiev.h => usr/src/uts/common/sys/sysevent/pwrctl.h rename : usr/src/uts/i86pc/battery/Makefile => usr/src/uts/i86pc/acpi_drv/Makefile rename : usr/src/uts/i86pc/io/battery/battery.c => usr/src/uts/i86pc/io/acpi_drv/acpi_drv.c rename : usr/src/uts/i86pc/io/battery/battery.conf => usr/src/uts/i86pc/io/acpi_drv/acpi_drv.conf
-rw-r--r--usr/src/cmd/hal/addons/acpi/Makefile8
-rw-r--r--usr/src/cmd/hal/addons/acpi/addon-acpi.c4
-rw-r--r--usr/src/cmd/hal/fdi/Makefile3
-rw-r--r--usr/src/cmd/hal/hald/hald_dbus.c6
-rw-r--r--usr/src/cmd/hal/hald/hald_runner.c2
-rw-r--r--usr/src/cmd/hal/hald/solaris/devinfo.c2
-rw-r--r--usr/src/cmd/hal/hald/solaris/devinfo_acpi.c97
-rw-r--r--usr/src/cmd/hal/hald/solaris/devinfo_acpi.h9
-rw-r--r--usr/src/cmd/hal/hald/solaris/devinfo_misc.c70
-rw-r--r--usr/src/cmd/hal/hald/solaris/devinfo_misc.h3
-rw-r--r--usr/src/cmd/hal/hald/solaris/sysevent.c73
-rw-r--r--usr/src/cmd/hal/probing/Makefile4
-rw-r--r--usr/src/cmd/hal/probing/acpi/Makefile (renamed from usr/src/cmd/hal/probing/battery/Makefile)12
-rw-r--r--usr/src/cmd/hal/probing/acpi/probe-acpi.c (renamed from usr/src/cmd/hal/probing/battery/probe-battery.c)16
-rw-r--r--usr/src/cmd/hal/tools/Makefile40
-rw-r--r--usr/src/cmd/hal/tools/hal-functions.sh49
-rw-r--r--usr/src/cmd/hal/tools/hal-is-caller-privileged.c209
-rw-r--r--usr/src/cmd/hal/tools/hal-system-lcd-get-brightness.sh10
-rw-r--r--usr/src/cmd/hal/tools/hal-system-lcd-set-brightness.sh10
-rw-r--r--usr/src/cmd/hal/tools/hal-system-power-hibernate.sh10
-rw-r--r--usr/src/cmd/hal/tools/hal-system-power-reboot.sh10
-rw-r--r--usr/src/cmd/hal/tools/hal-system-power-shutdown.sh10
-rw-r--r--usr/src/cmd/hal/tools/hal-system-power-suspend.sh10
-rw-r--r--usr/src/cmd/hal/tools/sunos/Makefile61
-rw-r--r--usr/src/cmd/hal/tools/sunos/hal-system-lcd-get-brightness-sunos.c63
-rw-r--r--usr/src/cmd/hal/tools/sunos/hal-system-lcd-set-brightness-sunos.c65
-rw-r--r--usr/src/cmd/hal/tools/sunos/hal-system-power-hibernate-sunos.sh32
-rw-r--r--usr/src/cmd/hal/tools/sunos/hal-system-power-reboot-sunos.sh19
-rw-r--r--usr/src/cmd/hal/tools/sunos/hal-system-power-shutdown-sunos.sh19
-rw-r--r--usr/src/cmd/hal/tools/sunos/hal-system-power-suspend-sunos.sh43
-rw-r--r--usr/src/cmd/hal/utils/acpi.c (renamed from usr/src/cmd/hal/utils/battery.c)115
-rw-r--r--usr/src/cmd/hal/utils/acpi.h (renamed from usr/src/cmd/hal/utils/battery.h)12
-rw-r--r--usr/src/cmd/power/powerd.c14
-rw-r--r--usr/src/lib/libsecdb/auth_attr.txt5
-rw-r--r--usr/src/lib/libsecdb/help/auths/Makefile7
-rw-r--r--usr/src/lib/libsecdb/help/auths/SysPowerMgmtBrightness.html42
-rw-r--r--usr/src/lib/libsecdb/help/auths/SysPowerMgmtHeader.html40
-rw-r--r--usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspend.html42
-rw-r--r--usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspendtoDisk.html42
-rw-r--r--usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspendtoRAM.html42
-rw-r--r--usr/src/lib/libsecdb/help/profiles/Makefile7
-rw-r--r--usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmt.html38
-rw-r--r--usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtBrightness.html38
-rw-r--r--usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspend.html38
-rw-r--r--usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspendtoDisk.html38
-rw-r--r--usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspendtoRAM.html38
-rw-r--r--usr/src/lib/libsecdb/prof_attr.txt10
-rw-r--r--usr/src/lib/policykit/libpolkit/common/libpolkit-rbac.c13
-rw-r--r--usr/src/pkgdefs/SUNW0on/prototype_com10
-rw-r--r--usr/src/pkgdefs/SUNWckr/prototype_i3866
-rw-r--r--usr/src/pkgdefs/SUNWcsu/prototype_com10
-rw-r--r--usr/src/pkgdefs/SUNWhal/prototype_com19
-rw-r--r--usr/src/pkgdefs/SUNWhalr/prototype_com3
-rw-r--r--usr/src/pkgdefs/SUNWhea/prototype_com4
-rw-r--r--usr/src/pkgdefs/common_files/i.minorperm_i3862
-rw-r--r--usr/src/uts/common/io/power.c77
-rw-r--r--usr/src/uts/common/sys/Makefile4
-rw-r--r--usr/src/uts/common/sys/acpi_drv.h (renamed from usr/src/uts/common/sys/battery.h)130
-rw-r--r--usr/src/uts/common/sys/sysevent/eventdefs.h19
-rw-r--r--usr/src/uts/common/sys/sysevent/pwrctl.h (renamed from usr/src/uts/common/sys/sysevent/acpiev.h)50
-rw-r--r--usr/src/uts/i86pc/Makefile.files2
-rw-r--r--usr/src/uts/i86pc/Makefile.i86pc.shared2
-rw-r--r--usr/src/uts/i86pc/Makefile.rules4
-rw-r--r--usr/src/uts/i86pc/acpi_drv/Makefile (renamed from usr/src/uts/i86pc/battery/Makefile)14
-rw-r--r--usr/src/uts/i86pc/io/acpi_drv/acpi_drv.c2548
-rw-r--r--usr/src/uts/i86pc/io/acpi_drv/acpi_drv.conf (renamed from usr/src/uts/i86pc/io/battery/battery.conf)4
-rw-r--r--usr/src/uts/i86pc/io/battery/battery.c1972
-rw-r--r--usr/src/uts/intel/os/minor_perm2
-rw-r--r--usr/src/uts/intel/os/name_to_major2
69 files changed, 4221 insertions, 2213 deletions
diff --git a/usr/src/cmd/hal/addons/acpi/Makefile b/usr/src/cmd/hal/addons/acpi/Makefile
index 5ee5df687d..daf306a758 100644
--- a/usr/src/cmd/hal/addons/acpi/Makefile
+++ b/usr/src/cmd/hal/addons/acpi/Makefile
@@ -19,14 +19,14 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
PROG = hald-addon-acpi
-OBJS = addon-acpi.o logger.o util_helper.o battery.o util_pm.o
+OBJS = addon-acpi.o logger.o util_helper.o acpi.o util_pm.o
SRCS = addon-acpi.c ../../hald/logger.c ../../hald/util_helper.c
include ../../../Makefile.cmd
@@ -44,8 +44,8 @@ C99MODE = $(C99_ENABLE)
all: $(PROG)
-battery.o: ../../utils/battery.c
- $(COMPILE.c) -o $@ ../../utils/battery.c
+acpi.o: ../../utils/acpi.c
+ $(COMPILE.c) -o $@ ../../utils/acpi.c
$(POST_PROCESS_O)
logger.o: ../../hald/logger.c
diff --git a/usr/src/cmd/hal/addons/acpi/addon-acpi.c b/usr/src/cmd/hal/addons/acpi/addon-acpi.c
index 82eca86820..2f87da2bc0 100644
--- a/usr/src/cmd/hal/addons/acpi/addon-acpi.c
+++ b/usr/src/cmd/hal/addons/acpi/addon-acpi.c
@@ -3,7 +3,7 @@
* addon-acpi.c : Poll battery and AC adapter devices and update
* properties
*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Licensed under the Academic Free License version 2.1
@@ -27,7 +27,7 @@
#include <libhal.h>
#include "../../hald/logger.h"
#include "../../hald/util_helper.h"
-#include "../../utils/battery.h"
+#include "../../utils/acpi.h"
int
main(int argc, char **argv)
diff --git a/usr/src/cmd/hal/fdi/Makefile b/usr/src/cmd/hal/fdi/Makefile
index 6724d578bf..786b66510d 100644
--- a/usr/src/cmd/hal/fdi/Makefile
+++ b/usr/src/cmd/hal/fdi/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -42,7 +42,6 @@ FDIS = information/10freedesktop/10-camera-ptp.fdi \
information/10freedesktop/10-usb-pda.fdi \
information/10freedesktop/10-usb-zip-drives.fdi \
information/10freedesktop/10-wireless-mice.fdi \
- policy/10osvendor/10-keyboard-policy.fdi \
policy/10osvendor/10-laptop-panel-mgmt-policy.fdi \
policy/10osvendor/10-network-attached.fdi \
policy/10osvendor/10-power-mgmt-policy.fdi \
diff --git a/usr/src/cmd/hal/hald/hald_dbus.c b/usr/src/cmd/hal/hald/hald_dbus.c
index 780aa88e61..f116c85972 100644
--- a/usr/src/cmd/hal/hald/hald_dbus.c
+++ b/usr/src/cmd/hal/hald/hald_dbus.c
@@ -3257,7 +3257,7 @@ hald_exec_method_cb (HalDevice *d, guint32 exit_type,
gint return_code, gchar **error,
gpointer data1, gpointer data2)
{
- dbus_uint32_t result;
+ dbus_int32_t result;
DBusMessage *reply = NULL;
DBusMessage *message;
DBusMessageIter iter;
@@ -3302,14 +3302,14 @@ hald_exec_method_cb (HalDevice *d, guint32 exit_type,
dbus_message_unref (reply);
} else {
- result = (dbus_uint32_t) return_code;
+ result = (dbus_int32_t) return_code;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
DIE (("No memory"));
dbus_message_iter_init_append (reply, &iter);
- dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &result);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &result);
if (conn != NULL) {
if (!dbus_connection_send (conn, reply, NULL))
diff --git a/usr/src/cmd/hal/hald/hald_runner.c b/usr/src/cmd/hal/hald/hald_runner.c
index a0f07d1197..cb6fcad7fc 100644
--- a/usr/src/cmd/hal/hald/hald_runner.c
+++ b/usr/src/cmd/hal/hald/hald_runner.c
@@ -291,7 +291,7 @@ add_basic_env(DBusMessageIter *iter, const gchar *udi) {
add_env(iter, "HAVE_POLKIT", "1");
#endif
- if (uname(&un) == 0) {
+ if (uname(&un) >= 0) {
char *sysname;
sysname = g_ascii_strdown(un.sysname, -1);
diff --git a/usr/src/cmd/hal/hald/solaris/devinfo.c b/usr/src/cmd/hal/hald/solaris/devinfo.c
index a216d7c603..40af76486e 100644
--- a/usr/src/cmd/hal/hald/solaris/devinfo.c
+++ b/usr/src/cmd/hal/hald/solaris/devinfo.c
@@ -141,6 +141,8 @@ static DevinfoDevHandler *devinfo_handlers[] = {
&devinfo_lofi_handler,
&devinfo_acpi_handler,
&devinfo_battery_handler,
+ &devinfo_power_button_handler,
+ &devinfo_keyboard_handler,
&devinfo_default_handler,
NULL
};
diff --git a/usr/src/cmd/hal/hald/solaris/devinfo_acpi.c b/usr/src/cmd/hal/hald/solaris/devinfo_acpi.c
index f23fa0b1c9..f93b156e9b 100644
--- a/usr/src/cmd/hal/hald/solaris/devinfo_acpi.c
+++ b/usr/src/cmd/hal/hald/solaris/devinfo_acpi.c
@@ -2,7 +2,7 @@
*
* devinfo_acpi : acpi devices
*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Licensed under the Academic Free License version 2.1
@@ -22,6 +22,8 @@
#include <sys/mkdev.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <sys/sysevent/dev.h>
+#include <sys/sysevent/pwrctl.h>
#include "../osspec.h"
#include "../logger.h"
@@ -36,6 +38,10 @@
static HalDevice *devinfo_acpi_add(HalDevice *, di_node_t, char *, char *);
static HalDevice *devinfo_battery_add(HalDevice *, di_node_t, char *, char *);
+static HalDevice *devinfo_power_button_add(HalDevice *parent, di_node_t node,
+ char *devfs_path, char *device_type);
+static void devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
+ gint return_code, char **error, gpointer userdata1, gpointer userdata2);
DevinfoDevHandler devinfo_acpi_handler = {
devinfo_acpi_add,
@@ -55,6 +61,15 @@ DevinfoDevHandler devinfo_battery_handler = {
devinfo_battery_get_prober
};
+DevinfoDevHandler devinfo_power_button_handler = {
+ devinfo_power_button_add,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
static HalDevice *
devinfo_acpi_add(HalDevice *parent, di_node_t node, char *devfs_path,
char *device_type)
@@ -94,7 +109,7 @@ devinfo_battery_add(HalDevice *parent, di_node_t node, char *devfs_path,
char *devpath;
driver_name = di_driver_name(node);
- if ((driver_name == NULL) || (strcmp(driver_name, "battery") != 0)) {
+ if ((driver_name == NULL) || (strcmp(driver_name, "acpi_drv") != 0)) {
return (NULL);
}
@@ -147,6 +162,64 @@ devinfo_battery_add_minor(HalDevice *parent, di_node_t node, char *minor_path,
devinfo_add_enqueue(d, minor_path, &devinfo_battery_handler);
}
+static HalDevice *
+devinfo_power_button_add(HalDevice *parent, di_node_t node, char *devfs_path,
+ char *device_type)
+{
+ HalDevice *d;
+ char *driver_name;
+
+ driver_name = di_driver_name(node);
+ if ((driver_name == NULL) || (strcmp(driver_name, "power") != 0)) {
+ return (NULL);
+ }
+
+ d = hal_device_new();
+
+ devinfo_set_default_properties(d, parent, node, devfs_path);
+ hal_device_add_capability(d, "button");
+ hal_device_property_set_bool(d, "button.has_state", FALSE);
+ hal_device_property_set_string(d, "info.category", "input");
+ hal_device_property_set_string(d, "button.type", "power");
+ hal_device_property_set_string(d, "info.product", "Power Button");
+
+ devinfo_add_enqueue(d, devfs_path, &devinfo_power_button_handler);
+
+ return (d);
+}
+
+void
+devinfo_power_button_rescan(void)
+{
+ HalDevice *d = NULL;
+ HalDeviceStore *store = hald_get_gdl();
+
+ d = hal_device_store_match_key_value_string (store, "button.type",
+ "power");
+ if (d != NULL) {
+ device_send_signal_condition(d, "ButtonPressed", "power");
+ }
+}
+
+void
+devinfo_brightness_hotkeys_rescan(char *subclass)
+{
+ HalDevice *d = NULL;
+
+ if ((d = hal_device_store_find(hald_get_gdl(),
+ "/org/freedesktop/Hal/devices/computer")) ||
+ (d = hal_device_store_find(hald_get_tdl(),
+ "/org/freedesktop/Hal/devices/computer"))) {
+ if (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) {
+ device_send_signal_condition(d, "ButtonPressed",
+ "brightness-up");
+ } else {
+ device_send_signal_condition(d, "ButtonPressed",
+ "brightness-down");
+ }
+ }
+}
+
void
devinfo_battery_device_rescan(char *parent_devfs_path, gchar *udi)
{
@@ -158,11 +231,27 @@ devinfo_battery_device_rescan(char *parent_devfs_path, gchar *udi)
return;
}
- hald_runner_run(d, "hald-probe-battery", NULL,
+ hald_runner_run(d, "hald-probe-acpi", NULL,
DEVINFO_PROBE_BATTERY_TIMEOUT, devinfo_battery_rescan_probing_done,
NULL, NULL);
}
+void
+devinfo_lid_device_rescan(char *subclass, gchar *udi)
+{
+ HalDevice *d = NULL;
+
+ d = hal_device_store_find(hald_get_gdl(), udi);
+ if (d == NULL) {
+ HAL_INFO(("device not found %s", udi));
+ return;
+ }
+
+ hal_device_property_set_bool(d, "button.state.value",
+ (strcmp(subclass, ESC_PWRCTL_REMOVE) == 0));
+ device_send_signal_condition(d, "ButtonPressed", "lid");
+}
+
static void
devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
gint return_code, char **error, gpointer userdata1, gpointer userdata2)
@@ -174,5 +263,5 @@ const gchar *
devinfo_battery_get_prober(HalDevice *d, int *timeout)
{
*timeout = DEVINFO_PROBE_BATTERY_TIMEOUT; /* 30 second timeout */
- return ("hald-probe-battery");
+ return ("hald-probe-acpi");
}
diff --git a/usr/src/cmd/hal/hald/solaris/devinfo_acpi.h b/usr/src/cmd/hal/hald/solaris/devinfo_acpi.h
index 12858d7e1e..08dd681905 100644
--- a/usr/src/cmd/hal/hald/solaris/devinfo_acpi.h
+++ b/usr/src/cmd/hal/hald/solaris/devinfo_acpi.h
@@ -2,7 +2,7 @@
*
* devinfo_acpi.h : definitions for acpi devices
*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Licensed under the Academic Free License version 2.1
@@ -18,6 +18,7 @@
extern DevinfoDevHandler devinfo_acpi_handler;
extern DevinfoDevHandler devinfo_battery_handler;
+extern DevinfoDevHandler devinfo_power_button_handler;
#define MINOR_SHIFT 8
#define MINOR2TYPE(minor) ((minor) >> MINOR_SHIFT)
@@ -36,8 +37,10 @@ void devinfo_battery_add_minor(HalDevice *parent, di_node_t node,
char *minor_path, dev_t dev);
void devinfo_battery_remove_minor(char *parent_devfs_path, gchar *udi);
void devinfo_battery_device_rescan(char *parent_devfs_path, gchar *udi);
-static void devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
- gint return_code, char **error, gpointer userdata1, gpointer userdata2);
const gchar *devinfo_battery_get_prober(HalDevice *d, int *timeout);
+void devinfo_power_button_rescan(void);
+void devinfo_brightness_hotkeys_rescan(char *subclass);
+
+void devinfo_lid_device_rescan(char *subclass, gchar *udi);
#endif /* DEVINFO_ACPI_H */
diff --git a/usr/src/cmd/hal/hald/solaris/devinfo_misc.c b/usr/src/cmd/hal/hald/solaris/devinfo_misc.c
index e69f3d29b1..408fd12f83 100644
--- a/usr/src/cmd/hal/hald/solaris/devinfo_misc.c
+++ b/usr/src/cmd/hal/hald/solaris/devinfo_misc.c
@@ -19,6 +19,7 @@
#include <string.h>
#include <sys/utsname.h>
#include <libdevinfo.h>
+#include <sys/uadmin.h>
#include "../osspec.h"
#include "../logger.h"
@@ -29,32 +30,41 @@
#include "devinfo_misc.h"
static HalDevice *devinfo_computer_add(HalDevice *, di_node_t, char *, char *);
-static HalDevice *devinfo_cpu_add(HalDevice *, di_node_t, char *,char *);
+static HalDevice *devinfo_cpu_add(HalDevice *, di_node_t, char *, char *);
+static HalDevice *devinfo_keyboard_add(HalDevice *, di_node_t, char *, char *);
static HalDevice *devinfo_default_add(HalDevice *, di_node_t, char *, char *);
DevinfoDevHandler devinfo_computer_handler = {
- devinfo_computer_add,
+ devinfo_computer_add,
NULL,
NULL,
NULL,
NULL,
- NULL
+ NULL
};
DevinfoDevHandler devinfo_cpu_handler = {
- devinfo_cpu_add,
+ devinfo_cpu_add,
NULL,
NULL,
NULL,
NULL,
- NULL
+ NULL
+};
+DevinfoDevHandler devinfo_keyboard_handler = {
+ devinfo_keyboard_add,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
DevinfoDevHandler devinfo_default_handler = {
- devinfo_default_add,
+ devinfo_default_add,
NULL,
NULL,
NULL,
NULL,
- NULL
+ NULL
};
static HalDevice *
@@ -69,10 +79,10 @@ devinfo_computer_add(HalDevice *parent, di_node_t node, char *devfs_path, char *
d = hal_device_new ();
- hal_device_property_set_string (d, "info.subsystem", "unknown");
- hal_device_property_set_string (d, "info.product", "Computer");
- hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/computer");
- hal_device_set_udi (d, "/org/freedesktop/Hal/devices/computer");
+ hal_device_property_set_string (d, "info.subsystem", "unknown");
+ hal_device_property_set_string (d, "info.product", "Computer");
+ hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/computer");
+ hal_device_set_udi (d, "/org/freedesktop/Hal/devices/computer");
hal_device_property_set_string (d, "solaris.devfs_path", devfs_path);
if (uname (&un) >= 0) {
@@ -81,11 +91,18 @@ devinfo_computer_add(HalDevice *parent, di_node_t node, char *devfs_path, char *
hal_device_property_set_string (d, "system.kernel.machine", un.machine);
}
+ hal_device_property_set_bool(d, "power_management.can_hibernate",
+ (uadmin(A_FREEZE, AD_CHECK_SUSPEND_TO_DISK, 0) == 0));
+ hal_device_property_set_bool(d, "power_management.can_suspend",
+ (uadmin(A_FREEZE, AD_CHECK_SUSPEND_TO_RAM, 0) == 0));
+
+ hal_device_add_capability(d, "button");
+
/*
* Let computer be in TDL while synthesizing all other events
* because some may write to the object
*/
- hal_device_store_add (hald_get_tdl (), d);
+ hal_device_store_add (hald_get_tdl (), d);
devinfo_add_enqueue (d, devfs_path, &devinfo_computer_handler);
@@ -93,10 +110,10 @@ devinfo_computer_add(HalDevice *parent, di_node_t node, char *devfs_path, char *
local_d = hal_device_new ();
hal_device_property_set_string (local_d, "info.parent", hal_device_get_udi (d));
- hal_device_property_set_string (local_d, "info.subsystem", "unknown");
- hal_device_property_set_string (local_d, "info.product", "Local devices");
- hal_device_property_set_string (local_d, "info.udi", "/org/freedesktop/Hal/devices/local");
- hal_device_set_udi (local_d, "/org/freedesktop/Hal/devices/local");
+ hal_device_property_set_string (local_d, "info.subsystem", "unknown");
+ hal_device_property_set_string (local_d, "info.product", "Local devices");
+ hal_device_property_set_string (local_d, "info.udi", "/org/freedesktop/Hal/devices/local");
+ hal_device_set_udi (local_d, "/org/freedesktop/Hal/devices/local");
hal_device_property_set_string (local_d, "solaris.devfs_path", "/local");
devinfo_add_enqueue (local_d, "/local", &devinfo_default_handler);
@@ -124,6 +141,27 @@ devinfo_cpu_add(HalDevice *parent, di_node_t node, char *devfs_path, char *devic
}
static HalDevice *
+devinfo_keyboard_add(HalDevice *parent, di_node_t node, char *devfs_path,
+ char *device_type)
+{
+ HalDevice *d;
+
+ if (strcmp(di_node_name(node), "keyboard") != 0) {
+ return (NULL);
+ }
+
+ d = hal_device_new ();
+
+ devinfo_set_default_properties (d, parent, node, devfs_path);
+ hal_device_add_capability (d, "input.keyboard");
+ hal_device_add_capability(d, "button");
+
+ devinfo_add_enqueue (d, devfs_path, &devinfo_keyboard_handler);
+
+ return (d);
+}
+
+static HalDevice *
devinfo_default_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
{
char *driver_name;
diff --git a/usr/src/cmd/hal/hald/solaris/devinfo_misc.h b/usr/src/cmd/hal/hald/solaris/devinfo_misc.h
index 1023166a39..609f53e93d 100644
--- a/usr/src/cmd/hal/hald/solaris/devinfo_misc.h
+++ b/usr/src/cmd/hal/hald/solaris/devinfo_misc.h
@@ -2,7 +2,7 @@
*
* devinfo_misc.h : definitions for misc devices
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Licensed under the Academic Free License version 2.1
@@ -18,6 +18,7 @@
extern DevinfoDevHandler devinfo_cpu_handler;
extern DevinfoDevHandler devinfo_computer_handler;
+extern DevinfoDevHandler devinfo_keyboard_handler;
extern DevinfoDevHandler devinfo_default_handler;
#endif /* DEVINFO_MISC_H */
diff --git a/usr/src/cmd/hal/hald/solaris/sysevent.c b/usr/src/cmd/hal/hald/solaris/sysevent.c
index 7e482b233c..7fabccfaf4 100644
--- a/usr/src/cmd/hal/hald/solaris/sysevent.c
+++ b/usr/src/cmd/hal/hald/solaris/sysevent.c
@@ -26,7 +26,7 @@
#include <libdevinfo.h>
#include <libsysevent.h>
#include <sys/sysevent/dev.h>
-#include <sys/sysevent/acpiev.h>
+#include <sys/sysevent/pwrctl.h>
#include <glib.h>
#include "../osspec.h"
@@ -55,6 +55,8 @@ static void sysevent_dev_branch(gchar *);
static void sysevent_lofi_add(gchar *, gchar *);
static void sysevent_lofi_remove(gchar *, gchar *);
static void sysevent_devfs_add(gchar *);
+static void sysevent_pwrctl(gchar *, gchar *, gchar *, gchar *, gchar *,
+ gchar *, uint_t);
static sysevent_handle_t *shp;
@@ -66,7 +68,7 @@ gboolean
sysevent_init(void)
{
GError *err = NULL;
- const char *subcl[3];
+ const char *subcl[6];
/*
* pipe used to serialize sysevents through the main loop
@@ -111,10 +113,13 @@ sysevent_init(void)
return (FALSE);
}
- subcl[0] = ESC_ACPIEV_ADD;
- subcl[1] = ESC_ACPIEV_REMOVE;
- subcl[2] = ESC_ACPIEV_STATE_CHANGE;
- if (sysevent_subscribe_event(shp, EC_ACPIEV, subcl, 3) != 0) {
+ subcl[0] = ESC_PWRCTL_ADD;
+ subcl[1] = ESC_PWRCTL_REMOVE;
+ subcl[2] = ESC_PWRCTL_STATE_CHANGE;
+ subcl[3] = ESC_PWRCTL_BRIGHTNESS_UP;
+ subcl[4] = ESC_PWRCTL_BRIGHTNESS_DOWN;
+ subcl[5] = ESC_PWRCTL_POWER_BUTTON;
+ if (sysevent_subscribe_event(shp, EC_PWRCTL, subcl, 6) != 0) {
HAL_INFO(("subscribe(dev_add) failed %d", errno));
sysevent_unbind_handle(shp);
return (FALSE);
@@ -173,8 +178,8 @@ sysevent_dev_handler(sysevent_t *ev)
goto out;
}
- if (strcmp(class, EC_ACPIEV) == 0) {
- if (nvlist_lookup_string(attr_list, ACPIEV_DEV_PHYS_PATH,
+ if (strcmp(class, EC_PWRCTL) == 0) {
+ if (nvlist_lookup_string(attr_list, PWRCTL_DEV_PHYS_PATH,
&phys_path) != 0) {
goto out;
}
@@ -184,20 +189,20 @@ sysevent_dev_handler(sysevent_t *ev)
}
if (nvlist_lookup_string(attr_list, DEV_NAME, &dev_name) != 0) {
- if (strcmp(class, EC_ACPIEV) == 0) {
+ if (strcmp(class, EC_PWRCTL) == 0) {
dev_name = "noname";
} else {
dev_name = "";
}
}
- if (nvlist_lookup_string(attr_list, ACPIEV_DEV_HID, &dev_hid) != 0) {
+ if (nvlist_lookup_string(attr_list, PWRCTL_DEV_HID, &dev_hid) != 0) {
dev_hid = "";
}
- if (nvlist_lookup_string(attr_list, ACPIEV_DEV_UID, &dev_uid) != 0) {
+ if (nvlist_lookup_string(attr_list, PWRCTL_DEV_UID, &dev_uid) != 0) {
dev_uid = "";
}
- if (nvlist_lookup_uint32(attr_list, ACPIEV_DEV_INDEX, &dev_index)
+ if (nvlist_lookup_uint32(attr_list, PWRCTL_DEV_INDEX, &dev_index)
!= 0) {
dev_index = 0;
}
@@ -227,7 +232,6 @@ sysevent_iochannel_data (GIOChannel *source,
gchar dev_name[1024];
gchar dev_uid[1024];
gchar dev_hid[1024];
- gchar udi[1024];
uint_t dev_index;
HAL_INFO (("sysevent_iochannel_data"));
@@ -265,20 +269,9 @@ sysevent_iochannel_data (GIOChannel *source,
}
} else if (strcmp(class, EC_DEV_BRANCH) == 0) {
sysevent_dev_branch(phys_path);
- } else if (strcmp(class, EC_ACPIEV) == 0) {
- if (strcmp(dev_hid, "PNP0C0A") == 0) {
- snprintf(udi, sizeof(udi),
- "/org/freedesktop/Hal/devices/pseudo/"
- "battery_0_battery%d_0", dev_index);
- } else if (strcmp(dev_hid, "ACPI0003") == 0) {
- snprintf(udi, sizeof(udi),
- "/org/freedesktop/Hal/devices/pseudo/"
- "battery_0_ac%d_0", dev_index);
- } else {
- HAL_INFO(("dev_hid %s unknown", dev_hid));
- continue;
- }
- devinfo_battery_device_rescan(phys_path, udi);
+ } else if (strcmp(class, EC_PWRCTL) == 0) {
+ sysevent_pwrctl(class, subclass, phys_path,
+ dev_name, dev_hid, dev_uid, dev_index);
} else if (strcmp(class, EC_DEVFS) == 0) {
if (strcmp(subclass, ESC_DEVFS_DEVI_ADD) == 0) {
sysevent_devfs_add(phys_path);
@@ -448,3 +441,29 @@ sysevent_devfs_add(gchar *devfs_path)
out:
di_fini (node);
}
+
+static void
+sysevent_pwrctl(gchar *class, gchar *subclass, gchar *phys_path,
+ gchar *dev_name, gchar *dev_hid, gchar *dev_uid, uint_t dev_index)
+{
+ const gchar prefix[] = "/org/freedesktop/Hal/devices/pseudo/acpi_drv_0";
+ gchar udi[HAL_PATH_MAX];
+
+ if (strcmp(dev_hid, "PNP0C0A") == 0) {
+ snprintf(udi, sizeof(udi), "%s_battery%d_0", prefix, dev_index);
+ devinfo_battery_device_rescan(phys_path, udi);
+ } else if (strcmp(dev_hid, "ACPI0003") == 0) {
+ snprintf(udi, sizeof (udi), "%s_ac%d_0", prefix, dev_index);
+ devinfo_battery_device_rescan(phys_path, udi);
+ } else if (strcmp(dev_hid, "PNP0C0D") == 0) {
+ snprintf(udi, sizeof (udi), "%s_lid_0", prefix);
+ devinfo_lid_device_rescan(subclass, udi);
+ } else if (strcmp(subclass, ESC_PWRCTL_POWER_BUTTON) == 0) {
+ devinfo_power_button_rescan();
+ } else if ((strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) ||
+ (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_DOWN) == 0)) {
+ devinfo_brightness_hotkeys_rescan(subclass);
+ } else {
+ HAL_INFO(("Unmatched EC_PWRCTL"));
+ }
+}
diff --git a/usr/src/cmd/hal/probing/Makefile b/usr/src/cmd/hal/probing/Makefile
index 00244dcbe4..20e1d4c3ac 100644
--- a/usr/src/cmd/hal/probing/Makefile
+++ b/usr/src/cmd/hal/probing/Makefile
@@ -19,13 +19,13 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
-SUBDIRS = storage volume printer network-printer battery
+SUBDIRS = storage volume printer network-printer acpi
all := TARGET= all
install := TARGET= install
diff --git a/usr/src/cmd/hal/probing/battery/Makefile b/usr/src/cmd/hal/probing/acpi/Makefile
index bd1faf680d..2bfd38d014 100644
--- a/usr/src/cmd/hal/probing/battery/Makefile
+++ b/usr/src/cmd/hal/probing/acpi/Makefile
@@ -19,15 +19,15 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
-PROG = hald-probe-battery
-OBJS = probe-battery.o logger.o battery.o util_pm.o
-SRCS = probe-battery.c
+PROG = hald-probe-acpi
+OBJS = probe-acpi.o logger.o acpi.o util_pm.o
+SRCS = probe-acpi.c
include ../../../Makefile.cmd
include ../../Makefile.hal
@@ -48,8 +48,8 @@ logger.o: ../../hald/logger.c
$(COMPILE.c) -o $@ ../../hald/logger.c
$(POST_PROCESS_O)
-battery.o: ../../utils/battery.c
- $(COMPILE.c) -o $@ ../../utils/battery.c
+acpi.o: ../../utils/acpi.c
+ $(COMPILE.c) -o $@ ../../utils/acpi.c
$(POST_PROCESS_O)
util_pm.o: ../../hald/util_pm.c
diff --git a/usr/src/cmd/hal/probing/battery/probe-battery.c b/usr/src/cmd/hal/probing/acpi/probe-acpi.c
index af3fd8741d..4cf9e50e03 100644
--- a/usr/src/cmd/hal/probing/battery/probe-battery.c
+++ b/usr/src/cmd/hal/probing/acpi/probe-acpi.c
@@ -1,8 +1,8 @@
/***************************************************************************
*
- * probe-battery.c : Probe for battery device information
+ * probe-acpi.c : Probe for ACPI device information
*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Licensed under the Academic Free License version 2.1
@@ -28,7 +28,7 @@
#include <libhal.h>
#include <logger.h>
-#include "../utils/battery.h"
+#include "../utils/acpi.h"
int
main(int argc, char *argv[])
@@ -53,17 +53,21 @@ main(int argc, char *argv[])
if ((ctx = libhal_ctx_init_direct(&error)) == NULL)
goto out;
- HAL_DEBUG(("Doing probe-battery for %s (udi=%s)",
+ HAL_DEBUG(("Doing probe-acpi for %s (udi=%s)",
device_file, udi));
if ((fd = open(device_file, O_RDONLY | O_NONBLOCK)) < 0) {
HAL_DEBUG(("Cannot open %s: %s", device_file, strerror(errno)));
goto out;
}
- if (strstr(udi, "ac")) {
+ if (strstr(udi, "_ac")) {
ac_adapter_update(ctx, udi, fd);
- } else {
+ } else if (strstr(udi, "_battery")) {
battery_update(ctx, udi, fd);
+ } else if (strstr(udi, "_lid")) {
+ lid_update(ctx, udi, fd);
+ } else if (strstr(udi, "_output")) {
+ laptop_panel_update(ctx, udi, fd);
}
ret = 0;
diff --git a/usr/src/cmd/hal/tools/Makefile b/usr/src/cmd/hal/tools/Makefile
index 1bffd11e74..84f577c141 100644
--- a/usr/src/cmd/hal/tools/Makefile
+++ b/usr/src/cmd/hal/tools/Makefile
@@ -19,16 +19,24 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
+SUBDIR = sunos
+
HAL_PROG = hal-device hal-find-by-capability hal-find-by-property \
hal-get-property hal-set-property lshal
-SCRIPT = hal-fdi-validate
+HAL_LIB = hal-is-caller-privileged
+
+SCRIPT_BIN = hal-fdi-validate
+
+SCRIPT_LIB = hal-system-lcd-set-brightness hal-system-lcd-get-brightness \
+ hal-system-power-hibernate hal-system-power-suspend \
+ hal-system-power-reboot hal-system-power-shutdown hal-functions
STORAGE_METHOD_PROG = hal-storage-closetray hal-storage-eject \
hal-storage-mount hal-storage-unmount \
@@ -46,7 +54,7 @@ STORAGE_SHAREDSRCS = $(STORAGE_SHAREDOBJS:%.o=%.c)
SRCS = $(PROGSRCS) $(STORAGE_SHAREDSRCS)
-CLOBBERFILES += $(HAL_PROG) $(STORAGE_PROG) $(SCRIPT)
+CLOBBERFILES += $(HAL_PROG) $(STORAGE_PROG) $(SCRIPT_BIN) $(SCRIPT_LIB) $(HAL_LIB)
CLEANFILES += $(STORAGE_SHAREDOBJS) $(STORAGE_OBJS)
include ../../Makefile.cmd
@@ -56,6 +64,8 @@ $(HAL_PROG) := LDLIBS += -lc -ldbus-1 -lhal
lshal := LDLIBS += -ldbus-glib-1 -lglib-2.0
+$(HAL_LIB) := LDLIBS += -lc -ldbus-1 -lpolkit $(ZIGNORE) -lglib-2.0
+
$(STORAGE_PROG) := LDLIBS += -lc -ldbus-1 -lglib-2.0 -lhal -lhal-storage -lbsm
$(STORAGE_METHOD_PROG) := LDLIBS += -lpolkit
@@ -65,14 +75,22 @@ CPPFLAGS += -I$(ROOT)/usr/include/hal
CPPFLAGS += -I$(ROOT)/usr/include/libpolkit
C99MODE = $(C99_ENABLE)
-ROOTUSRSBINPROG = $(HAL_PROG:%=$(ROOTUSRSBIN)/%) $(SCRIPT:%=$(ROOTUSRSBIN)/%)
+ROOTUSRSBINPROG = $(HAL_PROG:%=$(ROOTUSRSBIN)/%) \
+ $(SCRIPT_BIN:%=$(ROOTUSRSBIN)/%)
ROOTCMDDIR = $(ROOTLIB_HAL)
-ROOTCMD = $(STORAGE_PROG:%=$(ROOTCMDDIR)/%)
+ROOTCMD = $(STORAGE_PROG:%=$(ROOTCMDDIR)/%) \
+ $(HAL_LIB:%=$(ROOTCMDDIR)/%) \
+ $(SCRIPT_LIB:%=$(ROOTCMDDIR)/%)
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
.KEEP_STATE:
-all: $(HAL_PROG) $(STORAGE_PROG) $(SCRIPT)
+all: $(HAL_PROG) $(STORAGE_PROG) $(SCRIPT_BIN) $(SCRIPT_LIB) $(HAL_LIB) $(SUBDIR)
$(STORAGE_SHAREDOBJS): $(STORAGE_SHAREDSRCS)
$(COMPILE.c) $(STORAGE_SHAREDSRCS)
@@ -137,10 +155,14 @@ lshal: lshal.c
$(LINK.c) -o $@ lshal.c $(LDLIBS)
$(POST_PROCESS)
-install: all $(ROOTUSRSBINPROG) $(ROOTCMD)
-
+install: all $(ROOTUSRSBINPROG) $(ROOTCMD) $(SUBDIR)
-clean:
+clean: $(SUBDIR)
$(RM) $(CLEANFILES)
+$(SUBDIR): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
include ../../Makefile.targ
diff --git a/usr/src/cmd/hal/tools/hal-functions.sh b/usr/src/cmd/hal/tools/hal-functions.sh
new file mode 100644
index 0000000000..c6449f6e33
--- /dev/null
+++ b/usr/src/cmd/hal/tools/hal-functions.sh
@@ -0,0 +1,49 @@
+# -*-Shell-script-*-
+#
+# hal-functions.sh: This file contains functions to be used by most or all
+# hal shell scripts
+# hal-system-lcd-get-brightness.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+hal_check_priv() {
+ if [ "$HAVE_POLKIT" = "1" -a -n $HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME ]; then
+ ACTION=$1
+ PK_RESULT=`hal-is-caller-privileged --udi $UDI --action $ACTION \
+ --caller $HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME`
+ RET=$?
+ if [ "$RET" != "0" ]; then
+ echo "org.freedesktop.Hal.Device.Error" >&2
+ echo "Cannot determine if caller is privileged" >&2
+ exit 1
+ fi
+ if [ "$PK_RESULT" != "yes" ] ;then
+ echo "org.freedesktop.Hal.Device.PermissionDeniedByPolicy" >&2
+ echo "$ACTION $PK_RESULT <-- (action, result)" >&2
+ exit 1
+ fi
+ fi
+}
+
+hal_call_backend() {
+ PROGRAM=`basename $0`
+ if [ -n "$HALD_UNAME_S" -a -x ./$HALD_UNAME_S/$PROGRAM-$HALD_UNAME_S ]; then
+ ./$HALD_UNAME_S/$PROGRAM-$HALD_UNAME_S $@
+ else
+ echo "org.freedesktop.Hal.Device.UnknownError" >&2
+ echo "No back-end for your operating system" >&2
+ exit 1
+ fi
+}
+
+hal_exec_backend() {
+ PROGRAM=`basename $0`
+ if [ -n "$HALD_UNAME_S" -a -x ./$HALD_UNAME_S/$PROGRAM-$HALD_UNAME_S ]; then
+ exec ./$HALD_UNAME_S/$PROGRAM-$HALD_UNAME_S $@
+ else
+ echo "org.freedesktop.Hal.Device.UnknownError" >&2
+ echo "No back-end for your operating system" >&2
+ exit 1
+ fi
+}
diff --git a/usr/src/cmd/hal/tools/hal-is-caller-privileged.c b/usr/src/cmd/hal/tools/hal-is-caller-privileged.c
new file mode 100644
index 0000000000..2e333ba644
--- /dev/null
+++ b/usr/src/cmd/hal/tools/hal-is-caller-privileged.c
@@ -0,0 +1,209 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * hal-is-caller-privileged.c : Determine if a caller is privileged
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ **************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <glib.h>
+#include <stdlib.h>
+
+#include <libhal.h>
+#ifdef HAVE_POLKIT
+#include <libpolkit.h>
+#endif
+
+/**
+ * usage:
+ * @argc: Number of arguments given to program
+ * @argv: Arguments given to program
+ *
+ * Print out program usage.
+ */
+static void
+usage (int argc, char *argv[])
+{
+ fprintf (stderr,
+ "\n"
+ "usage : hal-is-caller-privileged --udi <udi> --action <action>\n"
+ " --caller <caller-name>\n"
+ " [--help] [--version]\n");
+ fprintf (stderr,
+ "\n"
+ " --udi Unique Device Id\n"
+ " --action PolicyKit action to check for\n"
+ " --caller The name of the caller\n"
+ " --version Show version and exit\n"
+ " --help Show this information and exit\n"
+ "\n"
+ "This program determines if a given process on the system bus is\n"
+ "privileged for a given PolicyKit action for a given device. If an error\n"
+ "occurs this program exits with a non-zero exit code. Otherwise\n"
+ "the textual reply will be printed on stdout and this program will\n"
+ "exit with exit code 0. Note that only the super user (root)\n"
+ "or other privileged users can use this tool.\n"
+ "\n");
+}
+
+#ifdef HAVE_POLKIT
+static void
+permission_denied_privilege (const char *privilege, const char *uid)
+{
+ fprintf (stderr, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy\n"
+);
+ fprintf (stderr, "%s refused uid %s\n", privilege, uid);
+ exit (1);
+}
+#endif
+
+/**
+ * main:
+ * @argc: Number of arguments given to program
+ * @argv: Arguments given to program
+ *
+ * Returns: Return code
+ *
+ * Main entry point
+ */
+int
+main (int argc, char *argv[])
+{
+ char *udi = NULL;
+ char *action = NULL;
+ char *caller = NULL;
+ dbus_bool_t is_version = FALSE;
+ DBusError error;
+#ifdef HAVE_POLKIT
+ LibPolKitContext *pol_ctx = NULL;
+#endif
+ DBusConnection *system_bus = NULL;
+ uid_t calling_uid;
+ char *privilege = NULL;
+ const char *invoked_by_uid;
+ gboolean allowed_by_privilege = FALSE;
+ gboolean is_temporary_privilege;
+
+ if (argc <= 1) {
+ usage (argc, argv);
+ return 1;
+ }
+
+ while (1) {
+ int c;
+ int option_index = 0;
+ const char *opt;
+ static struct option long_options[] = {
+ {"udi", 1, NULL, 0},
+ {"action", 1, NULL, 0},
+ {"caller", 1, NULL, 0},
+ {"version", 0, NULL, 0},
+ {"help", 0, NULL, 0},
+ {NULL, 0, NULL, 0}
+ };
+
+ c = getopt_long (argc, argv, "",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 0:
+ opt = long_options[option_index].name;
+
+ if (strcmp (opt, "help") == 0) {
+ usage (argc, argv);
+ return 0;
+ } else if (strcmp (opt, "version") == 0) {
+ is_version = TRUE;
+ } else if (strcmp (opt, "udi") == 0) {
+ udi = strdup (optarg);
+ } else if (strcmp (opt, "caller") == 0) {
+ caller = strdup (optarg);
+ } else if (strcmp (opt, "action") == 0) {
+ privilege = strdup (optarg);
+ }
+ break;
+
+ default:
+ usage (argc, argv);
+ return 1;
+ break;
+ }
+ }
+
+ if (is_version) {
+ printf ("hal-is-caller-privileged " PACKAGE_VERSION "\n");
+ return 0;
+ }
+
+ if (udi == NULL || caller == NULL || privilege == NULL) {
+ usage (argc, argv);
+ return 1;
+ }
+
+ dbus_error_init (&error);
+ system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (system_bus == NULL) {
+ printf ("Cannot connect to the system bus\n");
+ LIBHAL_FREE_DBUS_ERROR (&error);
+ fprintf (stderr, "This program should only be started by hald.\n");
+ exit (1);
+ }
+
+#ifdef HAVE_POLKIT
+ pol_ctx = libpolkit_new_context (system_bus);
+ if (pol_ctx == NULL) {
+ printf ("Cannot get libpolkit context\n");
+ }
+ invoked_by_uid = getenv("HAL_METHOD_INVOKED_BY_UID");
+
+ if (libpolkit_is_uid_allowed_for_privilege (pol_ctx,
+ caller,
+ invoked_by_uid,
+ privilege,
+ udi,
+ &allowed_by_privilege,
+ &is_temporary_privilege,
+ NULL) != LIBPOLKIT_RESULT_OK
+) {
+ printf ("cannot lookup privilege\n");
+ fprintf (stderr, "Cannot lookup privilege from PolicyKit");
+ exit (1);
+ }
+
+ if (!allowed_by_privilege) {
+ printf ("caller don't possess privilege\n");
+ permission_denied_privilege (privilege, invoked_by_uid);
+ }
+#endif
+
+ printf("yes\n");
+ return 0;
+}
diff --git a/usr/src/cmd/hal/tools/hal-system-lcd-get-brightness.sh b/usr/src/cmd/hal/tools/hal-system-lcd-get-brightness.sh
new file mode 100644
index 0000000000..7e7a9dd290
--- /dev/null
+++ b/usr/src/cmd/hal/tools/hal-system-lcd-get-brightness.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# hal-system-lcd-get-brightness.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+. ./hal-functions
+hal_check_priv hal-power-brightness
+hal_exec_backend
diff --git a/usr/src/cmd/hal/tools/hal-system-lcd-set-brightness.sh b/usr/src/cmd/hal/tools/hal-system-lcd-set-brightness.sh
new file mode 100644
index 0000000000..3a8bc29147
--- /dev/null
+++ b/usr/src/cmd/hal/tools/hal-system-lcd-set-brightness.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# hal-system-lcd-set-brightness.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+. ./hal-functions
+hal_check_priv hal-power-brightness
+hal_exec_backend
diff --git a/usr/src/cmd/hal/tools/hal-system-power-hibernate.sh b/usr/src/cmd/hal/tools/hal-system-power-hibernate.sh
new file mode 100644
index 0000000000..b64736f60d
--- /dev/null
+++ b/usr/src/cmd/hal/tools/hal-system-power-hibernate.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# hal-system-power-hibernate.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+. ./hal-functions
+hal_check_priv hal-power-hibernate
+hal_exec_backend
diff --git a/usr/src/cmd/hal/tools/hal-system-power-reboot.sh b/usr/src/cmd/hal/tools/hal-system-power-reboot.sh
new file mode 100644
index 0000000000..e62c9d8efe
--- /dev/null
+++ b/usr/src/cmd/hal/tools/hal-system-power-reboot.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# hal-system-power-reboot.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+. ./hal-functions
+hal_check_priv hal-power-reboot
+hal_exec_backend
diff --git a/usr/src/cmd/hal/tools/hal-system-power-shutdown.sh b/usr/src/cmd/hal/tools/hal-system-power-shutdown.sh
new file mode 100644
index 0000000000..5b37e2dc38
--- /dev/null
+++ b/usr/src/cmd/hal/tools/hal-system-power-shutdown.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# hal-system-power-shutdown.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+. ./hal-functions
+hal_check_priv hal-power-shutdown
+hal_exec_backend
diff --git a/usr/src/cmd/hal/tools/hal-system-power-suspend.sh b/usr/src/cmd/hal/tools/hal-system-power-suspend.sh
new file mode 100644
index 0000000000..6028da2997
--- /dev/null
+++ b/usr/src/cmd/hal/tools/hal-system-power-suspend.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# hal-system-power-suspend.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+. ./hal-functions
+hal_check_priv hal-power-suspend
+hal_exec_backend
diff --git a/usr/src/cmd/hal/tools/sunos/Makefile b/usr/src/cmd/hal/tools/sunos/Makefile
new file mode 100644
index 0000000000..b1b3a6dc19
--- /dev/null
+++ b/usr/src/cmd/hal/tools/sunos/Makefile
@@ -0,0 +1,61 @@
+#
+# 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 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+HAL_PROGS = hal-system-lcd-set-brightness-sunos \
+ hal-system-lcd-get-brightness-sunos
+
+HAL_SCRIPTS = hal-system-power-reboot-sunos hal-system-power-suspend-sunos \
+ hal-system-power-hibernate-sunos hal-system-power-shutdown-sunos
+
+OBJS = $(HAL_PROG:%=%.o)
+
+CLOBBERFILES += $(HAL_PROGS)
+
+include ../../../Makefile.cmd
+include ../../Makefile.hal
+
+$(HAL_PROGS) := LDLIBS += -lc $(ZIGNORE) -lglib-2.0
+
+CPPFLAGS += $(HAL_DBUS_CPPFLAGS) $(HAL_GLIB_CPPFLAGS) $(HAL_CONFIG_CPPFLAGS)
+CPPFLAGS += -I$(ROOT)/usr/include/hal
+CPPFLAGS += -I$(ROOT)/usr/include/libpolkit
+C99MODE = $(C99_ENABLE)
+
+ROOTCMDDIR = $(ROOTLIB_HAL)/sunos
+ROOTCMD = $(HAL_PROGS:%=$(ROOTCMDDIR)/%) \
+ $(HAL_SCRIPTS:%=$(ROOTCMDDIR)/%)
+
+.KEEP_STATE:
+
+all: $(HAL_PROGS) $(HAL_SCRIPTS)
+
+install: all $(ROOTCMD)
+
+clean:
+ $(RM) $(OBJS) $(HAL_PROGS) $(HAL_SCRIPTS)
+
+include ../../../Makefile.targ
diff --git a/usr/src/cmd/hal/tools/sunos/hal-system-lcd-get-brightness-sunos.c b/usr/src/cmd/hal/tools/sunos/hal-system-lcd-get-brightness-sunos.c
new file mode 100644
index 0000000000..5193d671e2
--- /dev/null
+++ b/usr/src/cmd/hal/tools/sunos/hal-system-lcd-get-brightness-sunos.c
@@ -0,0 +1,63 @@
+/***************************************************************************
+ *
+ * hal-system-lcd-get-brightness-sunos.c : Get LCD brightness
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "../../hald/util.h"
+#include <sys/acpi_drv.h>
+
+int
+main(int argc, char *argv[])
+{
+ struct acpi_drv_output_status status;
+ int fd = -1;
+ char *udi;
+ char device_file[HAL_PATH_MAX] = "/devices";
+ char *devfs_path;
+
+ if ((udi = getenv("UDI")) == NULL) {
+ return (-1);
+ }
+ if ((devfs_path = getenv("HAL_PROP_SOLARIS_DEVFS_PATH")) == NULL) {
+ return (-1);
+ }
+
+ strlcat(device_file, devfs_path, HAL_PATH_MAX);
+ fprintf(stderr, "Getting brightness on %s (udi=%s)",
+ device_file, udi);
+ if ((fd = open(device_file, O_RDONLY | O_NONBLOCK)) < 0) {
+ fprintf(stderr, "Cannot open %s: %s", device_file,
+ strerror(errno));
+ return (-1);
+ }
+
+ bzero(&status, sizeof (status));
+ if (ioctl(fd, ACPI_DRV_IOC_STATUS, &status) < 0) {
+ close(fd);
+ return (-1);
+ } else {
+ close(fd);
+ return (status.cur_level_index);
+ }
+}
diff --git a/usr/src/cmd/hal/tools/sunos/hal-system-lcd-set-brightness-sunos.c b/usr/src/cmd/hal/tools/sunos/hal-system-lcd-set-brightness-sunos.c
new file mode 100644
index 0000000000..d3e7fa0988
--- /dev/null
+++ b/usr/src/cmd/hal/tools/sunos/hal-system-lcd-set-brightness-sunos.c
@@ -0,0 +1,65 @@
+/***************************************************************************
+ *
+ * hal-system-lcd-set-brightness-sunos.c : Set LCD brightness
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/acpi_drv.h>
+#include "../../hald/util.h"
+
+int
+main(int argc, char *argv[])
+{
+ char arg[10];
+ int level;
+ int fd = -1;
+ char *udi;
+ char device_file[HAL_PATH_MAX] = "/devices";
+ char *devfs_path;
+
+ if ((udi = getenv("UDI")) == NULL) {
+ return (1);
+ }
+ if ((devfs_path = getenv("HAL_PROP_SOLARIS_DEVFS_PATH")) == NULL) {
+ return (1);
+ }
+ strlcat(device_file, devfs_path, HAL_PATH_MAX);
+ fprintf(stderr, "Setting brightness on %s (udi=%s)",
+ device_file, udi);
+
+ if ((fd = open(device_file, O_RDONLY | O_NONBLOCK)) < 0) {
+ fprintf(stderr, "Cannot open %s: %s", device_file,
+ strerror(errno));
+ return (1);
+ }
+ if (fgets(arg, sizeof (arg), stdin)) {
+ level = atoi(arg);
+ }
+ if (ioctl(fd, ACPI_DRV_IOC_SET_BRIGHTNESS, &level) < 0) {
+ close(fd);
+ return (1);
+ } else {
+ close(fd);
+ return (0);
+ }
+}
diff --git a/usr/src/cmd/hal/tools/sunos/hal-system-power-hibernate-sunos.sh b/usr/src/cmd/hal/tools/sunos/hal-system-power-hibernate-sunos.sh
new file mode 100644
index 0000000000..e6bd73c027
--- /dev/null
+++ b/usr/src/cmd/hal/tools/sunos/hal-system-power-hibernate-sunos.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# hal-system-power-hibernate-sunos.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+unsupported() {
+ echo org.freedesktop.Hal.Device.SystemPowerManagement.NotSupported >&2
+ echo No hibernate method found >&2
+ exit 1
+}
+
+if [ -x "/usr/sbin/uadmin" ] ; then
+ /usr/sbin/uadmin 3 0
+ RET=$?
+else
+ unsupported
+fi
+
+#Refresh devices as a resume can do funny things
+for type in button battery ac_adapter
+do
+ devices=`hal-find-by-capability --capability $type`
+ for device in $devices
+ do
+ dbus-send --system --print-reply --dest=org.freedesktop.Hal \
+ $device org.freedesktop.Hal.Device.Rescan
+ done
+done
+
+exit $RET
diff --git a/usr/src/cmd/hal/tools/sunos/hal-system-power-reboot-sunos.sh b/usr/src/cmd/hal/tools/sunos/hal-system-power-reboot-sunos.sh
new file mode 100644
index 0000000000..f41dd56308
--- /dev/null
+++ b/usr/src/cmd/hal/tools/sunos/hal-system-power-reboot-sunos.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# hal-system-power-reboot-sunos.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+unsupported() {
+ echo "org.freedesktop.Hal.Device.SystemPowerManagement.NotSupported" >&2
+ echo "No reboot command found" >&2
+ exit 1
+}
+
+if [ -x "/sbin/init" ] ; then
+ /sbin/init 6
+ exit $?
+else
+ unsupported
+fi
diff --git a/usr/src/cmd/hal/tools/sunos/hal-system-power-shutdown-sunos.sh b/usr/src/cmd/hal/tools/sunos/hal-system-power-shutdown-sunos.sh
new file mode 100644
index 0000000000..311e8475e7
--- /dev/null
+++ b/usr/src/cmd/hal/tools/sunos/hal-system-power-shutdown-sunos.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# hal-system-power-shutdown-sunos.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+unsupported() {
+ echo "org.freedesktop.Hal.Device.SystemPowerManagement.NotSupported" >&2
+ echo "No shutdown command found" >&2
+ exit 1
+}
+
+if [ -x "/sbin/init" ] ; then
+ /sbin/init 5
+ exit $?
+else
+ unsupported
+fi
diff --git a/usr/src/cmd/hal/tools/sunos/hal-system-power-suspend-sunos.sh b/usr/src/cmd/hal/tools/sunos/hal-system-power-suspend-sunos.sh
new file mode 100644
index 0000000000..5617b61f6f
--- /dev/null
+++ b/usr/src/cmd/hal/tools/sunos/hal-system-power-suspend-sunos.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+#
+# hal-system-system-power-suspend-sunos.sh
+#
+# Licensed under the Academic Free License version 2.1
+#
+
+alarm_not_supported() {
+ echo org.freedesktop.Hal.Device.SystemPowerManagement.AlarmNotSupported >&2
+ echo Waking the system up is not supported >&2
+ exit 1
+}
+
+unsupported() {
+ echo org.freedesktop.Hal.Device.SystemPowerManagement.NotSupported >&2
+ echo No suspend method found >&2
+ exit 1
+}
+
+read seconds_to_sleep
+if [ $seconds_to_sleep != "0" ] ; then
+ alarm_not_supported
+fi
+
+if [ -x "/usr/sbin/uadmin" ] ; then
+ /usr/sbin/uadmin 3 20
+ RET=$?
+else
+ unsupported
+fi
+
+#Refresh devices as a resume can do funny things
+for type in button battery ac_adapter
+do
+ devices=`hal-find-by-capability --capability $type`
+ for device in $devices
+ do
+ dbus-send --system --print-reply --dest=org.freedesktop.Hal \
+ $device org.freedesktop.Hal.Device.Rescan
+ done
+done
+
+exit $RET
diff --git a/usr/src/cmd/hal/utils/battery.c b/usr/src/cmd/hal/utils/acpi.c
index 9d2008db48..5b2444f4ae 100644
--- a/usr/src/cmd/hal/utils/battery.c
+++ b/usr/src/cmd/hal/utils/acpi.c
@@ -1,8 +1,8 @@
/***************************************************************************
*
- * battery.c : Main routines for setting battery and AC adapter properties
+ * acpi.c : Main routines for setting battery, AC adapter, and lid properties
*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Licensed under the Academic Free License version 2.1
@@ -21,14 +21,14 @@
#include <kstat.h>
#include <fcntl.h>
#include <errno.h>
-#include <sys/battery.h>
+#include <sys/acpi_drv.h>
#include <libhal.h>
#include "../hald/device_info.h"
#include "../hald/hald_dbus.h"
#include "../hald/logger.h"
#include "../hald/util_pm.h"
-#include "battery.h"
+#include "acpi.h"
static void
@@ -39,6 +39,79 @@ my_dbus_error_free(DBusError *error)
}
}
+gboolean
+laptop_panel_update(LibHalContext *ctx, const char *udi, int fd)
+{
+ LibHalChangeSet *cs;
+ DBusError error;
+ struct acpi_drv_output_info inf;
+
+ HAL_DEBUG(("laptop_panel_update() enter"));
+
+ dbus_error_init(&error);
+ if (!libhal_device_query_capability(ctx, udi, "laptop_panel", &error)) {
+ bzero(&inf, sizeof (inf));
+ if ((ioctl(fd, ACPI_DRV_IOC_INFO, &inf) < 0) ||
+ (inf.nlev == 0)) {
+ return (FALSE);
+ }
+
+ my_dbus_error_free(&error);
+ libhal_device_add_capability(ctx, udi, "laptop_panel", &error);
+ if ((cs = libhal_device_new_changeset(udi)) == NULL) {
+ my_dbus_error_free(&error);
+ return (FALSE);
+ }
+ libhal_changeset_set_property_string(cs, "info.product",
+ "Generic Backlight Device");
+ libhal_changeset_set_property_string(cs, "info.category",
+ "laptop_panel");
+ libhal_changeset_set_property_int(cs, "laptop_panel.num_levels",
+ inf.nlev);
+ my_dbus_error_free(&error);
+ libhal_device_commit_changeset(ctx, cs, &error);
+ libhal_device_free_changeset(cs);
+ }
+ my_dbus_error_free(&error);
+ HAL_DEBUG(("ac_adapter_present() exit"));
+ return (TRUE);
+}
+
+gboolean
+lid_update(LibHalContext *ctx, const char *udi, int fd)
+{
+ LibHalChangeSet *cs;
+ DBusError error;
+
+ HAL_DEBUG(("lid_update() enter"));
+
+ dbus_error_init(&error);
+ if (!libhal_device_query_capability(ctx, udi, "button", &error)) {
+ my_dbus_error_free(&error);
+ libhal_device_add_capability(ctx, udi, "button", &error);
+ if ((cs = libhal_device_new_changeset(udi)) == NULL) {
+ my_dbus_error_free(&error);
+ return (FALSE);
+ }
+ libhal_changeset_set_property_bool(cs, "button.has_state",
+ TRUE);
+ libhal_changeset_set_property_bool(cs, "button.state.value",
+ FALSE);
+ libhal_changeset_set_property_string(cs, "button.type",
+ "lid");
+ libhal_changeset_set_property_string(cs, "info.product",
+ "Lid Switch");
+ libhal_changeset_set_property_string(cs, "info.category",
+ "button");
+ my_dbus_error_free(&error);
+ libhal_device_commit_changeset(ctx, cs, &error);
+ libhal_device_free_changeset(cs);
+ }
+ my_dbus_error_free(&error);
+ HAL_DEBUG(("update_lid() exit"));
+ return (TRUE);
+}
+
static void
ac_adapter_present(LibHalContext *ctx, const char *udi, int fd)
{
@@ -47,7 +120,7 @@ ac_adapter_present(LibHalContext *ctx, const char *udi, int fd)
DBusError error;
HAL_DEBUG(("ac_adapter_present() enter"));
- if (ioctl(fd, BATT_IOC_POWER_STATUS, &pow) < 0) {
+ if (ioctl(fd, ACPI_DRV_IOC_POWER_STATUS, &pow) < 0) {
return;
}
if ((cs = libhal_device_new_changeset(udi)) == NULL) {
@@ -170,7 +243,7 @@ battery_last_full(LibHalChangeSet *cs, int fd)
acpi_bif_t bif;
bzero(&bif, sizeof (bif));
- if (ioctl(fd, BATT_IOC_INFO, &bif) < 0) {
+ if (ioctl(fd, ACPI_DRV_IOC_INFO, &bif) < 0) {
return;
}
libhal_changeset_set_property_int(cs, "battery.reporting_last_full",
@@ -197,12 +270,12 @@ battery_dynamic_update(LibHalContext *ctx, const char *udi, int fd)
HAL_DEBUG(("battery_dynamic_update() enter"));
bzero(&bst, sizeof (bst));
- if (ioctl(fd, BATT_IOC_STATUS, &bst) < 0) {
+ if (ioctl(fd, ACPI_DRV_IOC_STATUS, &bst) < 0) {
return;
}
- charging = bst.bst_state & BATT_BST_CHARGING ? TRUE : FALSE;
- discharging = bst.bst_state & BATT_BST_DISCHARGING ? TRUE : FALSE;
+ charging = bst.bst_state & ACPI_DRV_BST_CHARGING ? TRUE : FALSE;
+ discharging = bst.bst_state & ACPI_DRV_BST_DISCHARGING ? TRUE : FALSE;
/* No need to continue if battery is essentially idle. */
if (counter && !charging && !discharging) {
return;
@@ -359,7 +432,7 @@ battery_static_update(LibHalContext *ctx, const char *udi, int fd)
HAL_DEBUG(("battery_static_update() enter"));
bzero(&bif, sizeof (bif));
- if (ioctl(fd, BATT_IOC_INFO, &bif) < 0) {
+ if (ioctl(fd, ACPI_DRV_IOC_INFO, &bif) < 0) {
return (FALSE);
}
if ((cs = libhal_device_new_changeset(udi)) == NULL) {
@@ -436,17 +509,17 @@ battery_static_update(LibHalContext *ctx, const char *udi, int fd)
"battery.charge_level.unit", "mWh");
}
libhal_changeset_set_property_int(cs,
- "battery.charge_level.design", reporting_design);
- libhal_changeset_set_property_int(cs,
- "battery.charge_level.warning", reporting_warning);
- libhal_changeset_set_property_int(cs,
- "battery.charge_level.low", reporting_low);
- libhal_changeset_set_property_int(cs,
- "battery.charge_level.granularity_1", reporting_gran1);
- libhal_changeset_set_property_int(cs,
- "battery.charge_level.granularity_2", reporting_gran2);
+ "battery.charge_level.design", reporting_design);
+ libhal_changeset_set_property_int(cs,
+ "battery.charge_level.warning", reporting_warning);
+ libhal_changeset_set_property_int(cs,
+ "battery.charge_level.low", reporting_low);
+ libhal_changeset_set_property_int(cs,
+ "battery.charge_level.granularity_1", reporting_gran1);
+ libhal_changeset_set_property_int(cs,
+ "battery.charge_level.granularity_2", reporting_gran2);
}
-
+
dbus_error_init(&error);
libhal_device_commit_changeset(ctx, cs, &error);
@@ -471,7 +544,7 @@ battery_update(LibHalContext *ctx, const char *udi, int fd)
&error);
bzero(&bst, sizeof (bst));
- if (ioctl(fd, BATT_IOC_STATUS, &bst) < 0) {
+ if (ioctl(fd, ACPI_DRV_IOC_STATUS, &bst) < 0) {
if (errno == ENXIO) {
my_dbus_error_free(&error);
libhal_device_set_property_bool(ctx, udi,
diff --git a/usr/src/cmd/hal/utils/battery.h b/usr/src/cmd/hal/utils/acpi.h
index 58878ebea6..476f81b5b2 100644
--- a/usr/src/cmd/hal/utils/battery.h
+++ b/usr/src/cmd/hal/utils/acpi.h
@@ -1,8 +1,8 @@
/***************************************************************************
*
- * battery.h
+ * acpi.h
*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Licensed under the Academic Free License version 2.1
@@ -11,8 +11,8 @@
#pragma ident "%Z%%M% %I% %E% SMI"
-#ifndef BATTERY_H
-#define BATTERY_H
+#ifndef ACPI_H
+#define ACPI_H
#include "../hald/util.h"
@@ -20,7 +20,9 @@
gboolean battery_update(LibHalContext *ctx, const char *udi, int fd);
gboolean ac_adapter_update(LibHalContext *ctx, const char *udi, int fd);
+gboolean lid_update(LibHalContext *ctx, const char *udi, int fd);
+gboolean laptop_panel_update(LibHalContext *ctx, const char *udi, int fd);
gboolean update_devices(gpointer data);
int open_device(LibHalContext *ctx, char *udi);
-#endif /* BATTERY_H */
+#endif /* ACPI_H */
diff --git a/usr/src/cmd/power/powerd.c b/usr/src/cmd/power/powerd.c
index a559041d0a..0b91bd61f2 100644
--- a/usr/src/cmd/power/powerd.c
+++ b/usr/src/cmd/power/powerd.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -1167,7 +1167,7 @@ static void
power_button_monitor(void *arg)
{
struct pollfd pfd;
- int events;
+ int events, ret;
if (ioctl(pb_fd, PB_BEGIN_MONITOR, NULL) == -1) {
logerror("Failed to monitor the power button.");
@@ -1187,12 +1187,20 @@ power_button_monitor(void *arg)
if (!(pfd.revents & POLLIN))
continue;
+ /*
+ * Monitor the power button, but only take action if
+ * gnome-power-manager is not running.
+ *
+ * ret greater than 0 means could not find process.
+ */
+ ret = system("/usr/bin/pgrep -f -P 1 gnome-power-manager");
+
if (ioctl(pfd.fd, PB_GET_EVENTS, &events) == -1) {
logerror("Failed to get power button events.");
thr_exit((void *) 0);
}
- if ((events & PB_BUTTON_PRESS) &&
+ if ((ret > 0) && (events & PB_BUTTON_PRESS) &&
(poweroff(NULL, power_button_cmd) != 0)) {
logerror("Power button is pressed, powering "
"down the system!");
diff --git a/usr/src/lib/libsecdb/auth_attr.txt b/usr/src/lib/libsecdb/auth_attr.txt
index 9a5cdf18ba..ea5203ceb8 100644
--- a/usr/src/lib/libsecdb/auth_attr.txt
+++ b/usr/src/lib/libsecdb/auth_attr.txt
@@ -152,6 +152,11 @@ solaris.smf.read.ndmp:::Read permission for protected SMF NDMP Service Propertie
solaris.system.:::Machine Administration::help=SysHeader.html
solaris.system.date:::Set Date & Time::help=SysDate.html
solaris.system.shutdown:::Shutdown the System::help=SysShutdown.html
+solaris.system.power.:::System Power Management::help=SysPowerMgmtHeader.html
+solaris.system.power.suspend.:::Suspend the System::help=SysPowerMgmtSuspend.html
+solaris.system.power.suspend.disk:::Suspend to Disk::help=SysPowerMgmtSuspendtoDisk.html
+solaris.system.power.suspend.ram:::Suspend to RAM::help=SysPowerMgmtSuspendToRAM.html
+solaris.system.power.brightness:::Control LCD Brightness::help=SysPowerMgmtBrightness.html
#
solaris.smf.manage.iscsitgt:::Manage ISCSI Target Service States::help=SmfValueIscsitgt.html
solaris.smf.read.iscsitgt:::Read ISCSI Target secrets::help=SmfValueIscsitgt.html
diff --git a/usr/src/lib/libsecdb/help/auths/Makefile b/usr/src/lib/libsecdb/help/auths/Makefile
index 811e5a0ff9..e168b9ed64 100644
--- a/usr/src/lib/libsecdb/help/auths/Makefile
+++ b/usr/src/lib/libsecdb/help/auths/Makefile
@@ -131,7 +131,12 @@ HTMLENTS = \
PrintUnlabeled.html \
TNDaemon.html \
TNctl.html \
- ValueTND.html
+ ValueTND.html \
+ SysPowerMgmtHeader.html \
+ SysPowerMgmtSuspend.html \
+ SysPowerMgmtSuspendtoDisk.html \
+ SysPowerMgmtSuspendtoRAM.html \
+ SysPowerMgmtBrightness.html
HELPDIR=$(ROOT)/usr/lib/help
AUTHDIR=$(HELPDIR)/auths
diff --git a/usr/src/lib/libsecdb/help/auths/SysPowerMgmtBrightness.html b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtBrightness.html
new file mode 100644
index 0000000000..2996f18bc3
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtBrightness.html
@@ -0,0 +1,42 @@
+<HTML>
+<!--
+ Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ 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
+-->
+<!-- SCCS keyword
+#pragma ident "%Z%%M% %I% %E% SMI"
+-->
+<HEAD>
+<!--
+META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"
+-->
+<!--
+META NAME="GENERATOR" CONTENT="Mozilla/4.02 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]"
+-->
+</HEAD>
+<BODY>
+When Control LCD Brightness is in the Authorizations Included column, it grants the authorization to control LCD brightness.
+<p>
+If Control LCD Brightness is grayed, then you are not entitled to Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/help/auths/SysPowerMgmtHeader.html b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtHeader.html
new file mode 100644
index 0000000000..1c5b1f5c72
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtHeader.html
@@ -0,0 +1,40 @@
+<HTML>
+<!--
+ Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ 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
+-->
+<!-- SCCS keyword
+#pragma ident "%Z%%M% %I% %E% SMI"
+-->
+<HEAD>
+<!--
+META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"
+-->
+<!--
+META NAME="GENERATOR" CONTENT="Mozilla/4.02 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]"
+-->
+</HEAD>
+<BODY>
+Authorized to change the system power management policies.
+<BR>&nbsp;
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspend.html b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspend.html
new file mode 100644
index 0000000000..ba6bb0cee5
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspend.html
@@ -0,0 +1,42 @@
+<HTML>
+<!--
+ Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ 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
+-->
+<!-- SCCS keyword
+#pragma ident "%Z%%M% %I% %E% SMI"
+-->
+<HEAD>
+<!--
+META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"
+-->
+<!--
+META NAME="GENERATOR" CONTENT="Mozilla/4.02 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]"
+-->
+</HEAD>
+<BODY>
+When Suspend the System is in the Authorizations Included column, it grants the authorization to suspend the operating system.
+<p>
+If Suspend the System is grayed, then you are not entitled to Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspendtoDisk.html b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspendtoDisk.html
new file mode 100644
index 0000000000..f81b8b79c0
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspendtoDisk.html
@@ -0,0 +1,42 @@
+<HTML>
+<!--
+ Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ 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
+-->
+<!-- SCCS keyword
+#pragma ident "%Z%%M% %I% %E% SMI"
+-->
+<HEAD>
+<!--
+META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"
+-->
+<!--
+META NAME="GENERATOR" CONTENT="Mozilla/4.02 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]"
+-->
+</HEAD>
+<BODY>
+When Suspend to Disk is in the Authorizations Included column, it grants the authorization to suspend the operating system to disk.
+<p>
+If Suspend to Disk is grayed, then you are not entitled to Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspendtoRAM.html b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspendtoRAM.html
new file mode 100644
index 0000000000..70ff5ff824
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/auths/SysPowerMgmtSuspendtoRAM.html
@@ -0,0 +1,42 @@
+<HTML>
+<!--
+ Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ 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
+-->
+<!-- SCCS keyword
+#pragma ident "%Z%%M% %I% %E% SMI"
+-->
+<HEAD>
+<!--
+META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"
+-->
+<!--
+META NAME="GENERATOR" CONTENT="Mozilla/4.02 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]"
+-->
+</HEAD>
+<BODY>
+When Suspend to RAM is in the Authorizations Included column, it grants the authorization to suspend the operating system to RAM.
+<p>
+If Suspend to RAM is grayed, then you are not entitled to Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/help/profiles/Makefile b/usr/src/lib/libsecdb/help/profiles/Makefile
index 41beab05fe..b8cc361a40 100644
--- a/usr/src/lib/libsecdb/help/profiles/Makefile
+++ b/usr/src/lib/libsecdb/help/profiles/Makefile
@@ -80,7 +80,12 @@ HTMLENTS = \
RtDefault.html \
RtIdmapMngmnt.html \
RtIdmapNameRulesMngmnt.html \
- RtVscanMngmnt.html
+ RtVscanMngmnt.html \
+ RtSysPowerMgmt.html \
+ RtSysPowerMgmtSuspend.html \
+ RtSysPowerMgmtSuspendtoDisk.html \
+ RtSysPowerMgmtSuspendtoRAM.html \
+ RtSysPowerMgmtBrightness.html
HELPDIR = $(ROOT)/usr/lib/help
diff --git a/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmt.html b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmt.html
new file mode 100644
index 0000000000..bcc46d4a71
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmt.html
@@ -0,0 +1,38 @@
+<HTML>
+<!--
+ 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 Sun Microsystems, Inc. All rights reserved.
+-- Use is subject to license terms.
+-->
+<HEAD>
+ <TITLE> </TITLE>
+
+
+</HEAD>
+<BODY>
+<!-- ident "%Z%%M% %I% %E% SMI" -->
+
+When System Power Management is in the Rights Included column, it grants the right to configure system power management policies.
+<p>
+If System Power Management is grayed, then you are not entitled to Add or Remove this right.
+<p>
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtBrightness.html b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtBrightness.html
new file mode 100644
index 0000000000..470f431e74
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtBrightness.html
@@ -0,0 +1,38 @@
+<HTML>
+<!--
+ 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 Sun Microsystems, Inc. All rights reserved.
+-- Use is subject to license terms.
+-->
+<HEAD>
+ <TITLE> </TITLE>
+
+
+</HEAD>
+<BODY>
+<!-- ident "%Z%%M% %I% %E% SMI" -->
+
+When Control LCD Brightness is in the Rights Included column, it grants the right to control LCD brightness.
+<p>
+If Control LCD Brightness is grayed, then you are not entitled to Add or Remove this right.
+<p>
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspend.html b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspend.html
new file mode 100644
index 0000000000..2438bb4086
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspend.html
@@ -0,0 +1,38 @@
+<HTML>
+<!--
+ 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 Sun Microsystems, Inc. All rights reserved.
+-- Use is subject to license terms.
+-->
+<HEAD>
+ <TITLE> </TITLE>
+
+
+</HEAD>
+<BODY>
+<!-- ident "%Z%%M% %I% %E% SMI" -->
+
+When Suspend the System is in the Rights Included column, it grants the right to suspend the operating system.
+<p>
+If Suspend the System is grayed, then you are not entitled to Add or Remove this right.
+<p>
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspendtoDisk.html b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspendtoDisk.html
new file mode 100644
index 0000000000..a30dfb2a27
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspendtoDisk.html
@@ -0,0 +1,38 @@
+<HTML>
+<!--
+ 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 Sun Microsystems, Inc. All rights reserved.
+-- Use is subject to license terms.
+-->
+<HEAD>
+ <TITLE> </TITLE>
+
+
+</HEAD>
+<BODY>
+<!-- ident "%Z%%M% %I% %E% SMI" -->
+
+When Suspend to Disk is in the Rights Included column, it grants the right to suspend the operating system to disk.
+<p>
+If Suspend to Disk is grayed, then you are not entitled to Add or Remove this right.
+<p>
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspendtoRAM.html b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspendtoRAM.html
new file mode 100644
index 0000000000..f762a9007b
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/profiles/RtSysPowerMgmtSuspendtoRAM.html
@@ -0,0 +1,38 @@
+<HTML>
+<!--
+ 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 Sun Microsystems, Inc. All rights reserved.
+-- Use is subject to license terms.
+-->
+<HEAD>
+ <TITLE> </TITLE>
+
+
+</HEAD>
+<BODY>
+<!-- ident "%Z%%M% %I% %E% SMI" -->
+
+When Suspend to RAM is in the Rights Included column, it grants the right to suspend the operating system to RAM.
+<p>
+If Suspend to RAM is grayed, then you are not entitled to Add or Remove this right.
+<p>
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/prof_attr.txt b/usr/src/lib/libsecdb/prof_attr.txt
index 33bd14bfda..0384d74bf4 100644
--- a/usr/src/lib/libsecdb/prof_attr.txt
+++ b/usr/src/lib/libsecdb/prof_attr.txt
@@ -34,7 +34,7 @@
All:::Execute any command as the user or role:help=RtAll.html
Audit Control:::Configure Solaris Auditing:auths=solaris.audit.config,solaris.jobs.admin;help=RtAuditCtrl.html
Audit Review:::Review Solaris Auditing logs:auths=solaris.audit.read;help=RtAuditReview.html
-Console User:::Manage System as the Console User:help=RtConsUser.html
+Console User:::Manage System as the Console User:profiles=Suspend To RAM,Suspend To Disk,Brightness;auths=solaris.system.shutdown;help=RtConsUser.html
Contract Observer:::Reliably observe any/all contract events:help=RtContractObserver.html
Device Management:::Control Access to Removable Media:auths=solaris.device.*;help=RtDeviceMngmnt.html
Printer Management:::Manage printers, daemons, spooling:auths=solaris.print.*,solaris.label.print,solaris.smf.manage.discovery.printers.*,solaris.smf.value.discovery.printers.*;help=RtPrntAdmin.html
@@ -93,3 +93,11 @@ Object Label Management:::Change labels on files.:auths=solaris.device.allocate,
Outside Accred:::Allow a user to operate outside the user accreditation range.:auths=solaris.label.range;help=RtOutsideAccred.html
ISCSI Target Administration:::Configure ISCSI Target service:auths=solaris.smf.modify.iscsitgt,solaris.smf.read.iscsitgt,solaris.smf.value.iscsitgt
ISCSI Target Management:::Start/Stop ISCSI Target service:auths=solaris.smf.manage.iscsitgt
+#
+# Power Management profiles:
+#
+System Power:::For authorized users to manage system power:auths=solaris.system.power.*;help=RtSysPowerMgmt.html
+Suspend:::For authorized users to Suspend system:auths=solaris.system.power.suspend.*;help=RtSysPowerMgmtSuspend.html
+Suspend To Disk:::For authorized users to Suspend to Disk:auths=solaris.system.power.suspend.disk;help=RtSysPowerMgmtSuspendToDisk.html
+Suspend To RAM:::For authorized users to Suspend to RAM:auths=solaris.system.power.suspend.ram;help=RtSysPowerMgmtSuspendToRAM.html
+Brightness:::For authorized users to Control LCD Brightness:auths=solaris.system.power.brightness;help=RtSysPowerMgmtBrightness.html
diff --git a/usr/src/lib/policykit/libpolkit/common/libpolkit-rbac.c b/usr/src/lib/policykit/libpolkit/common/libpolkit-rbac.c
index c7fcf1a454..f57d72a20c 100644
--- a/usr/src/lib/policykit/libpolkit/common/libpolkit-rbac.c
+++ b/usr/src/lib/policykit/libpolkit/common/libpolkit-rbac.c
@@ -2,7 +2,7 @@
*
* libpolkit-rbac.c : RBAC implementation of the libpolkit API
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Licensed under the Academic Free License version 2.1
@@ -150,6 +150,17 @@ libpolkit_is_uid_allowed_for_privilege (LibPolKitContext *ctx,
authname = "solaris.device.mount.fixed";
} else if (strcmp (privilege, "hal-storage-fixed-mount-all-options") == 0) {
authname = "solaris.device.mount.alloptions.fixed";
+ } else if (strcmp(privilege, "hal-power-suspend") == 0) {
+ authname = "solaris.system.power.suspend.ram";
+ } else if (strcmp(privilege, "hal-power-hibernate") == 0) {
+ authname = "solaris.system.power.suspend.disk";
+ } else if ((strcmp(privilege, "hal-power-shutdown") == 0) ||
+ (strcmp(privilege, "hal-power-reboot") == 0)) {
+ authname = "solaris.system.shutdown";
+ } else if (strcmp(privilege, "hal-power-cpu") == 0) {
+ authname = "solaris.system.power.cpu";
+ } else if (strcmp(privilege, "hal-power-brightness") == 0) {
+ authname = "solaris.system.power.brightness";
} else {
/* replace '-' with '.' */
authname = g_strdup (privilege);
diff --git a/usr/src/pkgdefs/SUNW0on/prototype_com b/usr/src/pkgdefs/SUNW0on/prototype_com
index f6f01a4208..0baa381f90 100644
--- a/usr/src/pkgdefs/SUNW0on/prototype_com
+++ b/usr/src/pkgdefs/SUNW0on/prototype_com
@@ -308,6 +308,11 @@ f none usr/lib/help/auths/locale/PrintUnlabeled.html 444 root bin
f none usr/lib/help/auths/locale/TNDaemon.html 444 root bin
f none usr/lib/help/auths/locale/TNctl.html 444 root bin
f none usr/lib/help/auths/locale/ValueTND.html 444 root bin
+f none usr/lib/help/auths/locale/SysPowerMgmtHeader.html 444 root bin
+f none usr/lib/help/auths/locale/SysPowerMgmtSuspend.html 444 root bin
+f none usr/lib/help/auths/locale/SysPowerMgmtSuspendtoDisk.html 444 root bin
+f none usr/lib/help/auths/locale/SysPowerMgmtSuspendtoRAM.html 444 root bin
+f none usr/lib/help/auths/locale/SysPowerMgmtBrightness.html 444 root bin
#
d none usr/lib/help/profiles 755 root bin
d none usr/lib/help/profiles/locale 755 root bin
@@ -363,6 +368,11 @@ f none usr/lib/help/profiles/locale/RtIdmapNameRulesMngmnt.html 444 root bin
f none usr/lib/help/profiles/locale/RtInfoSec.html 444 root bin
f none usr/lib/help/profiles/locale/RtObjectLabelMngmnt.html 444 root bin
f none usr/lib/help/profiles/locale/RtOutsideAccred.html 444 root bin
+f none usr/lib/help/profiles/locale/RtSysPowerMgmt.html 444 root bin
+f none usr/lib/help/profiles/locale/RtSysPowerMgmtSuspend.html 444 root bin
+f none usr/lib/help/profiles/locale/RtSysPowerMgmtSuspendtoDisk.html 444 root bin
+f none usr/lib/help/profiles/locale/RtSysPowerMgmtSuspendtoRAM.html 444 root bin
+f none usr/lib/help/profiles/locale/RtSysPowerMgmtBrightness.html 444 root bin
#
#
# OCF Messages
diff --git a/usr/src/pkgdefs/SUNWckr/prototype_i386 b/usr/src/pkgdefs/SUNWckr/prototype_i386
index 426aec3901..e74fd2522b 100644
--- a/usr/src/pkgdefs/SUNWckr/prototype_i386
+++ b/usr/src/pkgdefs/SUNWckr/prototype_i386
@@ -68,8 +68,8 @@ f none kernel/dacf/net_dacf 755 root sys
f none kernel/devname/sdev_nsconfig_mod 755 root sys
f none kernel/drv/aggr 755 root sys
f none kernel/drv/arp 755 root sys
-f none kernel/drv/battery 755 root sys
-f none kernel/drv/battery.conf 644 root sys
+f none kernel/drv/acpi_drv 755 root sys
+f none kernel/drv/acpi_drv.conf 644 root sys
f none kernel/drv/bl 755 root sys
f none kernel/drv/bmc 755 root sys
f none kernel/drv/bmc.conf 644 root sys
@@ -279,7 +279,7 @@ f none kernel/devname/amd64/sdev_nsconfig_mod 755 root sys
d none kernel/drv/amd64 755 root sys
f none kernel/drv/amd64/aggr 755 root sys
f none kernel/drv/amd64/arp 755 root sys
-f none kernel/drv/amd64/battery 755 root sys
+f none kernel/drv/amd64/acpi_drv 755 root sys
f none kernel/drv/amd64/bl 755 root sys
f none kernel/drv/amd64/bmc 755 root sys
f none kernel/drv/amd64/bscbus 755 root sys
diff --git a/usr/src/pkgdefs/SUNWcsu/prototype_com b/usr/src/pkgdefs/SUNWcsu/prototype_com
index 483cc82a7b..64b01337b1 100644
--- a/usr/src/pkgdefs/SUNWcsu/prototype_com
+++ b/usr/src/pkgdefs/SUNWcsu/prototype_com
@@ -522,6 +522,11 @@ f none usr/lib/help/auths/locale/C/SmfIdmapStates.html 444 root bin
f none usr/lib/help/auths/locale/C/SmfValueIdmap.html 444 root bin
f none usr/lib/help/auths/locale/C/SmfValueVscan.html 0444 root bin
f none usr/lib/help/auths/locale/C/SmfVscanStates.html 0444 root bin
+f none usr/lib/help/auths/locale/C/SysPowerMgmtHeader.html 0444 root bin
+f none usr/lib/help/auths/locale/C/SysPowerMgmtSuspend.html 0444 root bin
+f none usr/lib/help/auths/locale/C/SysPowerMgmtSuspendtoDisk.html 0444 root bin
+f none usr/lib/help/auths/locale/C/SysPowerMgmtSuspendtoRAM.html 0444 root bin
+f none usr/lib/help/auths/locale/C/SysPowerMgmtBrightness.html 0444 root bin
d none usr/lib/help/profiles 755 root bin
d none usr/lib/help/profiles/locale 755 root bin
d none usr/lib/help/profiles/locale/C 755 root bin
@@ -574,6 +579,11 @@ f none usr/lib/help/profiles/locale/C/RtZoneMngmnt.html 444 root bin
f none usr/lib/help/profiles/locale/C/RtIdmapMngmnt.html 444 root bin
f none usr/lib/help/profiles/locale/C/RtIdmapNameRulesMngmnt.html 444 root bin
f none usr/lib/help/profiles/locale/C/RtVscanMngmnt.html 444 root bin
+f none usr/lib/help/profiles/locale/C/RtSysPowerMgmt.html 444 root bin
+f none usr/lib/help/profiles/locale/C/RtSysPowerMgmtSuspend.html 444 root bin
+f none usr/lib/help/profiles/locale/C/RtSysPowerMgmtSuspendtoDisk.html 444 root bin
+f none usr/lib/help/profiles/locale/C/RtSysPowerMgmtSuspendtoRAM.html 444 root bin
+f none usr/lib/help/profiles/locale/C/RtSysPowerMgmtBrightness.html 444 root bin
d none usr/lib/iconv 755 root bin
f none usr/lib/iconv/646da.8859.t 444 root bin
f none usr/lib/iconv/646de.8859.t 444 root bin
diff --git a/usr/src/pkgdefs/SUNWhal/prototype_com b/usr/src/pkgdefs/SUNWhal/prototype_com
index 2cc544a272..5f795202d4 100644
--- a/usr/src/pkgdefs/SUNWhal/prototype_com
+++ b/usr/src/pkgdefs/SUNWhal/prototype_com
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -50,12 +50,14 @@ f none usr/lib/hal/hald 555 root bin
f none usr/lib/hal/hald-addon-acpi 555 root bin
f none usr/lib/hal/hald-addon-network-discovery 555 root bin
f none usr/lib/hal/hald-addon-storage 555 root bin
-f none usr/lib/hal/hald-probe-battery 555 root bin
+f none usr/lib/hal/hald-probe-acpi 555 root bin
f none usr/lib/hal/hald-probe-network-printer 555 root bin
f none usr/lib/hal/hald-probe-printer 555 root bin
f none usr/lib/hal/hald-probe-storage 555 root bin
f none usr/lib/hal/hald-probe-volume 555 root bin
f none usr/lib/hal/hald-runner 555 root bin
+f none usr/lib/hal/hal-functions 555 root bin
+f none usr/lib/hal/hal-is-caller-privileged 555 root bin
f none usr/lib/hal/hal-storage-closetray 555 root bin
f none usr/lib/hal/hal-storage-eject 555 root bin
f none usr/lib/hal/hal-storage-mount 555 root bin
@@ -64,6 +66,19 @@ f none usr/lib/hal/hal-storage-cleanup-mountpoint 555 root bin
f none usr/lib/hal/hal-storage-cleanup-all-mountpoints 555 root bin
f none usr/lib/hal/hal-storage-zpool-export 555 root bin
f none usr/lib/hal/hal-storage-zpool-import 555 root bin
+f none usr/lib/hal/hal-system-lcd-get-brightness 555 root bin
+f none usr/lib/hal/hal-system-lcd-set-brightness 555 root bin
+f none usr/lib/hal/hal-system-power-hibernate 555 root bin
+f none usr/lib/hal/hal-system-power-reboot 555 root bin
+f none usr/lib/hal/hal-system-power-shutdown 555 root bin
+f none usr/lib/hal/hal-system-power-suspend 555 root bin
+d none usr/lib/hal/sunos 755 root bin
+f none usr/lib/hal/sunos/hal-system-lcd-get-brightness-sunos 555 root bin
+f none usr/lib/hal/sunos/hal-system-lcd-set-brightness-sunos 555 root bin
+f none usr/lib/hal/sunos/hal-system-power-hibernate-sunos 555 root bin
+f none usr/lib/hal/sunos/hal-system-power-reboot-sunos 555 root bin
+f none usr/lib/hal/sunos/hal-system-power-shutdown-sunos 555 root bin
+f none usr/lib/hal/sunos/hal-system-power-suspend-sunos 555 root bin
s none usr/lib/libhal.so=./libhal.so.1.0.0
s none usr/lib/libhal.so.1=./libhal.so.1.0.0
f none usr/lib/libhal.so.1.0.0 755 root bin
diff --git a/usr/src/pkgdefs/SUNWhalr/prototype_com b/usr/src/pkgdefs/SUNWhalr/prototype_com
index 9cbe319b4f..8452322a9f 100644
--- a/usr/src/pkgdefs/SUNWhalr/prototype_com
+++ b/usr/src/pkgdefs/SUNWhalr/prototype_com
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -66,7 +66,6 @@ d none etc/hal/fdi/information/20thirdparty 755 root bin
d none etc/hal/fdi/information/30user 755 root bin
d none etc/hal/fdi/policy 755 root bin
d none etc/hal/fdi/policy/10osvendor 755 root bin
-f none etc/hal/fdi/policy/10osvendor/10-keyboard-policy.fdi 444 root bin
f none etc/hal/fdi/policy/10osvendor/10-laptop-panel-mgmt-policy.fdi 444 root bin
f none etc/hal/fdi/policy/10osvendor/10-network-attached.fdi 444 root bin
f none etc/hal/fdi/policy/10osvendor/10-power-mgmt-policy.fdi 444 root bin
diff --git a/usr/src/pkgdefs/SUNWhea/prototype_com b/usr/src/pkgdefs/SUNWhea/prototype_com
index cc72136ac2..d41415c209 100644
--- a/usr/src/pkgdefs/SUNWhea/prototype_com
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com
@@ -655,7 +655,7 @@ f none usr/include/sys/auxv_SPARC.h 644 root bin
f none usr/include/sys/avintr.h 644 root bin
f none usr/include/sys/avl.h 644 root bin
f none usr/include/sys/avl_impl.h 644 root bin
-f none usr/include/sys/battery.h 644 root bin
+f none usr/include/sys/acpi_drv.h 644 root bin
f none usr/include/sys/bitmap.h 644 root bin
f none usr/include/sys/bitset.h 644 root bin
f none usr/include/sys/bl.h 644 root bin
@@ -1253,7 +1253,6 @@ f none usr/include/sys/sysconf.h 644 root bin
f none usr/include/sys/sysconfig.h 644 root bin
f none usr/include/sys/sysconfig_impl.h 644 root bin
d none usr/include/sys/sysevent 755 root bin
-f none usr/include/sys/sysevent/acpiev.h 644 root bin
f none usr/include/sys/sysevent/ap_driver.h 644 root bin
f none usr/include/sys/sysevent/domain.h 644 root bin
f none usr/include/sys/sysevent/dr.h 644 root bin
@@ -1261,6 +1260,7 @@ f none usr/include/sys/sysevent/env.h 644 root bin
f none usr/include/sys/sysevent/eventdefs.h 644 root bin
f none usr/include/sys/sysevent/ipmp.h 644 root bin
f none usr/include/sys/sysevent/dev.h 644 root bin
+f none usr/include/sys/sysevent/pwrctl.h 644 root bin
f none usr/include/sys/sysevent/svm.h 644 root bin
f none usr/include/sys/sysevent.h 644 root bin
f none usr/include/sys/sysevent_impl.h 644 root bin
diff --git a/usr/src/pkgdefs/common_files/i.minorperm_i386 b/usr/src/pkgdefs/common_files/i.minorperm_i386
index 7ae8205f64..21e7979017 100644
--- a/usr/src/pkgdefs/common_files/i.minorperm_i386
+++ b/usr/src/pkgdefs/common_files/i.minorperm_i386
@@ -319,7 +319,7 @@ physmem:*
asy:*
asy:*,cu
ucode:*
-battery:*
+acpi_drv:*
smbsrv:*
vscan:*
nsmb:*
diff --git a/usr/src/uts/common/io/power.c b/usr/src/uts/common/io/power.c
index e87922ce84..cef95d8c44 100644
--- a/usr/src/uts/common/io/power.c
+++ b/usr/src/uts/common/io/power.c
@@ -1,4 +1,3 @@
-
/*
* CDDL HEADER START
*
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -58,6 +57,8 @@
#include <sys/stat.h>
#include <sys/poll.h>
#include <sys/pbio.h>
+#include <sys/sysevent/eventdefs.h>
+#include <sys/sysevent/pwrctl.h>
#if defined(__sparc)
#include <sys/machsystm.h>
@@ -175,6 +176,8 @@ struct power_soft_state {
#endif
};
+static void power_gen_sysevent(struct power_soft_state *);
+
#ifdef ACPI_POWER_BUTTON
static int power_attach_acpi(struct power_soft_state *softsp);
static void power_detach_acpi(struct power_soft_state *softsp);
@@ -224,7 +227,7 @@ static struct dev_ops power_ops = {
static struct modldrv modldrv = {
&mod_driverops, /* Type of module. This one is a driver */
- "power button driver v%I%", /* name of module */
+ "power button driver", /* name of module */
&power_ops, /* driver ops */
};
@@ -442,14 +445,14 @@ power_high_intr(caddr_t arg)
if (hasEPIC) {
/* read isr - first issue command */
EPIC_WR(hdl, softsp->power_btn_reg,
- EPIC_ATOM_INTR_READ);
+ EPIC_ATOM_INTR_READ);
/* next, read the reg */
EPIC_RD(hdl, softsp->power_btn_reg, reg);
if (reg & EPIC_FIRE_INTERRUPT) { /* PB pressed */
/* clear the interrupt */
EPIC_WR(hdl, softsp->power_btn_reg,
- EPIC_ATOM_INTR_CLEAR);
+ EPIC_ATOM_INTR_CLEAR);
} else {
if (!softsp->power_btn_ioctl) {
mutex_exit(&softsp->power_intr_mutex);
@@ -678,6 +681,7 @@ power_issue_shutdown(caddr_t arg)
mutex_exit(&softsp->power_mutex);
pollwakeup(&softsp->pollhd, POLLRDNORM);
pollwakeup(&softsp->pollhd, POLLIN);
+ power_gen_sysevent(softsp);
return (DDI_INTR_CLAIMED);
}
@@ -699,6 +703,59 @@ power_issue_shutdown(caddr_t arg)
return (DDI_INTR_CLAIMED);
}
+static void
+power_gen_sysevent(struct power_soft_state *softsp)
+{
+ nvlist_t *attr_list = NULL;
+ int err;
+ char pathname[MAXPATHLEN];
+ char hid[9] = "\0";
+
+ /* Allocate and build sysevent attribute list */
+ err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, DDI_NOSLEEP);
+ if (err != 0) {
+ cmn_err(CE_WARN,
+ "cannot allocate memory for sysevent attributes\n");
+ return;
+ }
+
+#ifdef ACPI_POWER_BUTTON
+ /* Only control method power button has HID */
+ if (softsp->gpe_attached) {
+ (void) strlcpy(hid, "PNP0C0C", sizeof (hid));
+ }
+#endif
+
+ err = nvlist_add_string(attr_list, PWRCTL_DEV_HID, hid);
+ if (err != 0) {
+ cmn_err(CE_WARN,
+ "Failed to add attr [%s] for %s/%s event",
+ PWRCTL_DEV_HID, EC_PWRCTL, ESC_PWRCTL_POWER_BUTTON);
+ nvlist_free(attr_list);
+ return;
+ }
+
+ (void) ddi_pathname(softsp->dip, pathname);
+ err = nvlist_add_string(attr_list, PWRCTL_DEV_PHYS_PATH, pathname);
+ if (err != 0) {
+ cmn_err(CE_WARN,
+ "Failed to add attr [%s] for %s/%s event",
+ PWRCTL_DEV_PHYS_PATH, EC_PWRCTL, ESC_PWRCTL_POWER_BUTTON);
+ nvlist_free(attr_list);
+ return;
+ }
+
+ /* Generate/log sysevent */
+ err = ddi_log_sysevent(softsp->dip, DDI_VENDOR_SUNW, EC_PWRCTL,
+ ESC_PWRCTL_POWER_BUTTON, attr_list, NULL, DDI_NOSLEEP);
+ if (err != DDI_SUCCESS) {
+ cmn_err(CE_WARN,
+ "cannot log sysevent, err code %x\n", err);
+ }
+
+ nvlist_free(attr_list);
+}
+
/*
* Open the device.
*/
@@ -1097,8 +1154,8 @@ power_setup_epic_regs(dev_info_t *dip, struct power_soft_state *softsp)
attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
if (ddi_regs_map_setup(dip, 0, (caddr_t *)&reg_base,
- EPIC_REGS_OFFSET, EPIC_REGS_LEN, &attr,
- &softsp->power_rhandle) != DDI_SUCCESS) {
+ EPIC_REGS_OFFSET, EPIC_REGS_LEN, &attr,
+ &softsp->power_rhandle) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
@@ -1107,11 +1164,11 @@ power_setup_epic_regs(dev_info_t *dip, struct power_soft_state *softsp)
/* Clear power button interrupt first */
EPIC_WR(softsp->power_rhandle, softsp->power_btn_reg,
- EPIC_ATOM_INTR_CLEAR);
+ EPIC_ATOM_INTR_CLEAR);
/* Enable EPIC interrupt for power button single press event */
EPIC_WR(softsp->power_rhandle, softsp->power_btn_reg,
- EPIC_ATOM_INTR_ENABLE);
+ EPIC_ATOM_INTR_ENABLE);
/*
* At this point, EPIC interrupt processing is fully initialised.
@@ -1165,7 +1222,7 @@ power_setup_mbc_regs(dev_info_t *dip, struct power_soft_state *softsp)
attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
if (ddi_regs_map_setup(dip, 0, (caddr_t *)&reg_base, 0, 0, &attr,
- &softsp->power_rhandle) != DDI_SUCCESS) {
+ &softsp->power_rhandle) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
softsp->power_btn_reg = &reg_base[FIRE_SSI_ISR];
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index d0d531088f..400cf12915 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -73,6 +73,7 @@ GENHDRS= \
priv_names.h
CHKHDRS= \
+ acpi_drv.h \
acct.h \
acctctl.h \
acl.h \
@@ -97,7 +98,6 @@ CHKHDRS= \
auxv_SPARC.h \
avl.h \
avl_impl.h \
- battery.h \
bitmap.h \
bitset.h \
bl.h \
@@ -882,7 +882,6 @@ SATAGENHDRS= \
sata_cfgadm.h
SYSEVENTHDRS= \
- acpiev.h \
ap_driver.h \
dev.h \
domain.h \
@@ -890,6 +889,7 @@ SYSEVENTHDRS= \
env.h \
eventdefs.h \
ipmp.h \
+ pwrctl.h \
svm.h
CONTRACTHDRS= \
diff --git a/usr/src/uts/common/sys/battery.h b/usr/src/uts/common/sys/acpi_drv.h
index 1cc22d8ebd..7867348d52 100644
--- a/usr/src/uts/common/sys/battery.h
+++ b/usr/src/uts/common/sys/acpi_drv.h
@@ -20,12 +20,12 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#ifndef _BATTERY_H
-#define _BATTERY_H
+#ifndef _ACPI_DRV_H
+#define _ACPI_DRV_H
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -34,19 +34,23 @@ extern "C" {
#endif
#include <sys/param.h>
-
-#define _BATT_DRV (('B' << 24) + ('A' << 16) + ('T' << 8))
-
-#define BATT_IOC_BAY (_BATT_DRV | 0)
-#define BATT_IOC_INFO (_BATT_DRV | 1)
-#define BATT_IOC_STATUS (_BATT_DRV | 2)
-#define BATT_IOC_AC_COUNT (_BATT_DRV | 3)
-#define BATT_IOC_POWER_STATUS (_BATT_DRV | 4)
-#define BATT_IOC_SET_WARNING (_BATT_DRV | 5)
-#define BATT_IOC_GET_WARNING (_BATT_DRV | 6)
-
-#define BATT_BST_CHARGING 2
-#define BATT_BST_DISCHARGING 1
+#include <sys/kstat.h>
+
+enum acpi_drv_ioctl {
+ ACPI_DRV_IOC_BAY,
+ ACPI_DRV_IOC_INFO,
+ ACPI_DRV_IOC_STATUS,
+ ACPI_DRV_IOC_AC_COUNT,
+ ACPI_DRV_IOC_POWER_STATUS,
+ ACPI_DRV_IOC_SET_WARNING,
+ ACPI_DRV_IOC_GET_WARNING,
+ ACPI_DRV_IOC_LID_STATUS,
+ ACPI_DRV_IOC_LEVELS,
+ ACPI_DRV_IOC_SET_BRIGHTNESS
+};
+
+#define ACPI_DRV_BST_CHARGING 2
+#define ACPI_DRV_BST_DISCHARGING 1
typedef struct batt_bay {
/* Total number of bays in the system */
@@ -125,17 +129,17 @@ typedef struct acpi_bst {
} acpi_bst_t;
/* Battery warnning levels in percentage */
-typedef struct batt_warn {
+typedef struct acpi_drv_warn {
uint32_t bw_enabled; /* Enabled */
uint32_t bw_charge_warn; /* charge warn threshold */
uint32_t bw_charge_low; /* charge low threshold */
-} batt_warn_t;
+} acpi_drv_warn_t;
-#define BATT_DRV_NAME "battery"
-#define BATT_POWER_KSTAT_NAME "power"
-#define BATT_BTWARN_KSTAT_NAME "battery warning"
-#define BATT_BIF_KSTAT_NAME "battery BIF"
-#define BATT_BST_KSTAT_NAME "battery BST"
+#define ACPI_DRV_NAME "acpi_drv"
+#define ACPI_DRV_POWER_KSTAT_NAME "power"
+#define ACPI_DRV_BTWARN_KSTAT_NAME "battery warning"
+#define ACPI_DRV_BIF_KSTAT_NAME "battery BIF"
+#define ACPI_DRV_BST_KSTAT_NAME "battery BST"
#define AC "AC"
#define BATTERY "battery"
@@ -167,44 +171,62 @@ typedef struct batt_warn {
#define PSR_AC_PRESENT "psr_ac_present"
-typedef struct batt_power_kstat_s {
- struct kstat_named batt_power;
- struct kstat_named batt_supported_battery_count;
-} batt_power_kstat_t;
+typedef struct acpi_drv_power_kstat_s {
+ struct kstat_named acpi_drv_power;
+ struct kstat_named acpi_drv_supported_battery_count;
+} acpi_drv_power_kstat_t;
-typedef struct batt_warn_kstat_s {
- struct kstat_named batt_bw_enabled;
- struct kstat_named batt_bw_charge_warn;
- struct kstat_named batt_bw_charge_low;
-} batt_warn_kstat_t;
+typedef struct acpi_drv_warn_kstat_s {
+ struct kstat_named acpi_drv_bw_enabled;
+ struct kstat_named acpi_drv_bw_charge_warn;
+ struct kstat_named acpi_drv_bw_charge_low;
+} acpi_drv_warn_kstat_t;
/* BIF kstat */
-typedef struct batt_bif_kstat_s {
- struct kstat_named batt_bif_unit;
- struct kstat_named batt_bif_design_cap;
- struct kstat_named batt_bif_last_cap;
- struct kstat_named batt_bif_tech;
- struct kstat_named batt_bif_voltage;
- struct kstat_named batt_bif_warn_cap;
- struct kstat_named batt_bif_low_cap;
- struct kstat_named batt_bif_gran1_cap;
- struct kstat_named batt_bif_gran2_cap;
- struct kstat_named batt_bif_model;
- struct kstat_named batt_bif_serial;
- struct kstat_named batt_bif_type;
- struct kstat_named batt_bif_oem_info;
-} batt_bif_kstat_t;
+typedef struct acpi_drv_bif_kstat_s {
+ struct kstat_named acpi_drv_bif_unit;
+ struct kstat_named acpi_drv_bif_design_cap;
+ struct kstat_named acpi_drv_bif_last_cap;
+ struct kstat_named acpi_drv_bif_tech;
+ struct kstat_named acpi_drv_bif_voltage;
+ struct kstat_named acpi_drv_bif_warn_cap;
+ struct kstat_named acpi_drv_bif_low_cap;
+ struct kstat_named acpi_drv_bif_gran1_cap;
+ struct kstat_named acpi_drv_bif_gran2_cap;
+ struct kstat_named acpi_drv_bif_model;
+ struct kstat_named acpi_drv_bif_serial;
+ struct kstat_named acpi_drv_bif_type;
+ struct kstat_named acpi_drv_bif_oem_info;
+} acpi_drv_bif_kstat_t;
/* BST kstat */
-typedef struct batt_bst_kstat_s {
- struct kstat_named batt_bst_state;
- struct kstat_named batt_bst_rate;
- struct kstat_named batt_bst_rem_cap;
- struct kstat_named batt_bst_voltage;
-} batt_bst_kstat_t;
+typedef struct acpi_drv_bst_kstat_s {
+ struct kstat_named acpi_drv_bst_state;
+ struct kstat_named acpi_drv_bst_rate;
+ struct kstat_named acpi_drv_bst_rem_cap;
+ struct kstat_named acpi_drv_bst_voltage;
+} acpi_drv_bst_kstat_t;
+
+struct acpi_drv_display_info {
+ int noutput; /* number of output devices */
+ int sw_on;
+ int bright_on;
+};
+
+struct acpi_drv_output_info {
+ uint32_t adr; /* unique ID for this output device */
+ int nlev; /* number of brightness levels */
+};
+
+struct acpi_drv_output_status {
+ int state;
+ int num_levels;
+ int cur_level;
+ int cur_level_index;
+};
#ifdef __cplusplus
}
#endif
-#endif /* _BATTERY_H */
+#endif /* _ACPI_DRV_H */
diff --git a/usr/src/uts/common/sys/sysevent/eventdefs.h b/usr/src/uts/common/sys/sysevent/eventdefs.h
index a6abf8b966..fcb3ab18f5 100644
--- a/usr/src/uts/common/sys/sysevent/eventdefs.h
+++ b/usr/src/uts/common/sys/sysevent/eventdefs.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -208,14 +208,17 @@ extern "C" {
#define ESC_PLATFORM_SP_RESET "ESC_platform_sp_reset"
/*
- * EC_ACPIEV subclass definitions
+ * EC_PWRCTL subclass definitions
*/
-#define EC_ACPIEV "EC_acpiev"
-#define ESC_ACPIEV_ADD "ESC_acpiev_add"
-#define ESC_ACPIEV_REMOVE "ESC_acpiev_remove"
-#define ESC_ACPIEV_WARN "ESC_acpiev_warn"
-#define ESC_ACPIEV_LOW "ESC_acpiev_low"
-#define ESC_ACPIEV_STATE_CHANGE "ESC_acpiev_state_change"
+#define EC_PWRCTL "EC_pwrctl"
+#define ESC_PWRCTL_ADD "ESC_pwrctl_add"
+#define ESC_PWRCTL_REMOVE "ESC_pwrctl_remove"
+#define ESC_PWRCTL_WARN "ESC_pwrctl_warn"
+#define ESC_PWRCTL_LOW "ESC_pwrctl_low"
+#define ESC_PWRCTL_STATE_CHANGE "ESC_pwrctl_state_change"
+#define ESC_PWRCTL_POWER_BUTTON "ESC_pwrctl_power_button"
+#define ESC_PWRCTL_BRIGHTNESS_UP "ESC_pwrctl_brightness_up"
+#define ESC_PWRCTL_BRIGHTNESS_DOWN "ESC_pwrctl_brightness_down"
/*
* ZFS subclass definitions. supporting attributes (name/value paris) are found
diff --git a/usr/src/uts/common/sys/sysevent/acpiev.h b/usr/src/uts/common/sys/sysevent/pwrctl.h
index 6c1ea0fa0c..9293c7525e 100644
--- a/usr/src/uts/common/sys/sysevent/acpiev.h
+++ b/usr/src/uts/common/sys/sysevent/pwrctl.h
@@ -19,12 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#ifndef _SYS_SYSEVENT_ACPIEV_H
-#define _SYS_SYSEVENT_ACPIEV_H
+#ifndef _SYS_SYSEVENT_PWRCTL_H
+#define _SYS_SYSEVENT_PWRCTL_H
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -33,21 +33,24 @@ extern "C" {
#endif
/*
- * Event type schema for EC_ACPIEV:
- * Event Class - EC_ACPIEV
- * Event Sub-Class - ESC_ACPIEV_ADD |
- * ESC_ACPIEV_REMOVE |
- * ESC_ACPIEV_WARN |
- * ESC_ACPIEV_LOW |
- * ESC_ACPIEV_STATE_CHANGE
+ * Event type schema for EC_PWRCTL:
+ * Event Class - EC_PWRCTL
+ * Event Sub-Class - ESC_PWRCTL_ADD |
+ * ESC_PWRCTL_REMOVE |
+ * ESC_PWRCTL_WARN |
+ * ESC_PWRCTL_LOW |
+ * ESC_PWRCTL_STATE_CHANGE |
+ * ESC_PWRCTL_POWER_BUTTON |
+ * ESC_PWRCTL_BRIGHTNESS_UP |
+ * ESC_PWRCTL_BRIGHTNESS_DOWN
* Event Publisher - SUNW:kern:[environmental monitor name]
- * Attribute Name - ACPIEV_VERSION
+ * Attribute Name - PWRCTL_VERSION
* Attribute Type - SE_DATA_TYPE_UINT32
* Attribute Value - [version of the schema]
- * Attribute Name - ACPIEV_DEV_HID
+ * Attribute Name - PWRCTL_DEV_HID
* Attribute Type - SE_DATA_TYPE_STRING
* Attribute Value - [Label identifying the ACPI hardware]
- * Attribute Name - ACPIEV_DEV_UID
+ * Attribute Name - PWRCTL_DEV_UID
* Attribute Type - SE_DATA_TYPE_STRING
* Attribute Value - [Both the _HID and _UID values can be of either type
* STRING or NUMBER in the ACPI tables. In order to
@@ -55,25 +58,26 @@ extern "C" {
* interface, these values are always returned as NULL
* terminated strings, regardless of the original data
* type in the source ACPI table.]
- * Attribute Name - ACPIEV_DEV_INDEX
+ * Attribute Name - PWRCTL_DEV_INDEX
* Attribute Type - SE_DATA_TYPE_UINT32
* Attribute Value - [Device index]
*
- * ESC_ACPIEV_WARN, ESC_ACPIEV_LOW only field:
- * Attribute Name - ACPIEV_CHARGE_LEVEL
+ * ESC_PWRCTL_WARN, ESC_PWRCTL_LOW only field:
+ * Attribute Name - PWRCTL_CHARGE_LEVEL
* Attribute Type - SE_DATA_TYPE_UINT32
* Attribute Value - [charge level]
*/
-#define ACPIEV_VERSION "acpiev_version" /* Version of the schema */
-#define ACPIEV_DEV_PHYS_PATH "acpiev_dev_phys_path" /* Physical Path */
-#define ACPIEV_DEV_HID "acpiev_dev_hid" /* ACPI device Hardware Id */
-#define ACPIEV_DEV_UID "acpiev_dev_uid" /* ACPI device Unique Id */
-#define ACPIEV_DEV_INDEX "acpiev_dev_index" /* Device index */
-#define ACPIEV_CHARGE_LEVEL "acpiev_charge_level" /* Event related state */
+#define PWRCTL_VERSION "pwrctl_version" /* Version of the schema */
+#define PWRCTL_DEV_PHYS_PATH "pwrctl_dev_phys_path" /* Physical Path */
+#define PWRCTL_DEV_HID "pwrctl_dev_hid" /* ACPI device Hardware Id */
+#define PWRCTL_DEV_UID "pwrctl_dev_uid" /* ACPI device Unique Id */
+#define PWRCTL_DEV_INDEX "pwrctl_dev_index" /* Device index */
+#define PWRCTL_CHARGE_LEVEL "pwrctl_charge_level" /* Event related state */
+#define PWRCTL_BRIGHTNESS_LEVEL "pwrctl_brightness_level"
#ifdef __cplusplus
}
#endif
-#endif /* _SYS_SYSEVENT_ACPIEV_H */
+#endif /* _SYS_SYSEVENT_PWRCTL_H */
diff --git a/usr/src/uts/i86pc/Makefile.files b/usr/src/uts/i86pc/Makefile.files
index 8ec4d23a1e..5ae521c687 100644
--- a/usr/src/uts/i86pc/Makefile.files
+++ b/usr/src/uts/i86pc/Makefile.files
@@ -168,7 +168,7 @@ PCI_E_NEXUS_OBJS += pci_common.o pci_kstats.o pci_tools.o
PCINEXUS_OBJS += pci.o pci_common.o pci_kstats.o pci_tools.o
PCPLUSMP_OBJS += apic.o psm_common.o apic_introp.o mp_platform_common.o
-BATTERY_OBJS += battery.o
+ACPI_DRV_OBJS += acpi_drv.o
include $(SRC)/common/mc/mc-amd/Makefile.mcamd
MCAMD_OBJS += \
$(MCAMD_CMN_OBJS) \
diff --git a/usr/src/uts/i86pc/Makefile.i86pc.shared b/usr/src/uts/i86pc/Makefile.i86pc.shared
index 18bc7610e2..1e1c6abe1d 100644
--- a/usr/src/uts/i86pc/Makefile.i86pc.shared
+++ b/usr/src/uts/i86pc/Makefile.i86pc.shared
@@ -256,7 +256,7 @@ DRV_KMODS += pci-ide
DRV_KMODS += xsvc
DRV_KMODS += mc-amd
DRV_KMODS += tzmon
-DRV_KMODS += battery
+DRV_KMODS += acpi_drv
DRV_KMODS += cpudrv
diff --git a/usr/src/uts/i86pc/Makefile.rules b/usr/src/uts/i86pc/Makefile.rules
index a411dd1ad5..78d3832d9b 100644
--- a/usr/src/uts/i86pc/Makefile.rules
+++ b/usr/src/uts/i86pc/Makefile.rules
@@ -69,7 +69,7 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
-$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/battery/%.c
+$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpi_drv/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -256,7 +256,7 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/intel_nb5000/%.c
$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
-$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/battery/%.c
+$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpi_drv/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/mc/%.c
diff --git a/usr/src/uts/i86pc/battery/Makefile b/usr/src/uts/i86pc/acpi_drv/Makefile
index 0e95fd9dca..b1aafef9b2 100644
--- a/usr/src/uts/i86pc/battery/Makefile
+++ b/usr/src/uts/i86pc/acpi_drv/Makefile
@@ -20,14 +20,14 @@
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
-# This makefile drives the production of the battery
-# Battery Monitor driver kernel module.
+# This makefile drives the production of the acpi_drv
+# driver kernel module.
#
# i86pc architecture dependent
#
@@ -40,11 +40,11 @@ UTSBASE = ../..
#
# Define the module and object file sets.
#
-MODULE = battery
-OBJECTS = $(BATTERY_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(BATTERY_OBJS:%.o=$(LINTS_DIR)/%.ln)
+MODULE = acpi_drv
+OBJECTS = $(ACPI_DRV_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(ACPI_DRV_OBJS:%.o=$(LINTS_DIR)/%.ln)
ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR = $(UTSBASE)/i86pc/io/battery
+CONF_SRCDIR = $(UTSBASE)/i86pc/io/acpi_drv
#
# Include common rules.
diff --git a/usr/src/uts/i86pc/io/acpi_drv/acpi_drv.c b/usr/src/uts/i86pc/io/acpi_drv/acpi_drv.c
new file mode 100644
index 0000000000..3017184b41
--- /dev/null
+++ b/usr/src/uts/i86pc/io/acpi_drv/acpi_drv.c
@@ -0,0 +1,2548 @@
+/*
+ * 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 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Driver for ACPI Battery, Lid, and LCD Monitoring and Control
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/conf.h>
+#include <sys/modctl.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stat.h>
+#include <sys/sysevent/eventdefs.h>
+#include <sys/sysevent/pwrctl.h>
+#include <sys/reboot.h>
+#include <sys/sysmacros.h>
+#include <sys/acpi/acpi.h>
+#include <sys/acpica.h>
+#include <sys/note.h>
+#include <sys/acpi_drv.h>
+
+
+#define ACPI_DRV_MOD_STRING "ACPI driver"
+
+#define MINOR_SHIFT 8
+#define IDX_MASK ((1 << MINOR_SHIFT) - 1)
+#define MINOR_BATT(idx) (ACPI_DRV_TYPE_CBAT << MINOR_SHIFT | \
+ (idx))
+#define MINOR_AC(idx) (ACPI_DRV_TYPE_AC << MINOR_SHIFT | \
+ (idx))
+#define MINOR_LID(idx) (ACPI_DRV_TYPE_LID << MINOR_SHIFT | \
+ (idx))
+#define MINOR_DISPLAY(idx) (ACPI_DRV_TYPE_DISPLAY << MINOR_SHIFT \
+ | (idx))
+#define MINOR_OUTPUT(idx) (ACPI_DRV_TYPE_OUTPUT << MINOR_SHIFT | \
+ (idx))
+#define MINOR2IDX(minor) ((minor) & IDX_MASK)
+#define MINOR2TYPE(minor) ((minor) >> MINOR_SHIFT)
+
+#define ACPI_DRV_OK (0)
+#define ACPI_DRV_ERR (1)
+
+#define ACPI_DRV_MAX_BAT_NUM 8
+#define ACPI_DRV_MAX_AC_NUM 10
+#define ACPI_DRV_MAX_OUTPUT_NUM 5
+
+#define BST_FLAG_DISCHARGING (0x1)
+#define BST_FLAG_CHARGING (0x2)
+#define BST_FLAG_CRITICAL (0x4)
+
+/* Set if the battery is present */
+#define STA_FLAG_BATT_PRESENT (0x10)
+
+#define ACPI_DEVNAME_CBAT "PNP0C0A"
+#define ACPI_DEVNAME_SBAT "ACPI0002"
+#define ACPI_DEVNAME_AC "ACPI0003"
+#define ACPI_DEVNAME_LID "PNP0C0D"
+
+#define ACPI_DRV_EVENTS (POLLIN | POLLRDNORM)
+
+#ifdef DEBUG
+
+#define ACPI_DRV_PRINT_BUFFER_SIZE 512
+static char acpi_drv_prt_buf[ACPI_DRV_PRINT_BUFFER_SIZE];
+static kmutex_t acpi_drv_prt_mutex;
+
+static int acpi_drv_debug = 0;
+#define ACPI_DRV_DBG(lev, devp, ...) \
+ do { \
+ if (acpi_drv_debug) acpi_drv_printf((devp), \
+(lev), __VA_ARGS__); \
+_NOTE(CONSTCOND) } while (0)
+#define ACPI_DRV_PRT_NOTIFY(hdl, val) \
+ do { \
+ if (acpi_drv_debug) acpi_drv_prt_notify((hdl), (val)); \
+_NOTE(CONSTCOND) } while (0)
+
+#else
+
+#define ACPI_DRV_DBG(lev, devp, ...)
+#define ACPI_DRV_PRT_NOTIFY(hdl, val)
+
+#endif /* DEBUG */
+
+/* ACPI notify types */
+enum acpi_drv_notify {
+ ACPI_DRV_NTF_UNKNOWN = -1, /* No notifications seen, ever. */
+ ACPI_DRV_NTF_CHANGED,
+ ACPI_DRV_NTF_OK
+};
+
+/* Battery device types */
+enum acpi_drv_type {
+ ACPI_DRV_TYPE_UNKNOWN,
+ ACPI_DRV_TYPE_CBAT,
+ ACPI_DRV_TYPE_AC,
+ ACPI_DRV_TYPE_SBAT,
+ ACPI_DRV_TYPE_LID,
+ ACPI_DRV_TYPE_DISPLAY,
+ ACPI_DRV_TYPE_OUTPUT
+};
+
+struct acpi_drv_dev {
+ ACPI_HANDLE hdl;
+ char hid[9]; /* ACPI HardwareId */
+ char uid[9]; /* ACPI UniqueId */
+ ACPI_INTEGER adr; /* Bus device Id */
+ int valid; /* the device state is valid */
+
+ /*
+ * Unlike most other devices, when a battery is inserted or
+ * removed from the system, the device itself(the battery bay)
+ * is still considered to be present in the system.
+ *
+ * Value:
+ * 0 -- On-line
+ * 1 -- Off-line
+ * -1 -- Unknown
+ */
+ int present;
+ enum acpi_drv_type type;
+ int index; /* device index */
+ int minor;
+
+ struct acpi_drv_output_state *op;
+ struct acpi_drv_display_state *dp;
+};
+
+static int acpi_drv_dev_present(struct acpi_drv_dev *);
+#define acpi_drv_ac_present(a) (((a)->dev.type == ACPI_DRV_TYPE_AC) ? \
+ acpi_drv_dev_present(&(a)->dev) : -1)
+#define acpi_drv_cbat_present(a) (((a)->dev.type == ACPI_DRV_TYPE_CBAT) \
+ ? acpi_drv_dev_present(&(a)->dev) : -1)
+
+static dev_info_t *acpi_drv_dip = NULL;
+static kmutex_t acpi_drv_mutex;
+static struct pollhead acpi_drv_pollhead;
+
+/* Control Method Battery state */
+struct acpi_drv_cbat_state {
+ struct acpi_drv_dev dev;
+ /* Caches of _BST and _BIF */
+ enum acpi_drv_notify bat_bifok;
+ acpi_bif_t bif_cache;
+ enum acpi_drv_notify bat_bstok;
+ acpi_bst_t bst_cache;
+
+ uint32_t charge_warn;
+ uint32_t charge_low;
+
+ kstat_t *bat_bif_ksp;
+ kstat_t *bat_bst_ksp;
+} acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
+static int nbat;
+
+/*
+ * Synthesis battery state
+ * When there are multiple batteries present, the battery subsystem
+ * is not required to perform any synthesis of a composite battery
+ * from the data of the separate batteries. In cases where the
+ * battery subsystem does not synthesize a composite battery from
+ * the separate battery's data, the OS must provide that synthesis.
+ */
+static uint32_t acpi_drv_syn_rem_cap;
+static uint32_t acpi_drv_syn_last_cap;
+static uint32_t acpi_drv_syn_oem_warn_cap;
+static uint32_t acpi_drv_syn_oem_low_cap;
+
+static int acpi_drv_warn_enabled;
+static uint32_t acpi_drv_syn_warn_per;
+static uint32_t acpi_drv_syn_low_per;
+static uint32_t acpi_drv_syn_warn_cap;
+static uint32_t acpi_drv_syn_low_cap;
+/* Tracking boundery passing of _BST charge levels */
+static uint32_t acpi_drv_syn_last_level;
+
+/* AC state */
+static struct acpi_drv_ac_state {
+ struct acpi_drv_dev dev;
+} acpi_drv_ac[ACPI_DRV_MAX_AC_NUM];
+static int nac;
+
+/*
+ * Current power source device
+ * Note: assume only one device can be the power source device.
+ */
+static int acpi_drv_psr_type = ACPI_DRV_TYPE_UNKNOWN;
+static struct acpi_drv_dev *acpi_drv_psr_devp = NULL;
+
+/* Smart Battery state */
+static struct acpi_drv_sbat_state {
+ struct acpi_drv_dev dev;
+} acpi_drv_sbat;
+
+struct obj_desc {
+ char *name;
+ int offset;
+ int size;
+ int type;
+};
+
+/* Object copy definitions */
+#define OFFSETOF(s, m) ((size_t)(&(((s *)0)->m)))
+#define SIZEOF(s, m) (sizeof (((s *)0)->m))
+#define FIELD(n, s, m, t) \
+ { n, OFFSETOF(s, m), SIZEOF(s, m), t }
+#define FIELD_NULL { NULL, -1, 0, ACPI_TYPE_ANY }
+
+static struct obj_desc bif_desc[] = {
+ FIELD("bif_unit", acpi_bif_t, bif_unit, ACPI_TYPE_INTEGER),
+ FIELD("bif_design_cap", acpi_bif_t, bif_design_cap, ACPI_TYPE_INTEGER),
+ FIELD("bif_last_cap", acpi_bif_t, bif_last_cap, ACPI_TYPE_INTEGER),
+ FIELD("bif_tech", acpi_bif_t, bif_tech, ACPI_TYPE_INTEGER),
+ FIELD("bif_voltage", acpi_bif_t, bif_voltage, ACPI_TYPE_INTEGER),
+ FIELD("bif_warn_cap", acpi_bif_t, bif_warn_cap, ACPI_TYPE_INTEGER),
+ FIELD("bif_low_cap", acpi_bif_t, bif_low_cap, ACPI_TYPE_INTEGER),
+ FIELD("bif_gran1_cap", acpi_bif_t, bif_gran1_cap, ACPI_TYPE_INTEGER),
+ FIELD("bif_gran2_cap", acpi_bif_t, bif_gran2_cap, ACPI_TYPE_INTEGER),
+ FIELD("bif_model", acpi_bif_t, bif_model, ACPI_TYPE_STRING),
+ FIELD("bif_serial", acpi_bif_t, bif_serial, ACPI_TYPE_STRING),
+ FIELD("bif_type", acpi_bif_t, bif_type, ACPI_TYPE_STRING),
+ FIELD("bif_oem_info", acpi_bif_t, bif_oem_info, ACPI_TYPE_STRING),
+ FIELD_NULL
+};
+
+static struct obj_desc bst_desc[] = {
+ FIELD("bst_state", acpi_bst_t, bst_state, ACPI_TYPE_INTEGER),
+ FIELD("bst_rate", acpi_bst_t, bst_rate, ACPI_TYPE_INTEGER),
+ FIELD("bst_rem_cap", acpi_bst_t, bst_rem_cap, ACPI_TYPE_INTEGER),
+ FIELD("bst_voltage", acpi_bst_t, bst_voltage, ACPI_TYPE_INTEGER),
+ FIELD_NULL
+};
+
+/* kstat definitions */
+static kstat_t *acpi_drv_power_ksp;
+static kstat_t *acpi_drv_warn_ksp;
+
+acpi_drv_power_kstat_t acpi_drv_power_kstat = {
+ { SYSTEM_POWER, KSTAT_DATA_STRING },
+ { SUPPORTED_BATTERY_COUNT, KSTAT_DATA_UINT32 },
+};
+
+acpi_drv_warn_kstat_t acpi_drv_warn_kstat = {
+ { BW_ENABLED, KSTAT_DATA_UINT32 },
+ { BW_POWEROFF_THRESHOLD, KSTAT_DATA_UINT32 },
+ { BW_SHUTDOWN_THRESHOLD, KSTAT_DATA_UINT32 },
+};
+
+/* BIF */
+acpi_drv_bif_kstat_t acpi_drv_bif_kstat = {
+ { BIF_UNIT, KSTAT_DATA_UINT32 },
+ { BIF_DESIGN_CAP, KSTAT_DATA_UINT32 },
+ { BIF_LAST_CAP, KSTAT_DATA_UINT32 },
+ { BIF_TECH, KSTAT_DATA_UINT32 },
+ { BIF_VOLTAGE, KSTAT_DATA_UINT32 },
+ { BIF_WARN_CAP, KSTAT_DATA_UINT32 },
+ { BIF_LOW_CAP, KSTAT_DATA_UINT32 },
+ { BIF_GRAN1_CAP, KSTAT_DATA_UINT32 },
+ { BIF_GRAN2_CAP, KSTAT_DATA_UINT32 },
+ { BIF_MODEL, KSTAT_DATA_STRING },
+ { BIF_SERIAL, KSTAT_DATA_STRING },
+ { BIF_TYPE, KSTAT_DATA_STRING },
+ { BIF_OEM_INFO, KSTAT_DATA_STRING },
+};
+
+/* BST */
+acpi_drv_bst_kstat_t acpi_drv_bst_kstat = {
+ { BST_STATE, KSTAT_DATA_UINT32 },
+ { BST_RATE, KSTAT_DATA_UINT32 },
+ { BST_REM_CAP, KSTAT_DATA_UINT32 },
+ { BST_VOLTAGE, KSTAT_DATA_UINT32 },
+};
+
+struct acpi_drv_lid_state {
+ struct acpi_drv_dev dev;
+ enum acpi_drv_notify state_ok;
+ int state;
+} lid;
+
+/* Output device status */
+#define ACPI_DRV_DCS_CONNECTOR_EXIST (1 << 0)
+#define ACPI_DRV_DCS_ACTIVE (1 << 1)
+#define ACPI_DRV_DCS_READY (1 << 2)
+#define ACPI_DRV_DCS_FUNCTIONAL (1 << 3)
+#define ACPI_DRV_DCS_ATTACHED (1 << 4)
+
+/* _DOS default value is 1 */
+/* _DOS bit 1:0 */
+#define ACPI_DRV_DOS_SWITCH_OS_DGS 0
+#define ACPI_DRV_DOS_SWITCH_BIOS 1
+#define ACPI_DRV_DOS_SWITCH_DGS_LOCKED 2
+#define ACPI_DRV_DOS_SWITCH_OS_EVENT 3
+/* _DOS bit 2 */
+#define ACPI_DRV_DOS_BRIGHT_BIOS (0 << 2)
+#define ACPI_DRV_DOS_BRIGHT_OS (1 << 2)
+
+struct acpi_drv_output_state {
+ struct acpi_drv_dev dev;
+ uint32_t adr;
+ uint32_t *levels;
+ int num_levels; /* number of levels */
+ int nlev; /* actual array size of levels */
+ int cur_level;
+ int cur_level_index;
+ int state;
+} outputs[ACPI_DRV_MAX_OUTPUT_NUM];
+static int noutput = 0;
+
+struct acpi_drv_display_state {
+ struct acpi_drv_dev dev;
+ int mode;
+ int noutput;
+} display;
+
+static int acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
+static int acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
+static int acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
+ void **resultp);
+static int acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp);
+static int acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp);
+static int acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
+ cred_t *cr, int *rval);
+static int acpi_drv_chpoll(dev_t dev, short events, int anyyet,
+ short *reventsp, struct pollhead **phpp);
+static int acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode,
+ cred_t *cr, int *rval);
+static int acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode,
+ cred_t *cr, int *rval);
+static int acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode,
+ cred_t *cr, int *rval);
+static int acpi_drv_output_ioctl(int index, int cmd, intptr_t arg, int mode,
+ cred_t *cr, int *rval);
+#ifdef DEBUG
+static void acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
+ const char *fmt, ...);
+#endif
+
+/*
+ * Output device functions
+ */
+static int acpi_drv_output_init(ACPI_HANDLE hdl, struct acpi_drv_dev *dev);
+static void acpi_drv_output_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx);
+static int acpi_drv_output_get_state(struct acpi_drv_output_state *op);
+static int acpi_drv_output_get_level(struct acpi_drv_output_state *op);
+static int acpi_drv_output_set_level(struct acpi_drv_output_state *op,
+ uint32_t level);
+static struct acpi_drv_output_state *acpi_drv_idx2output(int idx);
+
+/*
+ * Display device functions
+ */
+static void acpi_drv_display_set_mode(struct acpi_drv_display_state *dp,
+ int state);
+
+static int acpi_drv_update_bif(struct acpi_drv_cbat_state *bp);
+static int acpi_drv_update_bst(struct acpi_drv_cbat_state *bp);
+static int acpi_drv_update_lid(struct acpi_drv_dev *bp);
+static int acpi_drv_set_warn(acpi_drv_warn_t *bwp);
+static struct acpi_drv_cbat_state *acpi_drv_idx2cbat(int idx);
+static struct acpi_drv_ac_state *acpi_drv_idx2ac(int idx);
+static int acpi_drv_acpi_init(void);
+static void acpi_drv_acpi_fini(void);
+static int acpi_drv_kstat_init(void);
+static void acpi_drv_kstat_fini(void);
+
+static struct cb_ops acpi_drv_cb_ops = {
+ acpi_drv_open, /* open */
+ acpi_drv_close, /* close */
+ nodev, /* strategy */
+ nodev, /* print */
+ nodev, /* dump */
+ nodev, /* read */
+ nodev, /* write */
+ acpi_drv_ioctl, /* ioctl */
+ nodev, /* devmap */
+ nodev, /* mmap */
+ nodev, /* segmap */
+ acpi_drv_chpoll, /* chpoll */
+ ddi_prop_op, /* prop_op */
+ NULL, /* streamtab */
+ D_NEW | D_MP,
+ CB_REV,
+ nodev,
+ nodev
+};
+
+static struct dev_ops acpi_drv_dev_ops = {
+ DEVO_REV,
+ 0, /* refcnt */
+ acpi_drv_getinfo, /* getinfo */
+ nulldev, /* identify */
+ nulldev, /* probe */
+ acpi_drv_attach, /* attach */
+ acpi_drv_detach, /* detach */
+ nodev, /* reset */
+ &acpi_drv_cb_ops,
+ NULL, /* no bus operations */
+ NULL /* power */
+};
+
+static struct modldrv modldrv1 = {
+ &mod_driverops,
+ ACPI_DRV_MOD_STRING,
+ &acpi_drv_dev_ops
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1,
+ (void *)&modldrv1,
+ NULL,
+};
+
+int
+_init(void)
+{
+ int ret;
+
+ mutex_init(&acpi_drv_mutex, NULL, MUTEX_DRIVER, NULL);
+#ifdef DEBUG
+ mutex_init(&acpi_drv_prt_mutex, NULL, MUTEX_DRIVER, NULL);
+#endif
+
+ if ((ret = mod_install(&modlinkage)) != 0) {
+ mutex_destroy(&acpi_drv_mutex);
+#ifdef DEBUG
+ mutex_destroy(&acpi_drv_prt_mutex);
+#endif
+ }
+ return (ret);
+}
+
+int
+_fini(void)
+{
+ int ret;
+
+ if ((ret = mod_remove(&modlinkage)) == 0) {
+#ifdef DEBUG
+ mutex_destroy(&acpi_drv_prt_mutex);
+#endif
+ mutex_destroy(&acpi_drv_mutex);
+ }
+
+ return (ret);
+}
+
+int
+_info(struct modinfo *mp)
+{
+ return (mod_info(&modlinkage, mp));
+}
+
+static int
+acpi_drv_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
+{
+ char name[20];
+ int i;
+ struct acpi_drv_cbat_state *bp;
+ struct acpi_drv_output_state *op;
+
+ switch (cmd) {
+ case DDI_ATTACH:
+ /* Limit to one instance of driver */
+ if (acpi_drv_dip) {
+ return (DDI_FAILURE);
+ }
+ break;
+ case DDI_RESUME:
+ case DDI_PM_RESUME:
+ return (DDI_SUCCESS);
+ default:
+ return (DDI_FAILURE);
+ }
+
+ acpi_drv_dip = devi;
+
+ /* Init ACPI related stuff */
+ if (acpi_drv_acpi_init() != ACPI_DRV_OK) {
+ goto error;
+ }
+
+ /* Init kstat related stuff */
+ if (acpi_drv_kstat_init() != ACPI_DRV_OK) {
+ goto error;
+ }
+
+ /* Create minor node for each output. */
+ for (op = &outputs[0]; op < &outputs[ACPI_DRV_MAX_OUTPUT_NUM]; op++) {
+ if (op->dev.valid) {
+ (void) snprintf(name, sizeof (name), "output%d",
+ op->dev.index);
+ if (ddi_create_minor_node(devi, name, S_IFCHR,
+ MINOR_OUTPUT(op->dev.index), DDI_PSEUDO, 0) ==
+ DDI_FAILURE) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "%s: minor node create failed", name);
+ goto error;
+ }
+ }
+ }
+
+ /* Create minor node for display device. */
+ if (ddi_create_minor_node(devi, "display", S_IFCHR, MINOR_DISPLAY(0),
+ DDI_PSEUDO, 0) == DDI_FAILURE) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "display: "
+ "minor node create failed");
+ goto error;
+ }
+ /* Create minor node for lid. */
+ if (ddi_create_minor_node(devi, "lid", S_IFCHR, MINOR_LID(0),
+ DDI_PSEUDO, 0) == DDI_FAILURE) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "lid: minor node create failed");
+ goto error;
+ }
+ /* Create minor node for each battery and ac */
+ for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
+ bp++) {
+ if (bp->dev.valid) {
+ (void) snprintf(name, sizeof (name), "battery%d",
+ bp->dev.index);
+ if (ddi_create_minor_node(devi, name, S_IFCHR,
+ MINOR_BATT(bp->dev.index), DDI_PSEUDO, 0) ==
+ DDI_FAILURE) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "%s: minor node create failed", name);
+ goto error;
+ }
+ }
+ }
+ for (i = 0; i < nac; i++) {
+ (void) snprintf(name, sizeof (name), "ac%d", i);
+ if (ddi_create_minor_node(devi, name, S_IFCHR,
+ MINOR_AC(i), DDI_PSEUDO, 0) == DDI_FAILURE) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "%s: minor node create failed", name);
+ goto error;
+ }
+ }
+
+ return (DDI_SUCCESS);
+
+error:
+ ddi_remove_minor_node(devi, NULL);
+ acpi_drv_kstat_fini();
+ acpi_drv_acpi_fini();
+ acpi_drv_dip = NULL;
+ return (DDI_FAILURE);
+}
+
+static int
+acpi_drv_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
+{
+ if (cmd != DDI_DETACH) {
+ return (DDI_FAILURE);
+ }
+
+ mutex_enter(&acpi_drv_mutex);
+ ddi_remove_minor_node(devi, NULL);
+
+ acpi_drv_kstat_fini();
+ acpi_drv_acpi_fini();
+ mutex_exit(&acpi_drv_mutex);
+ return (DDI_SUCCESS);
+}
+
+/* ARGSUSED */
+static int
+acpi_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
+{
+ switch (cmd) {
+ case DDI_INFO_DEVT2DEVINFO:
+ *resultp = acpi_drv_dip;
+ return (DDI_SUCCESS);
+ case DDI_INFO_DEVT2INSTANCE:
+ *resultp = (void*) 0;
+ return (DDI_SUCCESS);
+ default:
+ return (DDI_FAILURE);
+ }
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_open(dev_t *devp, int flag, int otyp, cred_t *crp)
+{
+ if (acpi_drv_dip == NULL) {
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_close(dev_t dev, int flag, int otyp, cred_t *crp)
+{
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
+ int *rval)
+{
+ int minor;
+ int type, index;
+ int res = 0;
+
+ minor = getminor(dev);
+ type = MINOR2TYPE(minor);
+ index = MINOR2IDX(minor);
+
+ mutex_enter(&acpi_drv_mutex);
+
+ switch (type) {
+ case ACPI_DRV_TYPE_CBAT:
+ res = acpi_drv_cbat_ioctl(index, cmd, arg, mode, cr, rval);
+ break;
+ case ACPI_DRV_TYPE_AC:
+ res = acpi_drv_ac_ioctl(index, cmd, arg, mode, cr, rval);
+ break;
+ case ACPI_DRV_TYPE_LID:
+ res = acpi_drv_lid_ioctl(index, cmd, arg, mode, cr, rval);
+ break;
+ case ACPI_DRV_TYPE_OUTPUT:
+ res = acpi_drv_output_ioctl(index, cmd, arg, mode, cr, rval);
+ break;
+ default:
+ res = EINVAL;
+ break;
+ }
+
+ mutex_exit(&acpi_drv_mutex);
+ return (res);
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_cbat_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
+ int *rval)
+{
+ int res = 0;
+ acpi_drv_warn_t bwarn;
+ struct acpi_drv_cbat_state *bp;
+
+ ASSERT(mutex_owned(&acpi_drv_mutex));
+
+ bp = acpi_drv_idx2cbat(index);
+ if (!bp || bp->dev.valid != 1) {
+ return (ENXIO);
+ }
+
+ switch (cmd) {
+ /*
+ * Return _BIF(Battery Information) of battery[index],
+ * if battery plugged.
+ */
+ case ACPI_DRV_IOC_INFO:
+ if (bp->dev.present == 0) {
+ res = ENXIO;
+ break;
+ }
+
+ res = acpi_drv_update_bif(bp);
+ if (res != ACPI_DRV_OK) {
+ break;
+ }
+ if (copyout(&bp->bif_cache, (void *)arg,
+ sizeof (bp->bif_cache))) {
+ res = EFAULT;
+ }
+ break;
+
+ /*
+ * Return _BST(Battery Status) of battery[index],
+ * if battery plugged.
+ */
+ case ACPI_DRV_IOC_STATUS:
+ if (bp->dev.present == 0) {
+ res = ENXIO;
+ break;
+ }
+
+ res = acpi_drv_update_bst(bp);
+ if (res != ACPI_DRV_OK) {
+ break;
+ }
+ if (copyout(&bp->bst_cache, (void *)arg,
+ sizeof (bp->bst_cache))) {
+ res = EFAULT;
+ }
+ break;
+
+ /* Return the state of the battery bays in the system */
+ case ACPI_DRV_IOC_BAY:
+ {
+ batt_bay_t bay;
+
+ bay.bay_number = nbat;
+ bay.battery_map = 0;
+ for (bp = &acpi_drv_cbat[0];
+ bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM]; bp++) {
+ if (bp->dev.valid) {
+ if (bp->dev.present) {
+ bay.battery_map |=
+ (1 << bp->dev.index);
+ }
+ }
+ }
+ if (copyout(&bay, (void *)arg, sizeof (bay))) {
+ res = EFAULT;
+ break;
+ }
+ }
+ break;
+
+ /*
+ * Return the current power source device if available:
+ * 0 -- battery supplying power
+ * 1 -- AC supplying power
+ */
+ case ACPI_DRV_IOC_POWER_STATUS:
+ {
+ int val;
+
+ /* State not available */
+ if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
+ res = ENXIO;
+ break;
+ }
+ val = (acpi_drv_psr_type == ACPI_DRV_TYPE_AC) ? 1 : 0;
+ if (copyout(&val, (void *)arg, sizeof (val))) {
+ res = EFAULT;
+ break;
+ }
+ }
+ break;
+
+ /* Get charge-warn and charge-low levels for the whole system */
+ case ACPI_DRV_IOC_GET_WARNING:
+ bwarn.bw_enabled = acpi_drv_warn_enabled;
+ bwarn.bw_charge_warn = acpi_drv_syn_warn_per;
+ bwarn.bw_charge_low = acpi_drv_syn_low_per;
+ if (copyout(&bwarn, (void *)arg, sizeof (&bwarn))) {
+ res = EFAULT;
+ }
+ break;
+
+ /* Set charge-warn and charge-low levels for the whole system */
+ case ACPI_DRV_IOC_SET_WARNING:
+ if (drv_priv(cr)) {
+ res = EPERM;
+ break;
+ }
+ if (copyin((void *)arg, &bwarn, sizeof (bwarn))) {
+ res = EFAULT;
+ break;
+ }
+ res = acpi_drv_set_warn(&bwarn);
+ break;
+
+ default:
+ res = EINVAL;
+ break;
+ }
+
+ return (res);
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_ac_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
+ int *rval)
+{
+ int res = 0;
+ int ac_state;
+ struct acpi_drv_ac_state *acp;
+
+ ASSERT(mutex_owned(&acpi_drv_mutex));
+
+ acp = acpi_drv_idx2ac(index);
+ if (!acp || acp->dev.valid != 1) {
+ return (ENXIO);
+ }
+
+ switch (cmd) {
+ /* Return the number of AC adapters in the system */
+ case ACPI_DRV_IOC_AC_COUNT:
+ if (copyout(&nac, (void *)arg, sizeof (nac))) {
+ res = EFAULT;
+ }
+ break;
+
+ /*
+ * Return the state of AC[index] if available:
+ * 0 -- Off-line
+ * 1 -- On-line
+ */
+ case ACPI_DRV_IOC_POWER_STATUS:
+ if (!acp || acp->dev.valid != 1) {
+ res = ENXIO;
+ break;
+ }
+ /* State not available */
+ if ((ac_state = acpi_drv_ac_present(acp)) == -1) {
+ res = ENXIO;
+ break;
+ }
+ if (copyout(&ac_state, (void *)arg, sizeof (ac_state))) {
+ res = EFAULT;
+ }
+ break;
+
+ default:
+ res = EINVAL;
+ break;
+ }
+
+ return (res);
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_lid_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
+ int *rval)
+{
+ int res = 0;
+
+ switch (cmd) {
+ case ACPI_DRV_IOC_LID_STATUS:
+ if (lid.state_ok == ACPI_DRV_NTF_UNKNOWN) {
+ /* State not available */
+ res = acpi_drv_update_lid(&lid.dev);
+ if (res != ACPI_DRV_OK) {
+ res = ENXIO;
+ break;
+ }
+ }
+ if (copyout(&lid.state, (void *)arg, sizeof (lid.state))) {
+ res = EFAULT;
+ break;
+ }
+ break;
+
+ default:
+ res = EINVAL;
+ break;
+ }
+ return (res);
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
+ struct pollhead **phpp)
+{
+ if (!anyyet) {
+ *phpp = &acpi_drv_pollhead;
+ }
+ *reventsp = 0;
+ return (0);
+}
+
+#ifdef DEBUG
+static void
+acpi_drv_printf(struct acpi_drv_dev *devp, uint_t lev,
+ const char *fmt, ...)
+{
+ va_list args;
+
+ mutex_enter(&acpi_drv_prt_mutex);
+
+ va_start(args, fmt);
+ (void) vsprintf(acpi_drv_prt_buf, fmt, args);
+ va_end(args);
+
+ if (devp) {
+ cmn_err(lev, "%s.%s: %s", devp->hid, devp->uid,
+ acpi_drv_prt_buf);
+ } else {
+ cmn_err(lev, "%s", acpi_drv_prt_buf);
+ }
+ mutex_exit(&acpi_drv_prt_mutex);
+}
+
+static void
+acpi_drv_prt_notify(ACPI_HANDLE hdl, UINT32 val)
+{
+ ACPI_BUFFER buf;
+ char str[1024];
+
+ buf.Length = sizeof (str);
+ buf.Pointer = str;
+ AcpiGetName(hdl, ACPI_FULL_PATHNAME, &buf);
+ cmn_err(CE_NOTE, "AcpiNotify(%s, 0x%02x)", str, val);
+}
+#endif /* DEBUG */
+
+static void
+acpi_drv_gen_sysevent(struct acpi_drv_dev *devp, char *ev, uint32_t val)
+{
+ nvlist_t *attr_list = NULL;
+ int err;
+ char pathname[MAXPATHLEN];
+
+ /* Allocate and build sysevent attribute list */
+ err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, DDI_NOSLEEP);
+ if (err != 0) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "cannot allocate memory for sysevent attributes\n");
+ return;
+ }
+
+ /* Add attributes */
+ err = nvlist_add_string(attr_list, PWRCTL_DEV_HID, devp->hid);
+ if (err != 0) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "Failed to add attr [%s] for %s/%s event",
+ PWRCTL_DEV_HID, EC_PWRCTL, ev);
+ nvlist_free(attr_list);
+ return;
+ }
+
+ err = nvlist_add_string(attr_list, PWRCTL_DEV_UID, devp->uid);
+ if (err != 0) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "Failed to add attr [%s] for %s/%s event",
+ PWRCTL_DEV_UID, EC_PWRCTL, ev);
+ nvlist_free(attr_list);
+ return;
+ }
+
+ err = nvlist_add_uint32(attr_list, PWRCTL_DEV_INDEX, devp->index);
+ if (err != 0) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "Failed to add attr [%s] for %s/%s event",
+ PWRCTL_DEV_INDEX, EC_PWRCTL, ev);
+ nvlist_free(attr_list);
+ return;
+ }
+
+ (void) ddi_pathname(acpi_drv_dip, pathname);
+ err = nvlist_add_string(attr_list, PWRCTL_DEV_PHYS_PATH, pathname);
+ if (err != 0) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "Failed to add attr [%s] for %s/%s event",
+ PWRCTL_DEV_PHYS_PATH, EC_PWRCTL, ev);
+ nvlist_free(attr_list);
+ return;
+ }
+
+ if (strcmp(ev, ESC_PWRCTL_WARN) && strcmp(ev, ESC_PWRCTL_LOW)) {
+ goto finish;
+ }
+
+ err = nvlist_add_uint32(attr_list, PWRCTL_CHARGE_LEVEL, val);
+ if (err != 0) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "Failed to add attr [%s] for %s/%s event",
+ PWRCTL_CHARGE_LEVEL, EC_PWRCTL, ev);
+ nvlist_free(attr_list);
+ return;
+ }
+
+finish:
+ ACPI_DRV_DBG(CE_NOTE, NULL, "SysEv(%s, %s.%s, %d)",
+ ev, devp->hid, devp->uid, val);
+ /* Generate/log sysevent */
+ err = ddi_log_sysevent(acpi_drv_dip, DDI_VENDOR_SUNW, EC_PWRCTL,
+ ev, attr_list, NULL, DDI_NOSLEEP);
+#ifdef DEBUG
+ if (err != DDI_SUCCESS) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "cannot log sysevent, err code %x\n", err);
+ }
+#endif
+
+ nvlist_free(attr_list);
+}
+
+static int
+acpi_drv_obj_copy(ACPI_OBJECT *op, char *bp, struct obj_desc *dp)
+{
+ ACPI_OBJECT *ep;
+ char *fp;
+
+ ep = &op->Package.Elements[0];
+ for (; dp->offset != -1; dp++) {
+ fp = bp + dp->offset;
+ if (dp->type == ACPI_TYPE_INTEGER &&
+ ep->Type == dp->type) {
+#ifdef DEBUG
+ if (dp->size <= 4) {
+ ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %u",
+ dp->name,
+ (uint32_t)ep->Integer.Value);
+ } else {
+#ifdef _LP64
+ ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %lu",
+ dp->name, (uint64_t)ep->Integer.Value);
+ }
+#else
+ ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: %llu",
+ dp->name, (uint64_t)ep->Integer.Value);
+ }
+#endif /* _LP64 */
+#endif /* DEBUG */
+ *(uint32_t *)fp = ep->Integer.Value;
+ } else if (dp->type == ACPI_TYPE_STRING &&
+ ep->Type == dp->type) {
+ ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: \"%s\"",
+ dp->name, ep->String.Pointer);
+ (void) strncpy(fp, ep->String.Pointer, dp->size);
+ } else if (dp->type == ACPI_TYPE_STRING &&
+ ep->Type == ACPI_TYPE_BUFFER) {
+#ifdef DEBUG
+ int len;
+ char buf[MAXNAMELEN + 1];
+
+ len = (MAXNAMELEN < ep->Buffer.Length) ?
+ MAXNAMELEN : ep->Buffer.Length;
+ bcopy(ep->Buffer.Pointer, buf, len);
+ buf[len] = 0;
+ ACPI_DRV_DBG(CE_NOTE, NULL, "\t%s: [%d] \"%s\"",
+ dp->name, len, buf);
+#endif
+
+ ASSERT(MAXNAMELEN >= ep->Buffer.Length);
+ bcopy(ep->Buffer.Pointer, fp, ep->Buffer.Length);
+ } else {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "Bad field at offset %d: type %d",
+ dp->offset, ep->Type);
+ if (dp->type != ACPI_TYPE_STRING) {
+ return (ACPI_DRV_ERR);
+ }
+ }
+ ep++;
+ }
+
+ return (ACPI_DRV_OK);
+}
+
+/*
+ * Returns the current power source devices. Used for the AC adapter and is
+ * located under the AC adapter object in name space. Used to determine if
+ * system is running off the AC adapter. This will report that the system is
+ * not running on the AC adapter if any of the batteries in the system is
+ * being forced to discharge through _BMC.
+ *
+ * Return value:
+ * 0 -- Off-line, ie. battery supplying system power
+ * 1 -- On-line, ie. AC supplying system power
+ * -1 -- Unknown, some error ocurred.
+ * Note: It will also update the driver ac state.
+ */
+static int
+acpi_drv_get_psr(struct acpi_drv_ac_state *acp)
+{
+ struct acpi_drv_dev *devp = &acp->dev;
+ int ac;
+
+ if (!devp->valid) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
+ return (-1);
+ }
+
+ if (acpica_eval_int(devp->hdl, "_PSR", &ac) == AE_OK) {
+ ACPI_DRV_DBG(CE_NOTE, devp, "_PSR = %d", ac);
+ devp->present = ac;
+ } else {
+ ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _PSR failed");
+ devp->present = -1;
+ }
+
+ return (ac);
+}
+
+/*
+ * For most systems, the _STA for this device will always
+ * return a value with bits 0-3 set and will toggle bit 4
+ * to indicate the actual presence of a battery.
+ *
+ * Return value:
+ * 0 -- battery not present
+ * 1 -- battery present
+ * -1 -- Unknown, some error ocurred.
+ * Note: It will also update the driver cbat state.
+ */
+static int
+acpi_drv_get_sta(struct acpi_drv_cbat_state *bp)
+{
+ struct acpi_drv_dev *devp = &bp->dev;
+ int val;
+
+ if (!devp->valid) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
+ return (-1);
+ }
+
+ if (acpica_eval_int(devp->hdl, "_STA", &val) == AE_OK) {
+ ACPI_DRV_DBG(CE_NOTE, devp, "_STA = 0x%x", val);
+ devp->present = ((val & STA_FLAG_BATT_PRESENT) != 0);
+ } else {
+ ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _STA failed");
+ devp->present = -1;
+ }
+
+ return (val);
+}
+
+static int
+acpi_drv_update_bif(struct acpi_drv_cbat_state *bp)
+{
+ ACPI_BUFFER buf;
+ ACPI_OBJECT *objp;
+
+ /* BIF is only available when battery plugged */
+ ASSERT(bp->dev.present != 0);
+
+ /* Update internal BIF cache */
+ bp->bat_bifok = ACPI_DRV_NTF_UNKNOWN;
+
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BIF",
+ NULL, &buf, ACPI_TYPE_PACKAGE))) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _BIF failed");
+ return (ACPI_DRV_ERR);
+ }
+
+ objp = buf.Pointer;
+ ACPI_DRV_DBG(CE_NOTE, &bp->dev, "get _BIF");
+ if (acpi_drv_obj_copy(objp, (char *)&bp->bif_cache, bif_desc) ==
+ ACPI_DRV_ERR) {
+ AcpiOsFree(objp);
+ return (ACPI_DRV_ERR);
+ }
+ AcpiOsFree(objp);
+ bp->bat_bifok = ACPI_DRV_NTF_OK;
+ return (ACPI_DRV_OK);
+}
+
+static int
+acpi_drv_update_bst(struct acpi_drv_cbat_state *bp)
+{
+ ACPI_BUFFER buf;
+ ACPI_OBJECT *objp;
+
+ /* BST is only available when battery plugged */
+ ASSERT(bp->dev.present != 0);
+
+ /* Update internal BST cache */
+ bp->bat_bstok = ACPI_DRV_NTF_UNKNOWN;
+
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BST",
+ NULL, &buf, ACPI_TYPE_PACKAGE))) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "AcpiEval _BST failed");
+ return (ACPI_DRV_ERR);
+ }
+
+ objp = buf.Pointer;
+ ACPI_DRV_DBG(CE_NOTE, &bp->dev, "get _BST");
+ if (acpi_drv_obj_copy(objp, (char *)&bp->bst_cache, bst_desc) ==
+ ACPI_DRV_ERR) {
+ AcpiOsFree(objp);
+ return (ACPI_DRV_ERR);
+ }
+ AcpiOsFree(objp);
+
+ if (bp->bst_cache.bst_rate == 0) {
+ bp->bst_cache.bst_state &= ~(ACPI_DRV_BST_CHARGING |
+ ACPI_DRV_BST_DISCHARGING);
+ }
+ bp->bat_bstok = ACPI_DRV_NTF_OK;
+ return (ACPI_DRV_OK);
+}
+
+/*
+ * Return value:
+ * 1 -- device On-line
+ * 0 -- device Off-line
+ * -1 -- Unknown, some error ocurred.
+ */
+static int
+acpi_drv_dev_present(struct acpi_drv_dev *devp)
+{
+ if (!devp->valid) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "device not valid");
+ return (-1);
+ }
+
+ ASSERT(devp->type != ACPI_DRV_TYPE_UNKNOWN);
+
+ /* Update the device state */
+ if (devp->present == -1) {
+ if (devp->type == ACPI_DRV_TYPE_AC) {
+ (void) acpi_drv_get_psr((struct acpi_drv_ac_state *)
+ devp);
+ } else if (devp->type == ACPI_DRV_TYPE_CBAT) {
+ (void) acpi_drv_get_sta((struct acpi_drv_cbat_state *)
+ devp);
+ }
+ }
+
+ return (devp->present);
+}
+
+/*
+ * Check if the device p existance state has changed.
+ * Return value:
+ * 1 -- changed
+ * 0 -- no change
+ * -1 -- unknown
+ */
+static int
+acpi_drv_update_present(struct acpi_drv_dev *p)
+{
+ int old_present = p->present;
+ int new_present;
+
+ ASSERT(p && p->valid);
+
+ p->present = -1;
+ new_present = acpi_drv_dev_present(p);
+ if (new_present == -1) {
+ return (-1);
+ }
+ if (new_present != old_present) {
+ return (1);
+ }
+ return (0);
+}
+
+static void
+acpi_drv_set_psr(struct acpi_drv_dev *p)
+{
+ acpi_drv_psr_devp = p;
+ if (p != NULL) {
+ ACPI_DRV_DBG(CE_NOTE, p, "psr = .");
+ acpi_drv_psr_type = p->type;
+ } else {
+ ACPI_DRV_DBG(CE_NOTE, p, "psr = ?");
+ acpi_drv_psr_type = ACPI_DRV_TYPE_UNKNOWN;
+ }
+}
+
+/*
+ * OSPM can determine independent warning and low battery
+ * capacity values based on the OEM-designed levels, but
+ * cannot set these values lower than the OEM-designed values.
+ */
+static int
+acpi_drv_set_warn(acpi_drv_warn_t *bwp)
+{
+ uint32_t warn, low;
+
+ warn = acpi_drv_syn_last_cap * bwp->bw_charge_warn / 100;
+ low = acpi_drv_syn_last_cap * bwp->bw_charge_low / 100;
+
+ /* Update internal state */
+ if (bwp->bw_enabled) {
+ if (low >= warn || warn < acpi_drv_syn_oem_warn_cap ||
+ low < acpi_drv_syn_oem_low_cap) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "charge level error");
+ return (EINVAL);
+ }
+
+ ACPI_DRV_DBG(CE_NOTE, NULL, "set warn: warn=%d low=%d", warn,
+ low);
+
+ acpi_drv_syn_warn_per = bwp->bw_charge_warn;
+ acpi_drv_syn_low_per = bwp->bw_charge_low;
+ acpi_drv_syn_warn_cap = warn;
+ acpi_drv_syn_low_cap = low;
+ acpi_drv_warn_enabled = 1;
+ } else {
+ acpi_drv_warn_enabled = 0;
+ }
+
+ return (0);
+}
+
+/*
+ * Update information for the synthesis battery
+ *
+ * Note: Sometimes the value to be returned from _BST or _BIF will be
+ * temporarily unknown. In this case, the method may return the value
+ * 0xFFFFFFFF as a placeholder. When the value becomes known, the
+ * appropriate notification (0x80 for _BST or 0x81 for BIF) should be
+ * issued, in like manner to any other change in the data returned by
+ * these methods. This will cause OSPM to re-evaluate the method obtaining
+ * the correct data value.
+ */
+static void
+acpi_drv_update_cap(int bif_changed)
+{
+ struct acpi_drv_cbat_state *bp;
+
+ if (bif_changed != 0) {
+ acpi_drv_syn_oem_warn_cap = 0xffffffff;
+ acpi_drv_syn_oem_low_cap = 0xffffffff;
+ acpi_drv_syn_last_cap = 0xffffffff;
+ }
+ acpi_drv_syn_last_level = acpi_drv_syn_rem_cap;
+ acpi_drv_syn_rem_cap = 0xffffffff; /* initially unknown */
+
+ for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
+ bp++) {
+ if (bp->dev.valid) {
+ /* Escape the empty bays */
+ if (acpi_drv_cbat_present(bp) <= 0) {
+ continue;
+ }
+
+ if (bif_changed != 0 &&
+ bp->bat_bifok == ACPI_DRV_NTF_OK) {
+ acpi_bif_t *bif;
+
+ bif = &bp->bif_cache;
+
+ if (acpi_drv_syn_last_cap == 0xffffffff) {
+ acpi_drv_syn_last_cap = 0;
+ }
+ acpi_drv_syn_last_cap += bif->bif_last_cap;
+
+ if (bif->bif_warn_cap == 0xffffffff ||
+ bif->bif_low_cap == 0xffffffff) {
+ ACPI_DRV_DBG(CE_WARN, &bp->dev,
+ "BIF value "
+ "invalid, warn_cap=0x%x "
+ "low_cap=0x%x", bif->bif_warn_cap,
+ bif->bif_low_cap);
+ continue;
+ }
+ if (acpi_drv_syn_oem_warn_cap == 0xffffffff) {
+ acpi_drv_syn_oem_warn_cap = 0;
+ }
+ if (acpi_drv_syn_oem_low_cap == 0xffffffff) {
+ acpi_drv_syn_oem_low_cap = 0;
+ }
+
+ /*
+ * Use the highest level as the synthesis
+ * level.
+ */
+ if (bif->bif_warn_cap >
+ acpi_drv_syn_oem_warn_cap) {
+ acpi_drv_syn_oem_low_cap =
+ bif->bif_low_cap;
+ acpi_drv_syn_oem_warn_cap =
+ bif->bif_warn_cap;
+ }
+ }
+#ifdef DEBUG
+ else if (bif_changed) {
+ ACPI_DRV_DBG(CE_NOTE, &bp->dev,
+ "BIF not ready");
+ }
+#endif
+
+ if (bp->bat_bstok == ACPI_DRV_NTF_OK) {
+ acpi_bst_t *bst;
+
+ bst = &bp->bst_cache;
+
+ /*
+ * Batteries that are rechargeable and are in
+ * the discharging state are required to return
+ * a valid Battery Present Rate value.
+ * 0xFFFFFFFF - Unknown rate/capacity
+ */
+ if (bst->bst_rem_cap == 0xffffffff) {
+ ACPI_DRV_DBG(CE_WARN, &bp->dev,
+ "BST value invalid, "
+ "rate=0x%x cap=0x%x",
+ bst->bst_rate, bst->bst_rem_cap);
+ continue;
+ }
+
+ if (acpi_drv_syn_rem_cap == 0xffffffff) {
+ acpi_drv_syn_rem_cap = 0;
+ }
+ acpi_drv_syn_rem_cap += bst->bst_rem_cap;
+ /* Check for overflow */
+ ASSERT(acpi_drv_syn_rem_cap >=
+ bst->bst_rem_cap);
+ }
+#ifdef DEBUG
+ else {
+ ACPI_DRV_DBG(CE_NOTE, &bp->dev,
+ "BST not ready");
+ }
+#endif
+ }
+ }
+
+ ACPI_DRV_DBG(CE_NOTE, NULL, "syn_cap: %d syn_oem_warn: %d "
+ "syn_oem_low: %d", acpi_drv_syn_rem_cap, acpi_drv_syn_oem_warn_cap,
+ acpi_drv_syn_oem_low_cap);
+}
+
+static struct acpi_drv_cbat_state *
+acpi_drv_idx2cbat(int idx)
+{
+ if (idx >= ACPI_DRV_MAX_BAT_NUM) {
+ return (NULL);
+ }
+ return (&acpi_drv_cbat[idx]);
+}
+
+static struct acpi_drv_ac_state *
+acpi_drv_idx2ac(int idx)
+{
+ if (idx >= ACPI_DRV_MAX_AC_NUM) {
+ return (NULL);
+ }
+ return (&acpi_drv_ac[idx]);
+}
+
+/*ARGSUSED*/
+static void
+acpi_drv_cbat_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
+{
+ struct acpi_drv_cbat_state *bp = ctx;
+ struct acpi_drv_dev *devp = &bp->dev;
+ int bif_changed;
+ uint32_t eval;
+ char *ev;
+ acpi_bst_t *bst;
+
+ mutex_enter(&acpi_drv_mutex);
+ ACPI_DRV_PRT_NOTIFY(hdl, val);
+
+ switch (val) {
+ /*
+ * BST has changed
+ * Whenever the Battery State value changes, the
+ * system will generate an SCI to notify the OS.
+ *
+ * Note: trip point is not used to implement the
+ * warning levels.
+ */
+ case 0x80:
+ /*
+ * We always get 0x80 and 0x81 at battery plug/unplug,
+ * but 0x80 may come first. In case that situation, we have
+ * to update battery present state here too to update bst
+ * correctly.
+ */
+ bif_changed = acpi_drv_update_present(devp);
+
+ /* Omit events sent by empty battery slot */
+ if (devp->present == 0) {
+ break;
+ }
+
+ if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
+ break;
+ }
+ acpi_drv_update_cap(bif_changed);
+
+ bst = &bp->bst_cache;
+ eval = bst->bst_rem_cap;
+
+ /*
+ * Keep tracking the current power source device
+ *
+ * Note: Even no battery plugged, some system
+ * send out 0x80 ACPI event. So make sure the battery
+ * is present first.
+ */
+ if (devp->present == 0) {
+ if (acpi_drv_psr_devp == devp) {
+ acpi_drv_set_psr(NULL);
+ }
+ break;
+ }
+ if (bst->bst_state & BST_FLAG_DISCHARGING) {
+ acpi_drv_set_psr(devp);
+ }
+ /*
+ * The Critical battery state indicates that all
+ * available batteries are discharged and do not
+ * appear to be able to supply power to run the
+ * system any longer. When this occurs, the OS
+ * should attempt to perform an emergency shutdown.
+ * Right now we do not shutdown. This would
+ * need some discussion first since it could be
+ * controversial.
+ */
+#ifdef DEBUG
+ if (bst->bst_state & BST_FLAG_CRITICAL) {
+ ACPI_DRV_DBG(CE_WARN, devp, "BST_FLAG_CRITICAL set");
+
+ /*
+ * BST_FLAG_CRITICAL may set even with AC,
+ * plugged, when plug/unplug battery. Check
+ * to avoid erroneous shutdown.
+ */
+ if (acpi_drv_psr_devp == devp &&
+ bst->bst_rem_cap != 0xffffffff) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "Battery in critical state");
+ }
+ } else
+#endif
+ if (acpi_drv_warn_enabled &&
+ (bst->bst_state & BST_FLAG_DISCHARGING)) {
+ /*
+ * This value is an estimation of the amount of
+ * energy or battery capacity required by the
+ * system to transition to any supported sleeping
+ * state. When the OS detects that the total
+ * available battery capacity is less than this
+ * value, it will transition the system to a user
+ * defined system state (S1-S5).
+ */
+ if (acpi_drv_syn_last_level > acpi_drv_syn_low_cap &&
+ acpi_drv_syn_rem_cap <= acpi_drv_syn_low_cap) {
+ acpi_drv_gen_sysevent(devp, ESC_PWRCTL_LOW,
+ eval);
+ /*
+ * When the total available energy (mWh) or capacity
+ * (mAh) in the batteries falls below this level,
+ * the OS will notify the user through the UI.
+ */
+ } else if (acpi_drv_syn_last_level >
+ acpi_drv_syn_warn_cap &&
+ acpi_drv_syn_rem_cap <= acpi_drv_syn_warn_cap) {
+ acpi_drv_gen_sysevent(devp, ESC_PWRCTL_WARN,
+ eval);
+ }
+ }
+
+ acpi_drv_gen_sysevent(devp, ESC_PWRCTL_STATE_CHANGE, 0);
+ pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
+ break;
+
+ /* BIF has changed */
+ case 0x81:
+ /*
+ * Note: Do not eliminate multiple ADD/REMOVE here,
+ * because they may corresponding to different batterys.
+ */
+ (void) acpi_drv_update_present(devp);
+ if (devp->present == 1) {
+ if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
+ break;
+ }
+ }
+
+ acpi_drv_update_cap(1);
+
+ eval = devp->present;
+ ev = eval ? ESC_PWRCTL_ADD : ESC_PWRCTL_REMOVE;
+ acpi_drv_gen_sysevent(devp, ev, 0);
+ pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
+ break;
+
+ case 0x82:
+ default:
+ break;
+ }
+
+ mutex_exit(&acpi_drv_mutex);
+}
+
+static int
+acpi_drv_update_lid(struct acpi_drv_dev *p)
+{
+ struct acpi_drv_lid_state *lp = (struct acpi_drv_lid_state *)p;
+
+ if (acpica_eval_int(p->hdl, "_LID", &lp->state) == AE_OK) {
+ lp->state_ok = ACPI_DRV_NTF_OK;
+ return (ACPI_DRV_OK);
+ }
+ return (ACPI_DRV_ERR);
+}
+
+/*ARGSUSED*/
+static void
+acpi_drv_ac_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
+{
+ struct acpi_drv_ac_state *acp = ctx;
+ struct acpi_drv_dev *devp = &acp->dev;
+ int old_present;
+ char *ev;
+ int eval;
+
+ ACPI_DRV_PRT_NOTIFY(hdl, val);
+ if (val != 0x80) {
+ return;
+ }
+
+ mutex_enter(&acpi_drv_mutex);
+ /*
+ * Note: if unplug and then quickly plug back, two ADD
+ * events will be generated.
+ */
+ old_present = devp->present;
+ eval = acpi_drv_get_psr(acp);
+
+ /* Eliminate redundant events */
+ if (eval != -1 && eval != old_present) {
+ /* Keep tracking the current power source device */
+ if (eval == 1) {
+ ev = ESC_PWRCTL_ADD;
+ acpi_drv_set_psr(devp);
+ } else {
+ ev = ESC_PWRCTL_REMOVE;
+ /* If AC was supplying the power, it's not now */
+ if (acpi_drv_psr_devp == devp) {
+ acpi_drv_set_psr(NULL);
+ }
+ }
+
+ acpi_drv_gen_sysevent(devp, ev, 0);
+ pollwakeup(&acpi_drv_pollhead, ACPI_DRV_EVENTS);
+ }
+
+ mutex_exit(&acpi_drv_mutex);
+}
+
+static void
+acpi_drv_lid_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
+{
+ struct acpi_drv_lid_state *p = ctx;
+
+ ACPI_DRV_PRT_NOTIFY(hdl, val);
+ if (val == 0x80) {
+ mutex_enter(&acpi_drv_mutex);
+ if (acpi_drv_update_lid(&p->dev) == ACPI_DRV_OK) {
+ acpi_drv_gen_sysevent(&p->dev, p->state ?
+ ESC_PWRCTL_ADD : ESC_PWRCTL_REMOVE, 0);
+ }
+ mutex_exit(&acpi_drv_mutex);
+ }
+}
+
+static int
+acpi_drv_obj_init(struct acpi_drv_dev *p)
+{
+ ACPI_DEVICE_INFO *info;
+ ACPI_BUFFER buf;
+ ACPI_NOTIFY_HANDLER ntf_handler = NULL;
+ ACPI_STATUS ret;
+
+ ASSERT(p != NULL && p->hdl != NULL);
+
+ p->valid = 0;
+
+ /* Info size is variable depending on existance of _CID */
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ ret = AcpiGetObjectInfo(p->hdl, &buf);
+ if (ACPI_FAILURE(ret)) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
+ return (ACPI_DRV_ERR);
+ }
+
+ info = buf.Pointer;
+ if ((info->Valid & ACPI_VALID_HID) == 0) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "AcpiGetObjectInfo(): _HID not available");
+ (void) strncpy(p->uid, "\0", 9);
+ } else {
+ (void) strncpy(p->hid, info->HardwareId.Value, 9);
+ }
+ (void) strncpy(p->hid, info->HardwareId.Value, 9);
+
+ /*
+ * This object is optional, but is required when the device
+ * has no other way to report a persistent unique device ID.
+ */
+ if ((info->Valid & ACPI_VALID_UID) == 0) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "AcpiGetObjectInfo(): _UID not available");
+ /* Use 0 as the default _UID */
+ (void) strncpy(p->uid, "\0", 9);
+ } else {
+ (void) strncpy(p->uid, info->UniqueId.Value, 9);
+ }
+
+ p->valid = 1;
+
+ if (strcmp(p->hid, ACPI_DEVNAME_CBAT) == 0) {
+ struct acpi_drv_cbat_state *bp =
+ (struct acpi_drv_cbat_state *)p;
+
+ p->type = ACPI_DRV_TYPE_CBAT;
+ p->index = nbat - 1;
+
+ /* Update device present state */
+ (void) acpi_drv_update_present(p);
+ if (p->present) {
+ (void) acpi_drv_update_bif(bp);
+ (void) acpi_drv_update_bst(bp);
+
+ /* Init the current power source */
+ if (bp->bst_cache.bst_state & BST_FLAG_DISCHARGING) {
+ acpi_drv_set_psr(p);
+ }
+ }
+ ntf_handler = acpi_drv_cbat_notify;
+ ACPI_DRV_DBG(CE_NOTE, p, "battery %s",
+ (p->present ? "present" : "absent"));
+ } else if (strcmp(p->hid, ACPI_DEVNAME_AC) == 0) {
+ p->type = ACPI_DRV_TYPE_AC;
+ p->index = nac - 1;
+
+ /* Update device present state */
+ (void) acpi_drv_update_present(p);
+ if (p->present) {
+ /* Init the current power source */
+ acpi_drv_set_psr(p);
+ }
+ ntf_handler = acpi_drv_ac_notify;
+ ACPI_DRV_DBG(CE_NOTE, p, "AC %s",
+ (p->present ? "on-line" : "off-line"));
+ } else if (strcmp(p->hid, ACPI_DEVNAME_SBAT) == 0) {
+ p->type = ACPI_DRV_TYPE_SBAT;
+ ACPI_DRV_DBG(CE_NOTE, p, "added");
+ } else if (strcmp(p->hid, ACPI_DEVNAME_LID) == 0) {
+ p->type = ACPI_DRV_TYPE_LID;
+ lid.state_ok = ACPI_DRV_NTF_UNKNOWN;
+ (void) acpi_drv_update_lid(p);
+ ntf_handler = acpi_drv_lid_notify;
+ ACPI_DRV_DBG(CE_NOTE, p, "added");
+ } else if (info->Valid & ACPI_VALID_ADR) {
+ p->adr = info->Address;
+ if (p->type == ACPI_DRV_TYPE_DISPLAY) {
+ /* Enable display control by OS */
+ display.mode = ACPI_DRV_DOS_SWITCH_OS_EVENT |
+ ACPI_DRV_DOS_BRIGHT_OS;
+ acpi_drv_display_set_mode(&display, display.mode);
+ } else {
+ p->index = noutput - 1;
+ if (acpi_drv_output_init(p->hdl, p) == ACPI_DRV_ERR) {
+ p->valid = 0;
+ AcpiOsFree(info);
+ return (ACPI_DRV_ERR);
+ }
+ ntf_handler = acpi_drv_output_notify;
+ p->type = ACPI_DRV_TYPE_OUTPUT;
+ }
+ } else {
+ ACPI_DRV_DBG(CE_NOTE, p, "unknown device");
+ p->valid = 0;
+ }
+
+ /* Register ACPI battery related events */
+ if (ntf_handler != NULL) {
+ if (ACPI_FAILURE(AcpiInstallNotifyHandler(p->hdl,
+ ACPI_ALL_NOTIFY, ntf_handler, p))) {
+ ACPI_DRV_DBG(CE_NOTE, NULL,
+ "Notify handler for %s.%s install failed",
+ p->hid, p->uid);
+ return (ACPI_DRV_ERR);
+ }
+ }
+
+ AcpiOsFree(info);
+ return (ACPI_DRV_OK);
+}
+
+/*ARGSUSED*/
+static ACPI_STATUS
+acpi_drv_find_cb(ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context,
+ void **ReturnValue)
+{
+ struct acpi_drv_dev *devp = (struct acpi_drv_dev *)Context;
+
+ if (devp == &acpi_drv_cbat[0].dev) {
+ struct acpi_drv_cbat_state *bp;
+
+ if (nbat == ACPI_DRV_MAX_BAT_NUM) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "Need to support more batteries: "
+ "BATTERY_MAX = %d", ACPI_DRV_MAX_BAT_NUM);
+ return (AE_LIMIT);
+ }
+ bp = &acpi_drv_cbat[nbat++];
+ devp = (struct acpi_drv_dev *)bp;
+ } else if (devp == &acpi_drv_ac[0].dev) {
+ struct acpi_drv_ac_state *ap;
+
+ if (nac == ACPI_DRV_MAX_AC_NUM) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "Need to support more ACs: "
+ "AC_MAX = %d", ACPI_DRV_MAX_AC_NUM);
+ return (AE_LIMIT);
+ }
+ ap = &acpi_drv_ac[nac++];
+ devp = (struct acpi_drv_dev *)ap;
+ } else if (devp == &lid.dev) {
+ struct acpi_drv_lid_state *lp;
+
+ lp = &lid;
+ devp = (struct acpi_drv_dev *)lp;
+ } else if (devp == &outputs[0].dev) {
+ int adr = 0;
+ ACPI_BUFFER buf1 = {ACPI_ALLOCATE_BUFFER, NULL};
+ ACPI_BUFFER buf2;
+ char str[256];
+ ACPI_HANDLE ohl = NULL;
+ struct acpi_drv_display_state *dp;
+ struct acpi_drv_output_state *op;
+
+ /*
+ * Reduce the search by checking for support of _ADR
+ * method.
+ */
+ if (acpica_eval_int(ObjHandle, "_ADR", &adr) != AE_OK) {
+ return (AE_OK);
+ }
+
+ /*
+ * Find the display device.
+ */
+ if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(ObjHandle, "_DOD",
+ NULL, &buf1, ACPI_TYPE_PACKAGE))) {
+ AcpiOsFree(buf1.Pointer);
+
+ buf2.Pointer = str;
+ buf2.Length = sizeof (str);
+ if (!ACPI_FAILURE(AcpiGetName(ObjHandle,
+ ACPI_FULL_PATHNAME, &buf2))) {
+ ACPI_DRV_DBG(CE_NOTE, NULL,
+ "_DOD Supported Pathname=%s\n",
+ (char *)buf2.Pointer);
+ }
+
+ dp = &display;
+ devp = (struct acpi_drv_dev *)dp;
+ devp->hdl = ObjHandle;
+ devp->index = 1;
+ devp->type = ACPI_DRV_TYPE_DISPLAY;
+ (void) acpi_drv_obj_init(devp);
+
+ /*
+ * Find the output devices.
+ */
+ while (ACPI_SUCCESS(AcpiGetNextObject(ACPI_TYPE_DEVICE,
+ ObjHandle, ohl, &ohl))) {
+ op = &outputs[noutput++];
+ devp = (struct acpi_drv_dev *)op;
+ devp->hdl = ohl;
+ (void) acpi_drv_obj_init(devp);
+ }
+ dp->noutput = noutput;
+ }
+ return (AE_OK);
+ } else {
+ ACPI_DRV_DBG(CE_WARN, NULL, "acpi_drv_find_cb(): "
+ "Unknown device");
+ return (AE_ERROR);
+ }
+
+ devp->hdl = ObjHandle;
+
+ /* Try to get as many working objs as possible */
+ (void) acpi_drv_obj_init(devp);
+ return (AE_OK);
+}
+
+static int
+acpi_drv_acpi_init()
+{
+ int *retp;
+
+ /* Check to see if ACPI CA services are available */
+ if (AcpiSubsystemStatus() != AE_OK) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "ACPI CA not ready");
+ return (ACPI_DRV_ERR);
+ }
+
+ /* Init Control Method Batterys */
+ if (ACPI_FAILURE(AcpiGetDevices(ACPI_DEVNAME_CBAT, acpi_drv_find_cb,
+ acpi_drv_cbat, (void *)&retp))) {
+ return (ACPI_DRV_ERR);
+ }
+
+ if (nbat == 0) {
+ return (ACPI_DRV_ERR);
+ }
+
+ /* Init AC */
+ if (ACPI_FAILURE(AcpiGetDevices(ACPI_DEVNAME_AC, acpi_drv_find_cb,
+ acpi_drv_ac, (void *)&retp))) {
+ return (ACPI_DRV_ERR);
+ }
+
+ /* Init LID */
+ if (ACPI_FAILURE(AcpiGetDevices(ACPI_DEVNAME_LID, acpi_drv_find_cb,
+ &lid, (void *)&retp))) {
+ return (ACPI_DRV_ERR);
+ }
+
+ /* Init Output Devices */
+ if (ACPI_FAILURE(AcpiGetDevices(NULL, acpi_drv_find_cb,
+ outputs, (void *)&retp))) {
+ return (ACPI_DRV_ERR);
+ }
+
+ /* Init Smart Battery */
+ if (ACPI_FAILURE(AcpiGetDevices(ACPI_DEVNAME_SBAT, acpi_drv_find_cb,
+ &acpi_drv_sbat, (void *)&retp))) {
+ return (ACPI_DRV_ERR);
+ }
+
+ acpi_drv_update_cap(1);
+
+ return (ACPI_DRV_OK);
+}
+
+static void
+acpi_drv_acpi_fini(void)
+{
+ int i;
+ struct acpi_drv_cbat_state *bp;
+ struct acpi_drv_output_state *op;
+
+ for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
+ bp++) {
+ if (bp->dev.valid) {
+ AcpiRemoveNotifyHandler(bp->dev.hdl, ACPI_DEVICE_NOTIFY,
+ acpi_drv_cbat_notify);
+ }
+ }
+ for (i = 0; i < nac; i++) {
+ AcpiRemoveNotifyHandler(acpi_drv_ac[i].dev.hdl,
+ ACPI_DEVICE_NOTIFY, acpi_drv_ac_notify);
+ }
+ AcpiRemoveNotifyHandler(lid.dev.hdl, ACPI_DEVICE_NOTIFY,
+ acpi_drv_lid_notify);
+ for (op = &outputs[0]; op < &outputs[ACPI_DRV_MAX_OUTPUT_NUM]; op++) {
+ if (op->dev.valid) {
+ if (op->levels) {
+ kmem_free(op->levels,
+ op->nlev * sizeof (uint32_t));
+ }
+ AcpiRemoveNotifyHandler(op->dev.hdl, ACPI_DEVICE_NOTIFY,
+ acpi_drv_output_notify);
+ }
+ }
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_kstat_power_update(kstat_t *ksp, int flag)
+{
+ if (flag == KSTAT_WRITE) {
+ return (EACCES);
+ }
+
+ mutex_enter(&acpi_drv_mutex);
+ if (acpi_drv_psr_type == ACPI_DRV_TYPE_UNKNOWN) {
+ mutex_exit(&acpi_drv_mutex);
+ return (EIO);
+ }
+ kstat_named_setstr(&acpi_drv_power_kstat.acpi_drv_power,
+ acpi_drv_psr_type == ACPI_DRV_TYPE_AC ? AC : BATTERY);
+ acpi_drv_power_kstat.acpi_drv_supported_battery_count.value.ui32 =
+ (uint32_t)nbat;
+ mutex_exit(&acpi_drv_mutex);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_kstat_warn_update(kstat_t *ksp, int flag)
+{
+ if (flag == KSTAT_WRITE) {
+ int ret = 0;
+ acpi_drv_warn_t bw;
+ acpi_drv_warn_kstat_t kbw;
+
+ kbw = *(acpi_drv_warn_kstat_t *)acpi_drv_warn_ksp->ks_data;
+
+ mutex_enter(&acpi_drv_mutex);
+ bw.bw_enabled = kbw.acpi_drv_bw_enabled.value.ui32;
+ bw.bw_charge_warn = kbw.acpi_drv_bw_charge_warn.value.ui32;
+ bw.bw_charge_low = kbw.acpi_drv_bw_charge_low.value.ui32;
+ ret = acpi_drv_set_warn(&bw);
+ mutex_exit(&acpi_drv_mutex);
+
+ return (ret);
+ } else {
+ acpi_drv_warn_kstat_t *wp = &acpi_drv_warn_kstat;
+
+ mutex_enter(&acpi_drv_mutex);
+ wp->acpi_drv_bw_enabled.value.ui32 = acpi_drv_warn_enabled;
+ wp->acpi_drv_bw_charge_warn.value.ui32 = acpi_drv_syn_warn_per;
+ wp->acpi_drv_bw_charge_low.value.ui32 = acpi_drv_syn_low_per;
+ mutex_exit(&acpi_drv_mutex);
+
+ return (0);
+ }
+}
+
+static int
+acpi_drv_kstat_bif_update(kstat_t *ksp, int flag)
+{
+ struct acpi_drv_cbat_state *bp;
+ acpi_bif_t *bif;
+ acpi_drv_bif_kstat_t *kp;
+
+ if (flag == KSTAT_WRITE) {
+ return (EACCES);
+ }
+
+ bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
+ mutex_enter(&acpi_drv_mutex);
+
+ if (acpi_drv_cbat_present(bp) <= 0) {
+ mutex_exit(&acpi_drv_mutex);
+ return (ENXIO);
+ }
+
+ bzero(&bif, sizeof (bif));
+ if (acpi_drv_update_bif(bp) != ACPI_DRV_OK) {
+ mutex_exit(&acpi_drv_mutex);
+ return (ENXIO);
+ }
+
+ bif = &bp->bif_cache;
+ kp = &acpi_drv_bif_kstat;
+
+ /* Update BIF */
+ kp->acpi_drv_bif_unit.value.ui32 = bif->bif_unit;
+ kp->acpi_drv_bif_design_cap.value.ui32 = bif->bif_design_cap;
+ kp->acpi_drv_bif_last_cap.value.ui32 = bif->bif_last_cap;
+ kp->acpi_drv_bif_tech.value.ui32 = bif->bif_tech;
+ kp->acpi_drv_bif_voltage.value.ui32 = bif->bif_voltage;
+ kp->acpi_drv_bif_warn_cap.value.ui32 = bif->bif_warn_cap;
+ kp->acpi_drv_bif_low_cap.value.ui32 = bif->bif_low_cap;
+ kp->acpi_drv_bif_gran1_cap.value.ui32 = bif->bif_gran1_cap;
+ kp->acpi_drv_bif_gran2_cap.value.ui32 = bif->bif_gran2_cap;
+
+ kstat_named_setstr(&kp->acpi_drv_bif_model, bif->bif_model);
+ kstat_named_setstr(&kp->acpi_drv_bif_serial, bif->bif_serial);
+ kstat_named_setstr(&kp->acpi_drv_bif_type, bif->bif_type);
+ kstat_named_setstr(&kp->acpi_drv_bif_oem_info, bif->bif_oem_info);
+
+ mutex_exit(&acpi_drv_mutex);
+ return (0);
+}
+
+static int
+acpi_drv_kstat_bst_update(kstat_t *ksp, int flag)
+{
+ struct acpi_drv_cbat_state *bp;
+ acpi_bst_t *bst;
+ acpi_drv_bst_kstat_t *kp;
+
+ if (flag == KSTAT_WRITE) {
+ return (EACCES);
+ }
+
+ bp = (struct acpi_drv_cbat_state *)ksp->ks_private;
+ mutex_enter(&acpi_drv_mutex);
+
+ if (acpi_drv_cbat_present(bp) <= 0) {
+ mutex_exit(&acpi_drv_mutex);
+ return (ENXIO);
+ }
+
+ bzero(&bst, sizeof (bst));
+ if (acpi_drv_update_bst(bp) != ACPI_DRV_OK) {
+ mutex_exit(&acpi_drv_mutex);
+ return (ENXIO);
+ }
+
+ bst = &bp->bst_cache;
+ kp = &acpi_drv_bst_kstat;
+
+ /* Update BST */
+ kp->acpi_drv_bst_state.value.ui32 = bst->bst_state;
+ kp->acpi_drv_bst_rate.value.ui32 = bst->bst_rate;
+ kp->acpi_drv_bst_rem_cap.value.ui32 = bst->bst_rem_cap;
+ kp->acpi_drv_bst_voltage.value.ui32 = bst->bst_voltage;
+
+ mutex_exit(&acpi_drv_mutex);
+ return (0);
+}
+
+static int
+acpi_drv_kstat_init(void)
+{
+ char name[KSTAT_STRLEN];
+ struct acpi_drv_cbat_state *bp;
+
+ /*
+ * Allocate, initialize and install powerstatus and
+ * supported_battery_count kstat.
+ */
+ acpi_drv_power_ksp = kstat_create(ACPI_DRV_NAME, 0,
+ ACPI_DRV_POWER_KSTAT_NAME, "misc",
+ KSTAT_TYPE_NAMED,
+ sizeof (acpi_drv_power_kstat) / sizeof (kstat_named_t),
+ KSTAT_FLAG_VIRTUAL);
+ if (acpi_drv_power_ksp == NULL) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "kstat_create(%s) fail", ACPI_DRV_POWER_KSTAT_NAME);
+ return (ACPI_DRV_ERR);
+ }
+
+ acpi_drv_power_ksp->ks_data = &acpi_drv_power_kstat;
+ acpi_drv_power_ksp->ks_update = acpi_drv_kstat_power_update;
+ acpi_drv_power_ksp->ks_data_size += MAXNAMELEN;
+ kstat_install(acpi_drv_power_ksp);
+
+ /*
+ * Allocate, initialize and install battery_capacity_warning kstat.
+ */
+ acpi_drv_warn_ksp = kstat_create(ACPI_DRV_NAME, 0,
+ ACPI_DRV_BTWARN_KSTAT_NAME, "misc",
+ KSTAT_TYPE_NAMED,
+ sizeof (acpi_drv_warn_kstat) / sizeof (kstat_named_t),
+ KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
+ if (acpi_drv_warn_ksp == NULL) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "kstat_create(%s) fail", ACPI_DRV_BTWARN_KSTAT_NAME);
+ return (ACPI_DRV_ERR);
+ }
+
+ acpi_drv_warn_ksp->ks_data = &acpi_drv_warn_kstat;
+ acpi_drv_warn_ksp->ks_update = acpi_drv_kstat_warn_update;
+ kstat_install(acpi_drv_warn_ksp);
+
+ /*
+ * Allocate, initialize and install BIF and BST kstat
+ * for each battery.
+ */
+ for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
+ bp++) {
+ if (bp->dev.valid) {
+ kstat_t *ksp;
+
+ /* BIF kstat */
+ (void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
+ ACPI_DRV_BIF_KSTAT_NAME, bp->dev.index);
+ ksp = kstat_create(ACPI_DRV_NAME, 0,
+ name, "misc", KSTAT_TYPE_NAMED,
+ sizeof (acpi_drv_bif_kstat) /
+ sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
+ if (ksp == NULL) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "kstat_create(%s) fail", name);
+ return (ACPI_DRV_ERR);
+ }
+ ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
+ name);
+
+ bp->bat_bif_ksp = ksp;
+ ksp->ks_data = &acpi_drv_bif_kstat;
+ ksp->ks_update = acpi_drv_kstat_bif_update;
+ ksp->ks_data_size += MAXNAMELEN * 4;
+ ksp->ks_private = bp;
+
+ kstat_install(ksp);
+
+ /* BST kstat */
+ (void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
+ ACPI_DRV_BST_KSTAT_NAME, bp->dev.index);
+ ksp = kstat_create(ACPI_DRV_NAME, 0, name, "misc",
+ KSTAT_TYPE_NAMED,
+ sizeof (acpi_drv_bst_kstat) /
+ sizeof (kstat_named_t),
+ KSTAT_FLAG_VIRTUAL);
+ if (ksp == NULL) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "kstat_create(%s) fail", name);
+ return (ACPI_DRV_ERR);
+ }
+ ACPI_DRV_DBG(CE_NOTE, NULL, "kstat_create(%s) ok",
+ name);
+
+ bp->bat_bst_ksp = ksp;
+ ksp->ks_data = &acpi_drv_bst_kstat;
+ ksp->ks_update = acpi_drv_kstat_bst_update;
+ ksp->ks_data_size += MAXNAMELEN * 4;
+ ksp->ks_private = bp;
+
+ kstat_install(ksp);
+ }
+ }
+
+ return (ACPI_DRV_OK);
+}
+
+static void
+acpi_drv_kstat_fini()
+{
+ struct acpi_drv_cbat_state *bp;
+
+ if (acpi_drv_power_ksp != NULL) {
+ kstat_delete(acpi_drv_power_ksp);
+ }
+ if (acpi_drv_warn_ksp != NULL) {
+ kstat_delete(acpi_drv_warn_ksp);
+ }
+ for (bp = &acpi_drv_cbat[0]; bp < &acpi_drv_cbat[ACPI_DRV_MAX_BAT_NUM];
+ bp++) {
+ if (bp->dev.valid) {
+ if (bp->bat_bif_ksp != NULL) {
+ kstat_delete(bp->bat_bif_ksp);
+ }
+ if (bp->bat_bst_ksp != NULL) {
+ kstat_delete(bp->bat_bst_ksp);
+ }
+ }
+ }
+}
+
+static int
+acpi_drv_set_int(ACPI_HANDLE dev, char *method, uint32_t aint)
+{
+ ACPI_OBJECT_LIST al;
+ ACPI_OBJECT ao;
+
+ al.Pointer = &ao;
+ al.Count = 1;
+ ao.Type = ACPI_TYPE_INTEGER;
+ ao.Integer.Value = aint;
+ return (AcpiEvaluateObject(dev, method, &al, NULL));
+}
+
+static int
+acpi_drv_output_init(ACPI_HANDLE hdl, struct acpi_drv_dev *dev)
+{
+ struct acpi_drv_output_state *op;
+ int adr;
+ ACPI_BUFFER buf1, buf2;
+ ACPI_OBJECT *objp;
+ char str[256];
+
+ if (acpica_eval_int(hdl, "_ADR", &adr) != AE_OK) {
+ return (ACPI_DRV_ERR);
+ }
+
+ /* Allocate object */
+ if (noutput == ACPI_DRV_MAX_OUTPUT_NUM) {
+ ACPI_DRV_DBG(CE_WARN, NULL,
+ "Need to support more output devices: "
+ "AC_MAX = %d", ACPI_DRV_MAX_OUTPUT_NUM);
+ return (ACPI_DRV_ERR);
+ }
+ op = dev->op = &outputs[noutput - 1];
+ op->adr = adr;
+
+ buf1.Pointer = str;
+ buf1.Length = sizeof (str);
+
+ if (!ACPI_FAILURE(AcpiGetName(hdl, ACPI_FULL_PATHNAME, &buf1))) {
+ ACPI_DRV_DBG(CE_NOTE, NULL, "Pathname=%s\n",
+ (char *)buf1.Pointer);
+ }
+
+ buf2.Length = ACPI_ALLOCATE_BUFFER;
+ if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(hdl, "_BCL",
+ NULL, &buf2, ACPI_TYPE_PACKAGE))) {
+ int i, j, k, l, m, nlev, tmp;
+
+ ACPI_DRV_DBG(CE_NOTE, NULL, "_BCL supported\n");
+ objp = buf2.Pointer;
+ /*
+ * op->nlev will be needed to free op->levels.
+ */
+ op->nlev = nlev = objp->Package.Count;
+ op->levels = kmem_zalloc(nlev * sizeof (uint32_t),
+ KM_SLEEP);
+ /*
+ * Get all the supported brightness levels.
+ */
+ for (i = 0; i < nlev; i++) {
+ ACPI_OBJECT *o = &objp->Package.Elements[i];
+ int lev = o->Integer.Value;
+
+ ACPI_DRV_DBG(CE_NOTE, NULL, "acpi_drv_output_init() "
+ "brlev=%d i=%d nlev=%d\n", lev, i, nlev);
+ if (o->Type != ACPI_TYPE_INTEGER) {
+ continue;
+ }
+ op->levels[i] = lev;
+ }
+
+ /*
+ * Sort the brightness levels.
+ */
+ for (j = 0; j < nlev; j++) {
+ for (k = 0; k < nlev - 1; k++) {
+ if (op->levels[k] > op->levels[k+1]) {
+ tmp = op->levels[k+1];
+ op->levels[k+1] = op->levels[k];
+ op->levels[k] = tmp;
+ }
+ }
+ }
+
+ /*
+ * The first two levels could be duplicated, so remove
+ * any duplicates.
+ */
+ for (l = 0; l < nlev - 1; l++) {
+ if (op->levels[l] == op->levels[l+1]) {
+ for (m = l + 1; m < nlev - 1; m++) {
+ op->levels[m] = op->levels[m+1];
+ }
+ nlev--;
+ }
+ }
+ op->num_levels = nlev;
+
+ AcpiOsFree(objp);
+ (void) acpi_drv_output_get_level(op);
+ ACPI_DRV_DBG(CE_NOTE, NULL, "acpi_drv_output_init(): "
+ "create minor "
+ "node for dev->adr=%"PRIu64, dev->adr);
+ } else {
+ ACPI_DRV_DBG(CE_NOTE, NULL, "_BCL NOT supported\n");
+ }
+
+ (void) acpi_drv_output_get_state(op);
+ return (ACPI_DRV_OK);
+}
+
+/*ARGSUSED*/
+static int
+acpi_drv_output_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
+ int *rval)
+{
+ struct acpi_drv_output_state *op;
+ int res = 0;
+ op = acpi_drv_idx2output(index);
+ if (!op || op->dev.valid != 1) {
+ return (ENXIO);
+ }
+
+ switch (cmd) {
+ case ACPI_DRV_IOC_INFO: {
+ struct acpi_drv_output_info inf;
+ inf.adr = op->adr;
+ inf.nlev = op->num_levels;
+ if (copyout(&inf, (void *)arg, sizeof (inf))) {
+ res = EFAULT;
+ }
+ break;
+ }
+
+ case ACPI_DRV_IOC_LEVELS:
+ if (copyout(op->levels, (void *)arg,
+ sizeof (*op->levels) * op->num_levels)) {
+ res = EFAULT;
+ }
+ break;
+
+ case ACPI_DRV_IOC_STATUS: {
+ /*
+ * Need to get the current levels through ACPI first
+ * then go through array of levels to find index.
+ */
+ struct acpi_drv_output_status status;
+ int i;
+
+ status.state = op->state;
+ status.num_levels = op->num_levels;
+ status.cur_level = op->cur_level;
+ for (i = 0; i < op->num_levels; i++) {
+ if (op->levels[i] == op->cur_level) {
+ status.cur_level_index = i;
+ ACPI_DRV_DBG(CE_NOTE, NULL, "ACPI_DRV_IOC_STATUS "
+ "cur_level_index %d\n", i);
+ break;
+ }
+ }
+ if (copyout(&status, (void *)arg, sizeof (status))) {
+ res = EFAULT;
+ }
+ break;
+ }
+
+ case ACPI_DRV_IOC_SET_BRIGHTNESS: {
+ int level;
+
+ if (drv_priv(cr)) {
+ res = EPERM;
+ break;
+ }
+ if (copyin((void *)arg, &level, sizeof (level))) {
+ res = EFAULT;
+ break;
+ }
+ ACPI_DRV_DBG(CE_NOTE, NULL,
+ "ACPI_DRV_IOC_SET_BRIGHTNESS level=%d\n", level);
+ if (acpi_drv_output_set_level(op, level) != ACPI_DRV_OK) {
+ res = EFAULT;
+ }
+ break;
+ }
+
+ default:
+ res = EINVAL;
+ break;
+ }
+ return (res);
+}
+
+static struct acpi_drv_output_state *
+acpi_drv_idx2output(int idx)
+{
+ if (idx >= ACPI_DRV_MAX_OUTPUT_NUM) {
+ return (NULL);
+ }
+ return (&outputs[idx]);
+}
+
+/*
+ * Output device status:
+ *
+ * Bits Definition
+ *
+ * 0 Output connector exists in the system now.
+ * 1 Output is activated.
+ * 2 Output is ready to switch.
+ * 3 Output is not defective.
+ * 4 Device is attached (optional).
+ * 5-31 Reserved (must be zero).
+ */
+static int
+acpi_drv_output_get_state(struct acpi_drv_output_state *op)
+{
+ if (acpica_eval_int(op->dev.hdl, "_DCS", &op->state) != AE_OK) {
+ op->state = 0;
+ return (ACPI_DRV_ERR);
+ }
+ return (ACPI_DRV_OK);
+}
+
+/*
+ * Get the current brightness level and index.
+ */
+static int
+acpi_drv_output_get_level(struct acpi_drv_output_state *op)
+{
+ int i;
+
+ if (acpica_eval_int(op->dev.hdl, "_BQC", &op->cur_level) != AE_OK) {
+ op->cur_level = ACPI_DRV_NTF_UNKNOWN;
+ return (ACPI_DRV_ERR);
+ }
+ for (i = 0; i < op->num_levels; i++) {
+ if (op->levels[i] == op->cur_level) {
+ op->cur_level_index = i;
+ ACPI_DRV_DBG(CE_NOTE, NULL,
+ "acpi_drv_output_get_level(): "
+ "cur_level = %d, cur_level_index = %d\n",
+ op->cur_level, i);
+ break;
+ }
+ }
+ return (ACPI_DRV_OK);
+}
+
+static int
+acpi_drv_output_set_level(struct acpi_drv_output_state *op, uint32_t level)
+{
+ if (acpi_drv_set_int(op->dev.hdl, "_BCM", op->levels[level]) !=
+ AE_OK) {
+ return (ACPI_DRV_ERR);
+ }
+ op->cur_level = op->levels[level];
+ op->cur_level_index = level;
+ return (ACPI_DRV_OK);
+}
+
+static void
+acpi_drv_output_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
+{
+ struct acpi_drv_dev *dev = ctx;
+ struct acpi_drv_output_state *op = dev->op;
+
+ ACPI_DRV_DBG(CE_NOTE, NULL, "acpi_drv_output_notify() val=0x%x\n", val);
+ mutex_enter(&acpi_drv_mutex);
+ ACPI_DRV_PRT_NOTIFY(hdl, val);
+ switch (val) {
+ case 0x86: /* increase brightness */
+ if (op->cur_level_index < op->num_levels - 1) {
+ if (acpi_drv_output_set_level(op,
+ op->cur_level_index + 1) != AE_OK) {
+ break;
+ }
+ }
+ acpi_drv_gen_sysevent(&op->dev, ESC_PWRCTL_BRIGHTNESS_UP, 0);
+ break;
+ case 0x87: /* decrease brightness */
+ if (op->cur_level_index > 0) {
+ if (acpi_drv_output_set_level(op,
+ op->cur_level_index - 1) != AE_OK) {
+ break;
+ }
+ }
+ acpi_drv_gen_sysevent(&op->dev, ESC_PWRCTL_BRIGHTNESS_DOWN, 0);
+ break;
+ default:
+ break;
+ }
+ mutex_exit(&acpi_drv_mutex);
+}
+
+/*
+ * Set the display control modes of display switching and brightness
+ * from BIOS or OSPM.
+ */
+static void
+acpi_drv_display_set_mode(struct acpi_drv_display_state *dp, int state)
+{
+ if (acpi_drv_set_int(dp->dev.hdl, "_DOS", state) != AE_OK) {
+ ACPI_DRV_DBG(CE_WARN, NULL, "Cannot set display mode %d\n",
+ state);
+ }
+}
diff --git a/usr/src/uts/i86pc/io/battery/battery.conf b/usr/src/uts/i86pc/io/acpi_drv/acpi_drv.conf
index 216cac8604..fce7f57995 100644
--- a/usr/src/uts/i86pc/io/battery/battery.conf
+++ b/usr/src/uts/i86pc/io/acpi_drv/acpi_drv.conf
@@ -19,12 +19,12 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
-name="battery" parent="pseudo" instance=0;
+name="acpi_drv" parent="pseudo" instance=0;
ddi-forceattach=1;
diff --git a/usr/src/uts/i86pc/io/battery/battery.c b/usr/src/uts/i86pc/io/battery/battery.c
deleted file mode 100644
index 1f0e7a049b..0000000000
--- a/usr/src/uts/i86pc/io/battery/battery.c
+++ /dev/null
@@ -1,1972 +0,0 @@
-/*
- * 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 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Solaris x86 ACPI Battery Monitor
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/conf.h>
-#include <sys/modctl.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/stat.h>
-#include <sys/sysevent/eventdefs.h>
-#include <sys/sysevent/acpiev.h>
-#include <sys/reboot.h>
-#include <sys/acpi/acpi.h>
-#include <sys/note.h>
-#include <sys/battery.h>
-
-
-#define BATT_MOD_STRING "ACPI battery driver %I%"
-
-#define MINOR_SHIFT 8
-#define IDX_MASK ((1 << MINOR_SHIFT) - 1)
-#define MINOR_BATT(idx) (BATT_TYPE_CBAT << MINOR_SHIFT | (idx))
-#define MINOR_AC(idx) (BATT_TYPE_AC << MINOR_SHIFT | (idx))
-#define MINOR2IDX(minor) ((minor) & IDX_MASK)
-#define MINOR2TYPE(minor) ((minor) >> MINOR_SHIFT)
-
-#define BATT_OK (0)
-#define BATT_ERR (1)
-
-#define BATT_MAX_BAT_NUM 8
-#define BATT_MAX_AC_NUM 10
-
-#define BST_FLAG_DISCHARGING (0x1)
-#define BST_FLAG_CHARGING (0x2)
-#define BST_FLAG_CRITICAL (0x4)
-
-/* Set if the battery is present */
-#define STA_FLAG_BATT_PRESENT (0x10)
-
-#define ACPI_DEVNAME_CBAT "PNP0C0A"
-#define ACPI_DEVNAME_SBAT "ACPI0002"
-#define ACPI_DEVNAME_AC "ACPI0003"
-
-#define BATT_EVENTS (POLLIN | POLLRDNORM)
-
-#ifdef DEBUG
-
-#define BATT_PRINT_BUFFER_SIZE 512
-static char batt_prt_buf[BATT_PRINT_BUFFER_SIZE];
-static kmutex_t batt_prt_mutex;
-
-static int batt_debug = 0;
-#define BATT_DBG(lev, devp, ...) \
- do { \
- if (batt_debug) batt_printf((devp), (lev), __VA_ARGS__); \
-_NOTE(CONSTCOND) } while (0)
-#define BATT_PRT_NOTIFY(hdl, val) \
- do { \
- if (batt_debug) batt_prt_notify((hdl), (val)); \
-_NOTE(CONSTCOND) } while (0)
-
-#else
-
-#define BATT_DBG(lev, devp, ...)
-#define BATT_PRT_NOTIFY(hdl, val)
-
-#endif /* DEBUG */
-
-/* ACPI notify types */
-enum batt_notify {
- BATT_NTF_UNKNOWN = -1, /* No notifications seen, ever. */
- BATT_NTF_CHANGED,
- BATT_NTF_OK
-};
-
-/* Battery device types */
-enum batt_type {
- BATT_TYPE_UNKNOWN = -1,
- BATT_TYPE_CBAT,
- BATT_TYPE_AC,
- BATT_TYPE_SBAT
-};
-
-struct batt_acpi_dev {
- ACPI_HANDLE hdl;
- char hid[9]; /* ACPI HardwareId */
- char uid[9]; /* ACPI UniqueId */
- int valid; /* the device state is valid */
-
- /*
- * Unlike most other devices, when a battery is inserted or
- * removed from the system, the device itself(the battery bay)
- * is still considered to be present in the system.
- *
- * Value:
- * 0 -- On-line
- * 1 -- Off-line
- * -1 -- Unknown
- */
- int present;
- enum batt_type type;
- int index; /* device index */
-};
-
-static int batt_dev_present(struct batt_acpi_dev *);
-#define batt_ac_present(a) (((a)->dev.type == BATT_TYPE_AC) ? \
- batt_dev_present(&(a)->dev) : -1)
-#define batt_cbat_present(a) (((a)->dev.type == BATT_TYPE_CBAT) ? \
- batt_dev_present(&(a)->dev) : -1)
-
-static dev_info_t *batt_dip = NULL;
-static kmutex_t batt_mutex;
-static struct pollhead batt_pollhead;
-
-/* Control Method Battery state */
-struct batt_cbat_state {
- struct batt_acpi_dev dev;
-/* Caches of _BST and _BIF */
- enum batt_notify bat_bifok;
- acpi_bif_t bif_cache;
- enum batt_notify bat_bstok;
- acpi_bst_t bst_cache;
-
- uint32_t charge_warn;
- uint32_t charge_low;
-
- kstat_t *bat_bif_ksp;
- kstat_t *bat_bst_ksp;
-} batt_cbat[BATT_MAX_BAT_NUM];
-static int nbat;
-
-/*
- * Synthesis battery state
- * When there are multiple batteries present, the battery subsystem
- * is not required to perform any synthesis of a composite battery
- * from the data of the separate batteries. In cases where the
- * battery subsystem does not synthesize a composite battery from
- * the separate battery's data, the OS must provide that synthesis.
- */
-static uint32_t batt_syn_rem_cap;
-static uint32_t batt_syn_last_cap;
-static uint32_t batt_syn_oem_warn_cap;
-static uint32_t batt_syn_oem_low_cap;
-
-static int batt_warn_enabled;
-static uint32_t batt_syn_warn_per;
-static uint32_t batt_syn_low_per;
-static uint32_t batt_syn_warn_cap;
-static uint32_t batt_syn_low_cap;
-/* Tracking boundery passing of _BST charge levels */
-static uint32_t batt_syn_last_level;
-
-/* AC state */
-static struct batt_ac_state {
- struct batt_acpi_dev dev;
-} batt_ac[BATT_MAX_AC_NUM];
-static int nac;
-
-/*
- * Current power source device
- * Note: assume only one device can be the power source device.
- */
-static int batt_psr_type = BATT_TYPE_UNKNOWN;
-static struct batt_acpi_dev *batt_psr_devp = NULL;
-
-/* Smart Battery state */
-static struct batt_sbat_state {
- struct batt_acpi_dev dev;
-} batt_sbat;
-
-struct obj_desc {
- char *name;
- int offset;
- int size;
- int type;
-};
-
-/* Object copy definitions */
-#define OFFSETOF(s, m) ((size_t)(&(((s *)0)->m)))
-#define SIZEOF(s, m) (sizeof (((s *)0)->m))
-#define FIELD(n, s, m, t) \
- { n, OFFSETOF(s, m), SIZEOF(s, m), t }
-#define FIELD_NULL { NULL, -1, 0, ACPI_TYPE_ANY }
-
-static struct obj_desc bif_desc[] = {
- FIELD("bif_unit", acpi_bif_t, bif_unit, ACPI_TYPE_INTEGER),
- FIELD("bif_design_cap", acpi_bif_t, bif_design_cap, ACPI_TYPE_INTEGER),
- FIELD("bif_last_cap", acpi_bif_t, bif_last_cap, ACPI_TYPE_INTEGER),
- FIELD("bif_tech", acpi_bif_t, bif_tech, ACPI_TYPE_INTEGER),
- FIELD("bif_voltage", acpi_bif_t, bif_voltage, ACPI_TYPE_INTEGER),
- FIELD("bif_warn_cap", acpi_bif_t, bif_warn_cap, ACPI_TYPE_INTEGER),
- FIELD("bif_low_cap", acpi_bif_t, bif_low_cap, ACPI_TYPE_INTEGER),
- FIELD("bif_gran1_cap", acpi_bif_t, bif_gran1_cap, ACPI_TYPE_INTEGER),
- FIELD("bif_gran2_cap", acpi_bif_t, bif_gran2_cap, ACPI_TYPE_INTEGER),
- FIELD("bif_model", acpi_bif_t, bif_model, ACPI_TYPE_STRING),
- FIELD("bif_serial", acpi_bif_t, bif_serial, ACPI_TYPE_STRING),
- FIELD("bif_type", acpi_bif_t, bif_type, ACPI_TYPE_STRING),
- FIELD("bif_oem_info", acpi_bif_t, bif_oem_info, ACPI_TYPE_STRING),
- FIELD_NULL
-};
-
-static struct obj_desc bst_desc[] = {
- FIELD("bst_state", acpi_bst_t, bst_state, ACPI_TYPE_INTEGER),
- FIELD("bst_rate", acpi_bst_t, bst_rate, ACPI_TYPE_INTEGER),
- FIELD("bst_rem_cap", acpi_bst_t, bst_rem_cap, ACPI_TYPE_INTEGER),
- FIELD("bst_voltage", acpi_bst_t, bst_voltage, ACPI_TYPE_INTEGER),
- FIELD_NULL
-};
-
-/* kstat definitions */
-static kstat_t *batt_power_ksp;
-static kstat_t *batt_warn_ksp;
-
-batt_power_kstat_t batt_power_kstat = {
- { SYSTEM_POWER, KSTAT_DATA_STRING },
- { SUPPORTED_BATTERY_COUNT, KSTAT_DATA_UINT32 },
-};
-
-batt_warn_kstat_t batt_warn_kstat = {
- { BW_ENABLED, KSTAT_DATA_UINT32 },
- { BW_POWEROFF_THRESHOLD, KSTAT_DATA_UINT32 },
- { BW_SHUTDOWN_THRESHOLD, KSTAT_DATA_UINT32 },
-};
-
-/* BIF */
-batt_bif_kstat_t batt_bif_kstat = {
- { BIF_UNIT, KSTAT_DATA_UINT32 },
- { BIF_DESIGN_CAP, KSTAT_DATA_UINT32 },
- { BIF_LAST_CAP, KSTAT_DATA_UINT32 },
- { BIF_TECH, KSTAT_DATA_UINT32 },
- { BIF_VOLTAGE, KSTAT_DATA_UINT32 },
- { BIF_WARN_CAP, KSTAT_DATA_UINT32 },
- { BIF_LOW_CAP, KSTAT_DATA_UINT32 },
- { BIF_GRAN1_CAP, KSTAT_DATA_UINT32 },
- { BIF_GRAN2_CAP, KSTAT_DATA_UINT32 },
- { BIF_MODEL, KSTAT_DATA_STRING },
- { BIF_SERIAL, KSTAT_DATA_STRING },
- { BIF_TYPE, KSTAT_DATA_STRING },
- { BIF_OEM_INFO, KSTAT_DATA_STRING },
-};
-
-/* BST */
-batt_bst_kstat_t batt_bst_kstat = {
- { BST_STATE, KSTAT_DATA_UINT32 },
- { BST_RATE, KSTAT_DATA_UINT32 },
- { BST_REM_CAP, KSTAT_DATA_UINT32 },
- { BST_VOLTAGE, KSTAT_DATA_UINT32 },
-};
-
-static int batt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
-static int batt_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
-static int batt_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
- void **resultp);
-static int batt_open(dev_t *devp, int flag, int otyp, cred_t *crp);
-static int batt_close(dev_t dev, int flag, int otyp, cred_t *crp);
-static int batt_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr,
- int *rval);
-static int batt_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
- struct pollhead **phpp);
-static int batt_ac_ioctl(int index, int cmd, intptr_t arg, int mode,
- cred_t *cr, int *rval);
-static int batt_cbat_ioctl(int index, int cmd, intptr_t arg, int mode,
- cred_t *cr, int *rval);
-#ifdef DEBUG
-static void batt_printf(struct batt_acpi_dev *devp, uint_t lev,
- const char *fmt, ...);
-#endif
-static int batt_get_bif(acpi_bif_t *bifp, struct batt_cbat_state *bp);
-static int batt_get_bst(acpi_bst_t *bstp, struct batt_cbat_state *bp);
-static int batt_set_warn(batt_warn_t *bwp);
-static struct batt_cbat_state *batt_idx2cbat(int idx);
-static struct batt_ac_state *batt_idx2ac(int idx);
-static int batt_acpi_init(void);
-static void batt_acpi_fini(void);
-static int batt_kstat_init(void);
-static void batt_kstat_fini(void);
-
-static struct cb_ops batt_cb_ops = {
- batt_open, /* open */
- batt_close, /* close */
- nodev, /* strategy */
- nodev, /* print */
- nodev, /* dump */
- nodev, /* read */
- nodev, /* write */
- batt_ioctl, /* ioctl */
- nodev, /* devmap */
- nodev, /* mmap */
- nodev, /* segmap */
- batt_chpoll, /* chpoll */
- ddi_prop_op, /* prop_op */
- NULL, /* streamtab */
- D_NEW | D_MP,
- CB_REV,
- nodev,
- nodev
-};
-
-static struct dev_ops batt_dev_ops = {
- DEVO_REV,
- 0, /* refcnt */
- batt_getinfo, /* getinfo */
- nulldev, /* identify */
- nulldev, /* probe */
- batt_attach, /* attach */
- batt_detach, /* detach */
- nodev, /* reset */
- &batt_cb_ops,
- NULL, /* no bus operations */
- NULL /* power */
-};
-
-static struct modldrv modldrv1 = {
- &mod_driverops,
- BATT_MOD_STRING,
- &batt_dev_ops
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- (void *)&modldrv1,
- NULL,
-};
-
-int
-_init(void)
-{
- int ret;
-
- mutex_init(&batt_mutex, NULL, MUTEX_DRIVER, NULL);
-#ifdef DEBUG
- mutex_init(&batt_prt_mutex, NULL, MUTEX_DRIVER, NULL);
-#endif
-
- if ((ret = mod_install(&modlinkage)) != 0) {
- mutex_destroy(&batt_mutex);
-#ifdef DEBUG
- mutex_destroy(&batt_prt_mutex);
-#endif
- }
- return (ret);
-}
-
-int
-_fini(void)
-{
- int ret;
-
- if ((ret = mod_remove(&modlinkage)) == 0) {
-#ifdef DEBUG
- mutex_destroy(&batt_prt_mutex);
-#endif
- mutex_destroy(&batt_mutex);
- }
-
- return (ret);
-}
-
-int
-_info(struct modinfo *mp)
-{
- return (mod_info(&modlinkage, mp));
-}
-
-static int
-batt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
- char name[20];
- int i;
- struct batt_cbat_state *bp;
-
- switch (cmd) {
- case DDI_ATTACH:
- /* Limit to one instance of driver */
- if (batt_dip) {
- return (DDI_FAILURE);
- }
- break;
- case DDI_RESUME:
- case DDI_PM_RESUME:
- return (DDI_SUCCESS);
- default:
- return (DDI_FAILURE);
- }
-
- batt_dip = devi;
-
- /* Init ACPI related stuff */
- if (batt_acpi_init() != BATT_OK) {
- goto error;
- }
-
- /* Init kstat related stuff */
- if (batt_kstat_init() != BATT_OK) {
- goto error;
- }
-
- /* Create minor node for each battery and ac */
- for (bp = &batt_cbat[0]; bp < &batt_cbat[BATT_MAX_BAT_NUM]; bp++) {
- if (bp->dev.valid) {
- (void) snprintf(name, sizeof (name), "battery%d",
- bp->dev.index);
- if (ddi_create_minor_node(devi, name, S_IFCHR,
- MINOR_BATT(bp->dev.index), DDI_PSEUDO, 0) ==
- DDI_FAILURE) {
- BATT_DBG(CE_WARN, NULL,
- "%s: minor node create failed", name);
- goto error;
- }
- }
- }
- for (i = 0; i < nac; i++) {
- (void) snprintf(name, sizeof (name), "ac%d", i);
- if (ddi_create_minor_node(devi, name, S_IFCHR,
- MINOR_AC(i), DDI_PSEUDO, 0) == DDI_FAILURE) {
- BATT_DBG(CE_WARN, NULL,
- "%s: minor node create failed", name);
- goto error;
- }
- }
-
- return (DDI_SUCCESS);
-
-error:
- ddi_remove_minor_node(devi, NULL);
- batt_kstat_fini();
- batt_acpi_fini();
- batt_dip = NULL;
- return (DDI_FAILURE);
-}
-
-static int
-batt_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
-{
- if (cmd != DDI_DETACH) {
- return (DDI_FAILURE);
- }
-
- ddi_remove_minor_node(devi, NULL);
-
- batt_kstat_fini();
- batt_acpi_fini();
- return (DDI_SUCCESS);
-}
-
-/* ARGSUSED */
-static int
-batt_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
-{
- switch (cmd) {
- case DDI_INFO_DEVT2DEVINFO:
- *resultp = batt_dip;
- return (DDI_SUCCESS);
- case DDI_INFO_DEVT2INSTANCE:
- *resultp = (void*) 0;
- return (DDI_SUCCESS);
- default:
- return (DDI_FAILURE);
- }
-}
-
-/*ARGSUSED*/
-static int
-batt_open(dev_t *devp, int flag, int otyp, cred_t *crp)
-{
- if (batt_dip == NULL) {
- return (ENXIO);
- }
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-batt_close(dev_t dev, int flag, int otyp, cred_t *crp)
-{
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-batt_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval)
-{
- int minor;
- int type, index;
- int res = 0;
-
- minor = getminor(dev);
- type = MINOR2TYPE(minor);
- index = MINOR2IDX(minor);
-
- mutex_enter(&batt_mutex);
-
- if (type == BATT_TYPE_CBAT) {
- res = batt_cbat_ioctl(index, cmd, arg, mode, cr, rval);
- } else if (type == BATT_TYPE_AC) {
- res = batt_ac_ioctl(index, cmd, arg, mode, cr, rval);
- } else {
- res = EINVAL;
- }
-
- mutex_exit(&batt_mutex);
- return (res);
-}
-
-/*ARGSUSED*/
-static int
-batt_cbat_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
- int *rval)
-{
- int res = 0;
- acpi_bif_t bif;
- acpi_bst_t bst;
- batt_warn_t bwarn;
- struct batt_cbat_state *bp;
-
- ASSERT(mutex_owned(&batt_mutex));
-
- bp = batt_idx2cbat(index);
- if (!bp || bp->dev.valid != 1) {
- return (ENXIO);
- }
-
- switch (cmd) {
- /*
- * Return _BIF(Battery Information) of battery[index],
- * if battery plugged.
- */
- case BATT_IOC_INFO:
- if (bp->dev.present == 0) {
- res = ENXIO;
- break;
- }
-
- (void) memset(&bif, 0, sizeof (bif));
- bp->bat_bifok = BATT_NTF_UNKNOWN;
- res = batt_get_bif(&bif, bp);
- if (res != BATT_OK) {
- break;
- }
- if (copyout(&bif, (void *)arg, sizeof (bif))) {
- res = EFAULT;
- }
- break;
-
- /*
- * Return _BST(Battery Status) of battery[index],
- * if battery plugged.
- */
- case BATT_IOC_STATUS:
- if (bp->dev.present == 0) {
- res = ENXIO;
- break;
- }
-
- (void) memset(&bst, 0, sizeof (bst));
- bp->bat_bstok = BATT_NTF_UNKNOWN;
- res = batt_get_bst(&bst, bp);
- if (res != BATT_OK) {
- break;
- }
- if (copyout(&bst, (void *)arg, sizeof (bst))) {
- res = EFAULT;
- }
- break;
-
- /* Return the state of the battery bays in the system */
- case BATT_IOC_BAY:
- {
- batt_bay_t bay;
-
- bay.bay_number = nbat;
- bay.battery_map = 0;
- for (bp = &batt_cbat[0];
- bp < &batt_cbat[BATT_MAX_BAT_NUM]; bp++) {
- if (bp->dev.valid) {
- if (bp->dev.present) {
- bay.battery_map |=
- (1 << bp->dev.index);
- }
- }
- }
- if (copyout(&bay, (void *)arg, sizeof (bay))) {
- res = EFAULT;
- break;
- }
- }
- break;
-
- /*
- * Return the current power source device if available:
- * 0 -- battery supplying power
- * 1 -- AC supplying power
- */
- case BATT_IOC_POWER_STATUS:
- {
- int val;
-
- /* State not available */
- if (batt_psr_type == BATT_TYPE_UNKNOWN) {
- res = ENXIO;
- break;
- }
- val = (batt_psr_type == BATT_TYPE_AC) ? 1 : 0;
- if (copyout(&val, (void *)arg, sizeof (val))) {
- res = EFAULT;
- break;
- }
- }
- break;
-
- /* Get charge-warn and charge-low levels for the whole system */
- case BATT_IOC_GET_WARNING:
- bwarn.bw_enabled = batt_warn_enabled;
- bwarn.bw_charge_warn = batt_syn_warn_per;
- bwarn.bw_charge_low = batt_syn_low_per;
- if (copyout(&bwarn, (void *)arg, sizeof (&bwarn))) {
- res = EFAULT;
- }
- break;
-
- /* Set charge-warn and charge-low levels for the whole system */
- case BATT_IOC_SET_WARNING:
- if (drv_priv(cr)) {
- res = EPERM;
- break;
- }
- if (copyin((void *)arg, &bwarn, sizeof (&bwarn))) {
- res = EFAULT;
- break;
- }
- res = batt_set_warn(&bwarn);
- break;
-
- default:
- res = EINVAL;
- break;
- }
-
- return (res);
-}
-
-/*ARGSUSED*/
-static int
-batt_ac_ioctl(int index, int cmd, intptr_t arg, int mode, cred_t *cr,
- int *rval)
-{
- int res = 0;
- int ac_state;
- struct batt_ac_state *acp;
-
- ASSERT(mutex_owned(&batt_mutex));
-
- acp = batt_idx2ac(index);
- if (!acp || acp->dev.valid != 1) {
- return (ENXIO);
- }
-
- switch (cmd) {
- /* Return the number of AC adapters in the system */
- case BATT_IOC_AC_COUNT:
- if (copyout(&nac, (void *)arg, sizeof (nac))) {
- res = EFAULT;
- }
- break;
-
- /*
- * Return the state of AC[index] if available:
- * 0 -- Off-line
- * 1 -- On-line
- */
- case BATT_IOC_POWER_STATUS:
- if (!acp || acp->dev.valid != 1) {
- res = ENXIO;
- break;
- }
- /* State not available */
- if ((ac_state = batt_ac_present(acp)) == -1) {
- res = ENXIO;
- break;
- }
- if (copyout(&ac_state, (void *)arg, sizeof (ac_state))) {
- res = EFAULT;
- }
- break;
-
- default:
- res = EINVAL;
- break;
- }
-
- return (res);
-}
-
-/*ARGSUSED*/
-static int
-batt_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
- struct pollhead **phpp)
-{
- if (!anyyet) {
- *phpp = &batt_pollhead;
- }
- *reventsp = 0;
- return (0);
-}
-
-#ifdef DEBUG
-static void
-batt_printf(struct batt_acpi_dev *devp, uint_t lev, const char *fmt, ...)
-{
- va_list args;
-
- mutex_enter(&batt_prt_mutex);
-
- va_start(args, fmt);
- (void) vsprintf(batt_prt_buf, fmt, args);
- va_end(args);
-
- if (devp) {
- cmn_err(lev, "%s.%s: %s", devp->hid, devp->uid, batt_prt_buf);
- } else {
- cmn_err(lev, "%s", batt_prt_buf);
- }
- mutex_exit(&batt_prt_mutex);
-}
-
-static void
-batt_prt_notify(ACPI_HANDLE hdl, UINT32 val)
-{
- ACPI_BUFFER buf;
- char str[1024];
-
- buf.Length = sizeof (str);
- buf.Pointer = str;
- AcpiGetName(hdl, ACPI_FULL_PATHNAME, &buf);
- cmn_err(CE_NOTE, "AcpiNotify(%s, 0x%02x)", str, val);
-}
-#endif /* DEBUG */
-
-static void
-batt_gen_sysevent(struct batt_acpi_dev *devp, char *ev, uint32_t val)
-{
- nvlist_t *attr_list = NULL;
- int err;
- char pathname[MAXPATHLEN];
-
- /* Allocate and build sysevent attribute list */
- err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, DDI_NOSLEEP);
- if (err != 0) {
- BATT_DBG(CE_WARN, NULL,
- "cannot allocate memory for sysevent attributes\n");
- return;
- }
-
- /* Add attributes */
- err = nvlist_add_string(attr_list, ACPIEV_DEV_HID, devp->hid);
- if (err != 0) {
- BATT_DBG(CE_WARN, NULL,
- "Failed to add attr [%s] for %s/%s event",
- ACPIEV_DEV_HID, EC_ACPIEV, ev);
- nvlist_free(attr_list);
- return;
- }
-
- err = nvlist_add_string(attr_list, ACPIEV_DEV_UID, devp->uid);
- if (err != 0) {
- BATT_DBG(CE_WARN, NULL,
- "Failed to add attr [%s] for %s/%s event",
- ACPIEV_DEV_UID, EC_ACPIEV, ev);
- nvlist_free(attr_list);
- return;
- }
-
- err = nvlist_add_uint32(attr_list, ACPIEV_DEV_INDEX, devp->index);
- if (err != 0) {
- BATT_DBG(CE_WARN, NULL,
- "Failed to add attr [%s] for %s/%s event",
- ACPIEV_DEV_INDEX, EC_ACPIEV, ev);
- nvlist_free(attr_list);
- return;
- }
-
- (void) ddi_pathname(batt_dip, pathname);
- err = nvlist_add_string(attr_list, ACPIEV_DEV_PHYS_PATH, pathname);
- if (err != 0) {
- BATT_DBG(CE_WARN, NULL,
- "Failed to add attr [%s] for %s/%s event",
- ACPIEV_DEV_PHYS_PATH, EC_ACPIEV, ev);
- nvlist_free(attr_list);
- return;
- }
-
- if (strcmp(ev, ESC_ACPIEV_WARN) && strcmp(ev, ESC_ACPIEV_LOW)) {
- goto finish;
- }
-
- err = nvlist_add_uint32(attr_list, ACPIEV_CHARGE_LEVEL, val);
- if (err != 0) {
- BATT_DBG(CE_WARN, NULL,
- "Failed to add attr [%s] for %s/%s event",
- ACPIEV_CHARGE_LEVEL, EC_ACPIEV, ev);
- nvlist_free(attr_list);
- return;
- }
-
-finish:
- BATT_DBG(CE_NOTE, NULL, "SysEv(%s, %s.%s, %d)",
- ev, devp->hid, devp->uid, val);
- /* Generate/log sysevent */
- err = ddi_log_sysevent(batt_dip, DDI_VENDOR_SUNW, EC_ACPIEV,
- ev, attr_list, NULL, DDI_NOSLEEP);
-#ifdef DEBUG
- if (err != DDI_SUCCESS) {
- BATT_DBG(CE_WARN, NULL,
- "cannot log sysevent, err code %x\n", err);
- }
-#endif
-
- nvlist_free(attr_list);
-}
-
-static int
-batt_obj_copy(ACPI_OBJECT *op, char *bp, struct obj_desc *dp)
-{
- ACPI_OBJECT *ep;
- char *fp;
-
- ep = &op->Package.Elements[0];
- for (; dp->offset != -1; dp++) {
- fp = bp + dp->offset;
- if (dp->type == ACPI_TYPE_INTEGER &&
- ep->Type == dp->type) {
-#ifdef DEBUG
- if (dp->size <= 4) {
- BATT_DBG(CE_NOTE, NULL, "\t%s: %u", dp->name,
- (uint32_t)ep->Integer.Value);
- } else {
-#ifdef _LP64
- BATT_DBG(CE_NOTE, NULL, "\t%s: %lu",
- dp->name, (uint64_t)ep->Integer.Value);
- }
-#else
- BATT_DBG(CE_NOTE, NULL, "\t%s: %llu",
- dp->name, (uint64_t)ep->Integer.Value);
- }
-#endif /* _LP64 */
-#endif /* DEBUG */
- *(uint32_t *)fp = ep->Integer.Value;
- } else if (dp->type == ACPI_TYPE_STRING &&
- ep->Type == dp->type) {
- BATT_DBG(CE_NOTE, NULL, "\t%s: \"%s\"",
- dp->name, ep->String.Pointer);
- (void) strncpy(fp, ep->String.Pointer, dp->size);
- } else if (dp->type == ACPI_TYPE_STRING &&
- ep->Type == ACPI_TYPE_BUFFER) {
-#ifdef DEBUG
- int len;
- char buf[MAXNAMELEN + 1];
-
- len = (MAXNAMELEN < ep->Buffer.Length) ?
- MAXNAMELEN : ep->Buffer.Length;
- bcopy(ep->Buffer.Pointer, buf, len);
- buf[len] = 0;
- BATT_DBG(CE_NOTE, NULL, "\t%s: [%d] \"%s\"",
- dp->name, len, buf);
-#endif
-
- ASSERT(MAXNAMELEN >= ep->Buffer.Length);
- bcopy(ep->Buffer.Pointer, fp, ep->Buffer.Length);
- } else {
- BATT_DBG(CE_WARN, NULL,
- "Bad field at offset %d: type %d",
- dp->offset, ep->Type);
- if (dp->type != ACPI_TYPE_STRING) {
- return (BATT_ERR);
- }
- }
- ep++;
- }
-
- return (BATT_OK);
-}
-
-static int
-batt_eval_int(ACPI_HANDLE hdl, ACPI_STRING name, ACPI_OBJECT_LIST *parms,
- int *rval)
-{
- ACPI_BUFFER buf;
- ACPI_OBJECT obj;
-
- buf.Length = sizeof (obj);
- buf.Pointer = &obj;
-
- if (ACPI_FAILURE(AcpiEvaluateObjectTyped(hdl, name, parms, &buf,
- ACPI_TYPE_INTEGER))) {
- return (BATT_ERR);
- }
-
- *rval = (int)obj.Integer.Value;
- return (BATT_OK);
-}
-
-/*
- * Returns the current power source devices. Used for the AC adapter and is
- * located under the AC adapter object in name space. Used to determine if
- * system is running off the AC adapter. This will report that the system is
- * not running on the AC adapter if any of the batteries in the system is
- * being forced to discharge through _BMC.
- *
- * Return value:
- * 0 -- Off-line, ie. battery supplying system power
- * 1 -- On-line, ie. AC supplying system power
- * -1 -- Unknown, some error ocurred.
- * Note: It will also update the driver ac state.
- */
-static int
-batt_get_psr(struct batt_ac_state *acp)
-{
- struct batt_acpi_dev *devp = &acp->dev;
- int ac;
-
- if (!devp->valid) {
- BATT_DBG(CE_WARN, NULL, "device not valid");
- return (-1);
- }
-
- if (ACPI_FAILURE(batt_eval_int(devp->hdl, "_PSR", NULL, &ac))) {
- BATT_DBG(CE_WARN, NULL, "AcpiEval _PSR failed");
- devp->present = -1;
- } else {
- BATT_DBG(CE_NOTE, devp, "_PSR = %d", ac);
- devp->present = ac;
- }
-
- return (ac);
-}
-
-/*
- * For most systems, the _STA for this device will always
- * return a value with bits 0-3 set and will toggle bit 4
- * to indicate the actual presence of a battery.
- *
- * Return value:
- * 0 -- battery not present
- * 1 -- battery present
- * -1 -- Unknown, some error ocurred.
- * Note: It will also update the driver cbat state.
- */
-static int
-batt_get_sta(struct batt_cbat_state *bp)
-{
- struct batt_acpi_dev *devp = &bp->dev;
- int val;
-
- if (!devp->valid) {
- BATT_DBG(CE_WARN, NULL, "device not valid");
- return (-1);
- }
-
- if (batt_eval_int(devp->hdl, "_STA", NULL, &val) == BATT_ERR) {
- BATT_DBG(CE_WARN, NULL, "AcpiEval _STA failed");
- devp->present = -1;
- } else {
- BATT_DBG(CE_NOTE, devp, "_STA = 0x%x", val);
- devp->present = ((val & STA_FLAG_BATT_PRESENT) != 0);
- }
-
- return (val);
-}
-
-static int
-batt_get_bif(acpi_bif_t *bifp, struct batt_cbat_state *bp)
-{
- /* BIF is only available when battery plugged */
- ASSERT(bp->dev.present != 0);
-
- /* Update internal BIF cache */
- if (bp->bat_bifok != BATT_NTF_OK) {
- ACPI_BUFFER buf;
- ACPI_OBJECT *objp;
-
- buf.Length = ACPI_ALLOCATE_BUFFER;
- if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BIF",
- NULL, &buf, ACPI_TYPE_PACKAGE))) {
- BATT_DBG(CE_WARN, NULL, "AcpiEval _BIF failed");
- return (BATT_ERR);
- }
-
- objp = buf.Pointer;
- BATT_DBG(CE_NOTE, &bp->dev, "get _BIF");
- if (batt_obj_copy(objp, (char *)&bp->bif_cache, bif_desc) ==
- BATT_ERR) {
- AcpiOsFree(objp);
- return (BATT_ERR);
- }
- AcpiOsFree(objp);
-
- bp->bat_bifok = BATT_NTF_OK;
- }
-
- /* Copy BIF back to user */
- if (bifp) {
- *bifp = bp->bif_cache;
- }
- return (BATT_OK);
-}
-
-static int
-batt_get_bst(acpi_bst_t *bstp, struct batt_cbat_state *bp)
-{
- /* BST is only available when battery plugged */
- ASSERT(bp->dev.present != 0);
-
- /* Update internal BST cache */
- if (bp->bat_bstok != BATT_NTF_OK) {
- ACPI_BUFFER buf;
- ACPI_OBJECT *objp;
-
- buf.Length = ACPI_ALLOCATE_BUFFER;
- if (ACPI_FAILURE(AcpiEvaluateObjectTyped(bp->dev.hdl, "_BST",
- NULL, &buf, ACPI_TYPE_PACKAGE))) {
- BATT_DBG(CE_WARN, NULL, "AcpiEval _BST failed");
- return (BATT_ERR);
- }
-
- objp = buf.Pointer;
- BATT_DBG(CE_NOTE, &bp->dev, "get _BST");
- if (batt_obj_copy(objp, (char *)&bp->bst_cache, bst_desc) ==
- BATT_ERR) {
- AcpiOsFree(objp);
- return (BATT_ERR);
- }
- AcpiOsFree(objp);
-
- if (bp->bst_cache.bst_rate == 0) {
- bp->bst_cache.bst_state &= ~(BATT_BST_CHARGING |
- BATT_BST_DISCHARGING);
- }
- bp->bat_bstok = BATT_NTF_OK;
- }
-
- /* Copy BST back to user */
- if (bstp) {
- *bstp = bp->bst_cache;
- }
- return (BATT_OK);
-}
-
-static int
-batt_update_bif(struct batt_cbat_state *bp)
-{
- bp->bat_bifok = BATT_NTF_UNKNOWN;
- return (batt_get_bif(NULL, bp));
-}
-
-static int
-batt_update_bst(struct batt_cbat_state *bp)
-{
- bp->bat_bstok = BATT_NTF_UNKNOWN;
- return (batt_get_bst(NULL, bp));
-}
-
-/*
- * Return value:
- * 1 -- device On-line
- * 0 -- device Off-line
- * -1 -- Unknown, some error ocurred.
- */
-static int
-batt_dev_present(struct batt_acpi_dev *devp)
-{
- if (!devp->valid) {
- BATT_DBG(CE_WARN, NULL, "device not valid");
- return (-1);
- }
-
- ASSERT(devp->type != BATT_TYPE_UNKNOWN);
-
- /* Update the device state */
- if (devp->present == -1) {
- if (devp->type == BATT_TYPE_AC) {
- (void) batt_get_psr((struct batt_ac_state *)devp);
- } else if (devp->type == BATT_TYPE_CBAT) {
- (void) batt_get_sta((struct batt_cbat_state *)devp);
- }
- }
-
- return (devp->present);
-}
-
-/*
- * Check if the device p existance state has changed.
- * Return value:
- * 1 -- changed
- * 0 -- no change
- * -1 -- unknown
- */
-static int
-batt_update_present(struct batt_acpi_dev *p)
-{
- int old_present = p->present;
- int new_present;
-
- ASSERT(p && p->valid);
-
- p->present = -1;
- new_present = batt_dev_present(p);
- if (new_present == -1) {
- return (-1);
- }
- if (new_present != old_present) {
- return (1);
- }
- return (0);
-}
-
-static void
-batt_set_psr(struct batt_acpi_dev *p)
-{
- batt_psr_devp = p;
- if (p != NULL) {
- BATT_DBG(CE_NOTE, p, "psr = .");
- batt_psr_type = p->type;
- } else {
- BATT_DBG(CE_NOTE, p, "psr = ?");
- batt_psr_type = BATT_TYPE_UNKNOWN;
- }
-}
-
-/*
- * OSPM can determine independent warning and low battery
- * capacity values based on the OEM-designed levels, but
- * cannot set these values lower than the OEM-designed values.
- */
-static int
-batt_set_warn(batt_warn_t *bwp)
-{
- uint32_t warn, low;
-
- warn = batt_syn_last_cap * bwp->bw_charge_warn / 100;
- low = batt_syn_last_cap * bwp->bw_charge_low / 100;
-
- /* Update internal state */
- if (bwp->bw_enabled) {
- if (low >= warn || warn < batt_syn_oem_warn_cap ||
- low < batt_syn_oem_low_cap) {
- BATT_DBG(CE_WARN, NULL, "charge level error");
- return (EINVAL);
- }
-
- BATT_DBG(CE_NOTE, NULL, "set warn: warn=%d low=%d", warn, low);
-
- batt_syn_warn_per = bwp->bw_charge_warn;
- batt_syn_low_per = bwp->bw_charge_low;
- batt_syn_warn_cap = warn;
- batt_syn_low_cap = low;
- batt_warn_enabled = 1;
- } else {
- batt_warn_enabled = 0;
- }
-
- return (0);
-}
-
-/*
- * Update information for the synthesis battery
- *
- * Note: Sometimes the value to be returned from _BST or _BIF will be
- * temporarily unknown. In this case, the method may return the value
- * 0xFFFFFFFF as a placeholder. When the value becomes known, the
- * appropriate notification (0x80 for _BST or 0x81 for BIF) should be
- * issued, in like manner to any other change in the data returned by
- * these methods. This will cause OSPM to re-evaluate the method obtaining
- * the correct data value.
- */
-static void
-batt_update_cap(int bif_changed)
-{
- struct batt_cbat_state *bp;
-
- if (bif_changed != 0) {
- batt_syn_oem_warn_cap = 0xffffffff;
- batt_syn_oem_low_cap = 0xffffffff;
- batt_syn_last_cap = 0xffffffff;
- }
- batt_syn_last_level = batt_syn_rem_cap;
- batt_syn_rem_cap = 0xffffffff; /* initially unknown */
-
- for (bp = &batt_cbat[0]; bp < &batt_cbat[BATT_MAX_BAT_NUM]; bp++) {
- if (bp->dev.valid) {
- /* Escape the empty bays */
- if (batt_cbat_present(bp) <= 0) {
- continue;
- }
-
- if (bif_changed != 0 && bp->bat_bifok == BATT_NTF_OK) {
- acpi_bif_t *bif;
-
- bif = &bp->bif_cache;
-
- if (batt_syn_last_cap == 0xffffffff) {
- batt_syn_last_cap = 0;
- }
- batt_syn_last_cap += bif->bif_last_cap;
-
- if (bif->bif_warn_cap == 0xffffffff ||
- bif->bif_low_cap == 0xffffffff) {
- BATT_DBG(CE_WARN, &bp->dev, "BIF value "
- "invalid, warn_cap=0x%x "
- "low_cap=0x%x", bif->bif_warn_cap,
- bif->bif_low_cap);
- continue;
- }
- if (batt_syn_oem_warn_cap == 0xffffffff) {
- batt_syn_oem_warn_cap = 0;
- }
- if (batt_syn_oem_low_cap == 0xffffffff) {
- batt_syn_oem_low_cap = 0;
- }
-
- /*
- * Use the highest level as the synthesis
- * level.
- */
- if (bif->bif_warn_cap > batt_syn_oem_warn_cap) {
- batt_syn_oem_low_cap = bif->bif_low_cap;
- batt_syn_oem_warn_cap =
- bif->bif_warn_cap;
- }
- }
-#ifdef DEBUG
- else if (bif_changed) {
- BATT_DBG(CE_NOTE, &bp->dev, "BIF not ready");
- }
-#endif
-
- if (bp->bat_bstok == BATT_NTF_OK) {
- acpi_bst_t *bst;
-
- bst = &bp->bst_cache;
-
- /*
- * Batteries that are rechargeable and are in
- * the discharging state are required to return
- * a valid Battery Present Rate value.
- * 0xFFFFFFFF - Unknown rate/capacity
- */
- if (bst->bst_rem_cap == 0xffffffff) {
- BATT_DBG(CE_WARN, &bp->dev,
- "BST value invalid, "
- "rate=0x%x cap=0x%x",
- bst->bst_rate, bst->bst_rem_cap);
- continue;
- }
-
- if (batt_syn_rem_cap == 0xffffffff) {
- batt_syn_rem_cap = 0;
- }
- batt_syn_rem_cap += bst->bst_rem_cap;
- /* Check for overflow */
- ASSERT(batt_syn_rem_cap >= bst->bst_rem_cap);
- }
-#ifdef DEBUG
- else {
- BATT_DBG(CE_NOTE, &bp->dev, "BST not ready");
- }
-#endif
- }
- }
-
- BATT_DBG(CE_NOTE, NULL, "syn_cap: %d syn_oem_warn: %d syn_oem_low: %d",
- batt_syn_rem_cap, batt_syn_oem_warn_cap, batt_syn_oem_low_cap);
-}
-
-static struct batt_cbat_state *
-batt_idx2cbat(int idx)
-{
- if (idx >= BATT_MAX_BAT_NUM) {
- return (NULL);
- }
- return (&batt_cbat[idx]);
-}
-
-static struct batt_ac_state *
-batt_idx2ac(int idx)
-{
- if (idx >= BATT_MAX_AC_NUM) {
- return (NULL);
- }
- return (&batt_ac[idx]);
-}
-
-/*ARGSUSED*/
-static void
-batt_cbat_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
-{
- struct batt_cbat_state *bp = ctx;
- struct batt_acpi_dev *devp = &bp->dev;
- int bif_changed;
- uint32_t eval;
- char *ev;
- acpi_bst_t *bst;
-
- BATT_PRT_NOTIFY(hdl, val);
- mutex_enter(&batt_mutex);
-
- switch (val) {
- /*
- * BST has changed
- * Whenever the Battery State value changes, the
- * system will generate an SCI to notify the OS.
- *
- * Note: trip point is not used to implement the
- * warning levels.
- */
- case 0x80:
- /*
- * We always get 0x80 and 0x81 at battery plug/unplug,
- * but 0x80 may come first. In case that situation, we have
- * to update battery present state here too to update bst
- * correctly.
- */
- bif_changed = batt_update_present(devp);
-
- /* Omit events sent by empty battery slot */
- if (devp->present == 0) {
- break;
- }
-
- if (batt_update_bst(bp) != BATT_OK) {
- break;
- }
- batt_update_cap(bif_changed);
-
- bst = &bp->bst_cache;
- eval = bst->bst_rem_cap;
-
- /*
- * Keep tracking the current power source device
- *
- * Note: Even no battery plugged, some system
- * send out 0x80 ACPI event. So make sure the battery
- * is present first.
- */
- if (devp->present == 0) {
- if (batt_psr_devp == devp) {
- batt_set_psr(NULL);
- }
- break;
- }
- if (bst->bst_state & BST_FLAG_DISCHARGING) {
- batt_set_psr(devp);
- }
- /*
- * The Critical battery state indicates that all
- * available batteries are discharged and do not
- * appear to be able to supply power to run the
- * system any longer. When this occurs, the OS
- * should attempt to perform an emergency shutdown.
- * Right now we do not shutdown. This would
- * need some discussion first since it could be
- * controversial.
- */
-#ifdef DEBUG
- if (bst->bst_state & BST_FLAG_CRITICAL) {
- BATT_DBG(CE_WARN, devp, "BST_FLAG_CRITICAL set");
-
- /*
- * BST_FLAG_CRITICAL may set even with AC,
- * plugged, when plug/unplug battery. Check
- * to avoid erroneous shutdown.
- */
- if (batt_psr_devp == devp &&
- bst->bst_rem_cap != 0xffffffff) {
- BATT_DBG(CE_WARN, NULL,
- "Battery in critical state");
- }
- } else
-#endif
- if (batt_warn_enabled &&
- (bst->bst_state & BST_FLAG_DISCHARGING)) {
- /*
- * This value is an estimation of the amount of
- * energy or battery capacity required by the
- * system to transition to any supported sleeping
- * state. When the OS detects that the total
- * available battery capacity is less than this
- * value, it will transition the system to a user
- * defined system state (S1-S5).
- */
- if (batt_syn_last_level > batt_syn_low_cap &&
- batt_syn_rem_cap <= batt_syn_low_cap) {
- batt_gen_sysevent(devp, ESC_ACPIEV_LOW, eval);
- /*
- * When the total available energy (mWh) or capacity
- * (mAh) in the batteries falls below this level,
- * the OS will notify the user through the UI.
- */
- } else if (batt_syn_last_level > batt_syn_warn_cap &&
- batt_syn_rem_cap <= batt_syn_warn_cap) {
- batt_gen_sysevent(devp, ESC_ACPIEV_WARN, eval);
- }
- }
-
- batt_gen_sysevent(devp, ESC_ACPIEV_STATE_CHANGE, 0);
- pollwakeup(&batt_pollhead, BATT_EVENTS);
- break;
-
- /* BIF has changed */
- case 0x81:
- /*
- * Note: Do not eliminate multiple ADD/REMOVE here,
- * because they may corresponding to different batterys.
- */
- (void) batt_update_present(devp);
- if (devp->present == 1) {
- if (batt_update_bif(bp) != BATT_OK) {
- break;
- }
- } else {
- bp->bat_bifok = BATT_NTF_UNKNOWN;
- bp->bat_bstok = BATT_NTF_UNKNOWN;
- }
-
- batt_update_cap(1);
-
- eval = devp->present;
- ev = eval ? ESC_ACPIEV_ADD : ESC_ACPIEV_REMOVE;
- batt_gen_sysevent(devp, ev, 0);
- pollwakeup(&batt_pollhead, BATT_EVENTS);
- break;
-
- case 0x82:
- default:
- break;
- }
-
- mutex_exit(&batt_mutex);
-}
-
-/*ARGSUSED*/
-static void
-batt_ac_notify(ACPI_HANDLE hdl, UINT32 val, void *ctx)
-{
- struct batt_ac_state *acp = ctx;
- struct batt_acpi_dev *devp = &acp->dev;
- int old_present;
- char *ev;
- int eval;
-
- BATT_PRT_NOTIFY(hdl, val);
- if (val != 0x80) {
- return;
- }
- mutex_enter(&batt_mutex);
-
- /*
- * Note: if unplug and then quickly plug back, two ADD
- * events will be generated.
- */
- old_present = devp->present;
- eval = batt_get_psr(acp);
-
- /* Eliminate redudant events */
- if (eval != -1 && eval != old_present) {
- /* Keep tracking the current power source device */
- if (eval == 1) {
- ev = ESC_ACPIEV_ADD;
- batt_set_psr(devp);
- } else {
- ev = ESC_ACPIEV_REMOVE;
- /* If AC was supplying the power, it's not now */
- if (batt_psr_devp == devp) {
- batt_set_psr(NULL);
- }
- }
-
- batt_gen_sysevent(devp, ev, 0);
- pollwakeup(&batt_pollhead, BATT_EVENTS);
- }
-
- mutex_exit(&batt_mutex);
-}
-
-static int
-batt_obj_init(struct batt_acpi_dev *p)
-{
- ACPI_DEVICE_INFO *info;
- ACPI_HANDLE hdl;
- ACPI_BUFFER buf;
- ACPI_NOTIFY_HANDLER ntf_handler = NULL;
- ACPI_STATUS ret;
-
- ASSERT(p != NULL && p->hdl != NULL);
-
- hdl = p->hdl;
-
- /* Info size is variable depending on existance of _CID */
- buf.Length = ACPI_ALLOCATE_BUFFER;
- ret = AcpiGetObjectInfo(hdl, &buf);
- if (ACPI_FAILURE(ret)) {
- BATT_DBG(CE_WARN, NULL,
- "AcpiGetObjectInfo() fail: %d", (int32_t)ret);
- return (BATT_ERR);
- }
-
- info = buf.Pointer;
-
- if ((info->Valid & ACPI_VALID_HID) == 0) {
- BATT_DBG(CE_WARN, NULL,
- "AcpiGetObjectInfo(): _HID not available");
- AcpiOsFree(info);
- return (BATT_ERR);
- }
- (void) strncpy(p->hid, info->HardwareId.Value, 9);
-
- /*
- * This object is optional, but is required when the device
- * has no other way to report a persistent unique device ID.
- */
- if ((info->Valid & ACPI_VALID_UID) == 0) {
- BATT_DBG(CE_WARN, NULL,
- "AcpiGetObjectInfo(): _UID not available");
- /* Use 0 as the default _UID */
- (void) strncpy(p->uid, "0", 9);
- } else {
- (void) strncpy(p->uid, info->UniqueId.Value, 9);
- }
-
- p->valid = 1;
- p->type = BATT_TYPE_UNKNOWN;
-
- if (strcmp(p->hid, ACPI_DEVNAME_CBAT) == 0) {
- struct batt_cbat_state *bp = (struct batt_cbat_state *)p;
-
- p->type = BATT_TYPE_CBAT;
- p->index = nbat - 1;
- bp->bat_bifok = BATT_NTF_UNKNOWN;
- bp->bat_bstok = BATT_NTF_UNKNOWN;
-
- /* Update device present state */
- (void) batt_update_present(p);
- if (p->present) {
- (void) batt_update_bif(bp);
- (void) batt_update_bst(bp);
-
- /* Init the current power source */
- if (bp->bst_cache.bst_state & BST_FLAG_DISCHARGING) {
- batt_set_psr(p);
- }
- }
- ntf_handler = batt_cbat_notify;
- BATT_DBG(CE_NOTE, p, "battery %s",
- (p->present ? "present" : "absent"));
- } else if (strcmp(p->hid, ACPI_DEVNAME_AC) == 0) {
- p->type = BATT_TYPE_AC;
- p->index = nac - 1;
-
- /* Update device present state */
- (void) batt_update_present(p);
- if (p->present) {
- /* Init the current power source */
- batt_set_psr(p);
- }
- ntf_handler = batt_ac_notify;
- BATT_DBG(CE_NOTE, p, "AC %s",
- (p->present ? "on-line" : "off-line"));
- } else if (strcmp(p->hid, ACPI_DEVNAME_SBAT) == 0) {
- p->type = BATT_TYPE_SBAT;
- BATT_DBG(CE_NOTE, p, "added");
- } else {
- BATT_DBG(CE_NOTE, p, "unknown device");
- p->valid = 0;
- }
-
- /* Register ACPI battery related events */
- if (ntf_handler != NULL) {
- if (ACPI_FAILURE(AcpiInstallNotifyHandler(hdl,
- ACPI_ALL_NOTIFY, ntf_handler, p))) {
- BATT_DBG(CE_NOTE, NULL,
- "Notify handler for %s.%s install failed",
- p->hid, p->uid);
- return (BATT_ERR);
- }
- }
-
-out:
- AcpiOsFree(info);
- return (BATT_OK);
-}
-
-/*ARGSUSED*/
-static ACPI_STATUS
-batt_find_cb(ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context,
- void **ReturnValue)
-{
- struct batt_acpi_dev *devp = (struct batt_acpi_dev *)Context;
-
- if (devp == &batt_cbat[0].dev) {
- struct batt_cbat_state *bp;
-
- if (nbat == BATT_MAX_BAT_NUM) {
- BATT_DBG(CE_WARN, NULL,
- "Need to support more batteries: "
- "BATTERY_MAX = %d", BATT_MAX_BAT_NUM);
- return (AE_LIMIT);
- }
- bp = &batt_cbat[nbat++];
- devp = (struct batt_acpi_dev *)bp;
- } else if (devp == &batt_ac[0].dev) {
- struct batt_ac_state *ap;
-
- if (nac == BATT_MAX_AC_NUM) {
- BATT_DBG(CE_WARN, NULL, "Need to support more ACs: "
- "AC_MAX = %d", BATT_MAX_AC_NUM);
- return (AE_LIMIT);
- }
- ap = &batt_ac[nac++];
- devp = (struct batt_acpi_dev *)ap;
- }
-
- devp->hdl = ObjHandle;
- *ReturnValue = NULL;
-
- /* Try to get as many working objs as possible */
- (void) batt_obj_init(devp);
- return (0);
-}
-
-static int
-batt_acpi_init()
-{
- int *retp;
-
- /* Check to see if ACPI CA services are available */
- if (AcpiSubsystemStatus() != AE_OK) {
- BATT_DBG(CE_WARN, NULL, "ACPI CA not ready");
- return (BATT_ERR);
- }
-
- /* Init Control Method Batterys */
- if (ACPI_FAILURE(AcpiGetDevices(ACPI_DEVNAME_CBAT, batt_find_cb,
- batt_cbat, (void *)&retp))) {
- return (BATT_ERR);
- }
-
- /* Init AC */
- if (ACPI_FAILURE(AcpiGetDevices(ACPI_DEVNAME_AC, batt_find_cb, batt_ac,
- (void *)&retp))) {
- return (BATT_ERR);
- }
-
- /* Init Smart Battery */
- if (ACPI_FAILURE(AcpiGetDevices(ACPI_DEVNAME_SBAT, batt_find_cb,
- &batt_sbat, (void *)&retp))) {
- return (BATT_ERR);
- }
-
- batt_update_cap(1);
-
- return (BATT_OK);
-}
-
-static void
-batt_acpi_fini(void)
-{
- int i;
- struct batt_cbat_state *bp;
-
- for (bp = &batt_cbat[0]; bp < &batt_cbat[BATT_MAX_BAT_NUM]; bp++) {
- if (bp->dev.valid) {
- AcpiRemoveNotifyHandler(bp->dev.hdl, ACPI_DEVICE_NOTIFY,
- batt_cbat_notify);
- }
- }
- for (i = 0; i < nac; i++) {
- AcpiRemoveNotifyHandler(batt_ac[i].dev.hdl, ACPI_DEVICE_NOTIFY,
- batt_ac_notify);
- }
-}
-
-/*ARGSUSED*/
-static int
-batt_kstat_power_update(kstat_t *ksp, int flag)
-{
- if (flag == KSTAT_WRITE) {
- return (EACCES);
- }
-
- mutex_enter(&batt_mutex);
- if (batt_psr_type == BATT_TYPE_UNKNOWN) {
- mutex_exit(&batt_mutex);
- return (EIO);
- }
- kstat_named_setstr(&batt_power_kstat.batt_power,
- batt_psr_type == BATT_TYPE_AC ? AC : BATTERY);
- batt_power_kstat.batt_supported_battery_count.value.ui32 =
- (uint32_t)nbat;
- mutex_exit(&batt_mutex);
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-batt_kstat_warn_update(kstat_t *ksp, int flag)
-{
- if (flag == KSTAT_WRITE) {
- int ret = 0;
- batt_warn_t bw;
- batt_warn_kstat_t kbw;
-
- kbw = *(batt_warn_kstat_t *)batt_warn_ksp->ks_data;
-
- mutex_enter(&batt_mutex);
- bw.bw_enabled = kbw.batt_bw_enabled.value.ui32;
- bw.bw_charge_warn = kbw.batt_bw_charge_warn.value.ui32;
- bw.bw_charge_low = kbw.batt_bw_charge_low.value.ui32;
- ret = batt_set_warn(&bw);
- mutex_exit(&batt_mutex);
-
- return (ret);
- } else {
- batt_warn_kstat_t *wp = &batt_warn_kstat;
-
- mutex_enter(&batt_mutex);
- wp->batt_bw_enabled.value.ui32 = batt_warn_enabled;
- wp->batt_bw_charge_warn.value.ui32 = batt_syn_warn_per;
- wp->batt_bw_charge_low.value.ui32 = batt_syn_low_per;
- mutex_exit(&batt_mutex);
-
- return (0);
- }
-}
-
-static int
-batt_kstat_bif_update(kstat_t *ksp, int flag)
-{
- struct batt_cbat_state *bp;
- acpi_bif_t bif;
- batt_bif_kstat_t *kp;
-
- if (flag == KSTAT_WRITE) {
- return (EACCES);
- }
-
- bp = (struct batt_cbat_state *)ksp->ks_private;
- mutex_enter(&batt_mutex);
-
- if (batt_cbat_present(bp) <= 0) {
- mutex_exit(&batt_mutex);
- return (ENXIO);
- }
-
- bzero(&bif, sizeof (bif));
- bp->bat_bifok = BATT_NTF_UNKNOWN;
- if (batt_get_bif(&bif, bp) != BATT_OK) {
- mutex_exit(&batt_mutex);
- return (ENXIO);
- }
-
- kp = &batt_bif_kstat;
-
- /* Update BIF */
- kp->batt_bif_unit.value.ui32 = bif.bif_unit;
- kp->batt_bif_design_cap.value.ui32 = bif.bif_design_cap;
- kp->batt_bif_last_cap.value.ui32 = bif.bif_last_cap;
- kp->batt_bif_tech.value.ui32 = bif.bif_tech;
- kp->batt_bif_voltage.value.ui32 = bif.bif_voltage;
- kp->batt_bif_warn_cap.value.ui32 = bif.bif_warn_cap;
- kp->batt_bif_low_cap.value.ui32 = bif.bif_low_cap;
- kp->batt_bif_gran1_cap.value.ui32 = bif.bif_gran1_cap;
- kp->batt_bif_gran2_cap.value.ui32 = bif.bif_gran2_cap;
-
- kstat_named_setstr(&kp->batt_bif_model, bif.bif_model);
- kstat_named_setstr(&kp->batt_bif_serial, bif.bif_serial);
- kstat_named_setstr(&kp->batt_bif_type, bif.bif_type);
- kstat_named_setstr(&kp->batt_bif_oem_info, bif.bif_oem_info);
-
- mutex_exit(&batt_mutex);
- return (0);
-}
-
-static int
-batt_kstat_bst_update(kstat_t *ksp, int flag)
-{
- struct batt_cbat_state *bp;
- acpi_bst_t bst;
- batt_bst_kstat_t *kp;
-
- if (flag == KSTAT_WRITE) {
- return (EACCES);
- }
-
- bp = (struct batt_cbat_state *)ksp->ks_private;
- mutex_enter(&batt_mutex);
-
- if (batt_cbat_present(bp) <= 0) {
- mutex_exit(&batt_mutex);
- return (ENXIO);
- }
-
- bzero(&bst, sizeof (bst));
- bp->bat_bstok = BATT_NTF_UNKNOWN;
- if (batt_get_bst(&bst, bp) != BATT_OK) {
- mutex_exit(&batt_mutex);
- return (ENXIO);
- }
-
- kp = &batt_bst_kstat;
-
- /* Update BST */
- kp->batt_bst_state.value.ui32 = bst.bst_state;
- kp->batt_bst_rate.value.ui32 = bst.bst_rate;
- kp->batt_bst_rem_cap.value.ui32 = bst.bst_rem_cap;
- kp->batt_bst_voltage.value.ui32 = bst.bst_voltage;
-
- mutex_exit(&batt_mutex);
- return (0);
-}
-
-static int
-batt_kstat_init(void)
-{
- char name[KSTAT_STRLEN];
- struct batt_cbat_state *bp;
-
- /*
- * Allocate, initialize and install powerstatus and
- * supported_battery_count kstat.
- */
- batt_power_ksp = kstat_create(BATT_DRV_NAME, 0,
- BATT_POWER_KSTAT_NAME, "misc",
- KSTAT_TYPE_NAMED,
- sizeof (batt_power_kstat) / sizeof (kstat_named_t),
- KSTAT_FLAG_VIRTUAL);
- if (batt_power_ksp == NULL) {
- BATT_DBG(CE_WARN, NULL,
- "kstat_create(%s) fail", BATT_POWER_KSTAT_NAME);
- return (BATT_ERR);
- }
-
- batt_power_ksp->ks_data = &batt_power_kstat;
- batt_power_ksp->ks_update = batt_kstat_power_update;
- batt_power_ksp->ks_data_size += MAXNAMELEN;
- kstat_install(batt_power_ksp);
-
- /*
- * Allocate, initialize and install battery_capacity_warning kstat.
- */
- batt_warn_ksp = kstat_create(BATT_DRV_NAME, 0,
- BATT_BTWARN_KSTAT_NAME, "misc",
- KSTAT_TYPE_NAMED,
- sizeof (batt_warn_kstat) / sizeof (kstat_named_t),
- KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
- if (batt_warn_ksp == NULL) {
- BATT_DBG(CE_WARN, NULL,
- "kstat_create(%s) fail", BATT_BTWARN_KSTAT_NAME);
- return (BATT_ERR);
- }
-
- batt_warn_ksp->ks_data = &batt_warn_kstat;
- batt_warn_ksp->ks_update = batt_kstat_warn_update;
- kstat_install(batt_warn_ksp);
-
- /*
- * Allocate, initialize and install BIF and BST kstat
- * for each battery.
- */
- for (bp = &batt_cbat[0]; bp < &batt_cbat[BATT_MAX_BAT_NUM]; bp++) {
- if (bp->dev.valid) {
- kstat_t *ksp;
-
- /* BIF kstat */
- (void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
- BATT_BIF_KSTAT_NAME, bp->dev.index);
- ksp = kstat_create(BATT_DRV_NAME, 0,
- name, "misc", KSTAT_TYPE_NAMED,
- sizeof (batt_bif_kstat) / sizeof (kstat_named_t),
- KSTAT_FLAG_VIRTUAL);
- if (ksp == NULL) {
- BATT_DBG(CE_WARN, NULL, "kstat_create(%s) fail",
- name);
- return (BATT_ERR);
- }
- BATT_DBG(CE_NOTE, NULL, "kstat_create(%s) ok", name);
-
- bp->bat_bif_ksp = ksp;
- ksp->ks_data = &batt_bif_kstat;
- ksp->ks_update = batt_kstat_bif_update;
- ksp->ks_data_size += MAXNAMELEN * 4;
- ksp->ks_private = bp;
-
- kstat_install(ksp);
-
- /* BST kstat */
- (void) snprintf(name, KSTAT_STRLEN-1, "%s%d",
- BATT_BST_KSTAT_NAME, bp->dev.index);
- ksp = kstat_create(BATT_DRV_NAME, 0, name, "misc",
- KSTAT_TYPE_NAMED,
- sizeof (batt_bst_kstat) / sizeof (kstat_named_t),
- KSTAT_FLAG_VIRTUAL);
- if (ksp == NULL) {
- BATT_DBG(CE_WARN, NULL,
- "kstat_create(%s) fail", name);
- return (BATT_ERR);
- }
- BATT_DBG(CE_NOTE, NULL, "kstat_create(%s) ok", name);
-
- bp->bat_bst_ksp = ksp;
- ksp->ks_data = &batt_bst_kstat;
- ksp->ks_update = batt_kstat_bst_update;
- ksp->ks_data_size += MAXNAMELEN * 4;
- ksp->ks_private = bp;
-
- kstat_install(ksp);
- }
- }
-
- return (BATT_OK);
-}
-
-static void
-batt_kstat_fini()
-{
- struct batt_cbat_state *bp;
-
- if (batt_power_ksp != NULL) {
- kstat_delete(batt_power_ksp);
- }
- if (batt_warn_ksp != NULL) {
- kstat_delete(batt_warn_ksp);
- }
- for (bp = &batt_cbat[0]; bp < &batt_cbat[BATT_MAX_BAT_NUM]; bp++) {
- if (bp->dev.valid) {
- if (bp->bat_bif_ksp != NULL) {
- kstat_delete(bp->bat_bif_ksp);
- }
- if (bp->bat_bst_ksp != NULL) {
- kstat_delete(bp->bat_bst_ksp);
- }
- }
- }
-}
diff --git a/usr/src/uts/intel/os/minor_perm b/usr/src/uts/intel/os/minor_perm
index dd4a22c682..93b00060fd 100644
--- a/usr/src/uts/intel/os/minor_perm
+++ b/usr/src/uts/intel/os/minor_perm
@@ -162,7 +162,7 @@ rtw:* 0666 root sys
wpi:* 0666 root sys
physmem:* 0600 root sys
sdp:sdp 0666 root sys
-battery:* 0666 root sys
+acpi_drv:* 0666 root sys
ucode:* 0644 root sys
dmfe:* 0666 root sys
afe:* 0666 root sys
diff --git a/usr/src/uts/intel/os/name_to_major b/usr/src/uts/intel/os/name_to_major
index efa9f0428f..03d52f9e68 100644
--- a/usr/src/uts/intel/os/name_to_major
+++ b/usr/src/uts/intel/os/name_to_major
@@ -136,7 +136,7 @@ lx_ptm 240
lx_systrace 241
lx_audio 242
physmem 243
-battery 244
+acpi_drv 244
ucode 245
ppm 246
cpunex 247