1#!/bin/sh
2#
3# Modify the power profile based on AC line state.  This script is
4# usually called from devd(8).
5#
6# Arguments: 0x00 (AC offline, economy) or 0x01 (AC online, performance)
7#
8# $FreeBSD$
9#
10
11# PROVIDE: power_profile
12# REQUIRE: FILESYSTEMS syslogd
13# KEYWORD: nojail nostart
14
15. /etc/rc.subr
16
17name="power_profile"
18desc="Modify the power profile based on AC line state"
19stop_cmd=':'
20LOGGER="logger -t power_profile -p daemon.notice"
21
22# Set a given sysctl node to a value.
23#
24# Variables:
25# $node: sysctl node to set with the new value
26# $value: HIGH for the highest performance value, LOW for the best
27#	  economy value, or the value itself.
28# $highest_value: maximum value for this sysctl, when $value is "HIGH"
29# $lowest_value: minimum value for this sysctl, when $value is "LOW"
30#
31sysctl_set()
32{
33	# Check if the node exists
34	if [ -z "$(sysctl -n ${node} 2> /dev/null)" ]; then
35		return
36	fi
37
38	# Get the new value, checking for special types HIGH or LOW
39	case ${value} in
40	[Hh][Ii][Gg][Hh])
41		value=${highest_value}
42		;;
43	[Ll][Oo][Ww])
44		value=${lowest_value}
45		;;
46	[Nn][Oo][Nn][Ee])
47		return
48		;;
49	*)
50		;;
51	esac
52
53	# Set the desired value
54	if [ -n "${value}" ]; then
55		if ! sysctl ${node}=${value} > /dev/null 2>&1; then
56			warn "unable to set ${node}=${value}"
57		fi
58	fi
59}
60
61if [ $# -ne 1 ]; then
62	err 1 "Usage: $0 [0x00|0x01]"
63fi
64load_rc_config $name
65
66# Find the next state (performance or economy).
67state=$1
68case ${state} in
690x01 | '')
70	${LOGGER} "changed to 'performance'"
71	profile="performance"
72	;;
730x00)
74	${LOGGER} "changed to 'economy'"
75	profile="economy"
76	;;
77*)
78	echo "Usage: $0 [0x00|0x01]"
79	exit 1
80esac
81
82# Set the various sysctls based on the profile's values.
83node="hw.acpi.cpu.cx_lowest"
84highest_value="C1"
85lowest_value="Cmax"
86eval value=\$${profile}_cx_lowest
87sysctl_set
88
89node="dev.cpu.0.freq"
90highest_value="`(sysctl -n dev.cpu.0.freq_levels | \
91	awk '{ split($0, a, "[/ ]"); print a[1] }' -) 2> /dev/null`"
92lowest_value="`(sysctl -n dev.cpu.0.freq_levels | \
93	awk '{ split($0, a, "[/ ]"); print a[length(a) - 1] }' -) 2> /dev/null`"
94eval value=\$${profile}_cpu_freq
95sysctl_set
96
97exit 0
98