#!/bin/bash
# -----------------------------------------------------------------------------
# $Id: pwrctl,v 1.1 2002/04/27 10:34:28 pvdabeel Exp $
#
# This script is invoked by pmud to configure the system for a
# given power level. The desired level is indicated by the first
# argument and can take the following values:
#
# minimum = minimum power
# medium  = medium power 
# maximum = full power  
# sleep   = prepare for sleep
# wakeup  = system woke up after a sleep
# warning = low battery condition detected, issue a warning to users
#
# the second argument gives the current power source, and can take the
# following values:
#
# ac
# battery
#
# This script is invoked when the AC power is connected or disconnected, 
# and also immediately after sleep. If the script /etc/power/pwrctl-local
# is present and executable, it will be called by this script before the
# main body of this script is executed. If pwrctl-local returns 1, then
# the main body of this script is NOT executed, in all other cases the
# main body of this script will be executed.
#
# Note that if you leave pwrctl-local writable by others than root (which
# should be the owner) you have created a serious security hole!
#
# You can edit this file, but it's better to edit /etc/power/pwrctl-local
# as that file will not be overwritten on upgrades.
# -----------------------------------------------------------------------------
# Debian add-on: support (sort of) for Core99 machines (Pismo,...). The
# Pismo can't sleep right now so it will wake again immediately. We spin
# down the disk on sleep, turn off backlight power and ignore the wakeup. 
# 
# While things are stabilizing, these commands could be used to put the system 
# into absolute minimum power mode. You can use commands of this sort in 
# /etc/init.d/powerfail if needs be (sample powerfail script is in
# /usr/share/doc/sysvinit/examples/).
# fblevel 0
# [ "`cat /proc/ide/hde/model`" != "(none)" ] && hdparm -f -S 1 -Y /dev/hde
# hdparm -f -S 1 -Y /dev/hda
# Use this to switch the display back on if the powerfail status is called
# off:
# fblevel 12
#
# 01/09/13: Recent 2.4 kernel versions support sleep properly, by all
# accounts. So shut down only if kernel version is insufficient. 
# Sample code to deal with broken airport drivers moved to pwrctl-local
# (courtesy Tom Rini).
#
# $Log: not supported by cvs2svn $
# Revision 1.1  2002/04/14 03:41:30  kain
# Initial import of PMUD for gentoo-ppc
#
# Revision 1.1.1.1  2001/12/07 11:31:53  sleemburg
# Initial CVS import of the unreleased pmud-0.8 to apmud (new project name
# because of a name clash at sourceforge.net).
#
# Revision 1.6  2000/12/12 08:56:57  stephan
# support for iBook and Pismo (same as other G3's)
#
# Revision 1.5  2000/10/09 14:33:40  stephan
# wakebay added
#
# Revision 1.4  2000/05/11 14:54:45  stephan
# pmud 0.6 changes
#
# Revision 1.3  2000/03/25 21:26:32  stephan
# pmud-0.5 changes
#
# Revision 1.2  2000/03/09 13:01:50  stephan
# formatting and call to pwrctl-local
#
# Revision 1.1  2000/01/06 13:48:19  stephan
# Initial revision
# -----------------------------------------------------------------------------
logger=/usr/bin/logger
localfun=/etc/power/pwrctl-local

function do_warn()
{
	local msg="Low battery, system will go down..."

	(
	/usr/X11R6/bin/xmessage -center -timeout 15 "$msg" || \
	echo "$msg" | /usr/bin/wall
	) &
}

function pwrctl_G3() 
{
	case "$1" in
	minimum)
	    	# min power, set disk to spin down after 1 minute
    		[ -f /sbin/hdparm ] && hdparm -p -S 12 /dev/hda
	;;
	medium)
	    	# medium power, set disk to spin down after 2.5 minutes
    		[ -f /sbin/hdparm ] && hdparm -p -S 30 /dev/hda
    	;;
	maximum)
		case "$2" in
		ac)
			# on mains, do not spin down
    			[ -f /sbin/hdparm ] && hdparm -p -S 0 /dev/hda
		;;
		*)
    			# on battery, set disk to spin down after 5 minutes
    			[ -f /sbin/hdparm ] && hdparm -p -S 60 /dev/hda
		;;
		esac
    	;;
	warning)
		do_warn
	;;
	lid-closed)
    	;;
	lid-opened)
    	;;
	sleep)
    	;;
	wakeup)
		[ -f /proc/sys/dev/cdrom/info ] && {
			device=$(cat /proc/sys/dev/cdrom/info | (
				IFS=":"
				while read var val
				do
					[ "$var" = "drive name" ] && {
						echo $val
						break
					}
				done
				))
				[ ! -z "$device" ] && {
					/sbin/wakebay /dev/${device}
				}
		}
	;;
	*)
		$logger -p daemon.error -t pwrctl "$0: invalid arg $1"
	;;
	esac
}

#------------------------------------------------------------------------------
# This is largely a no-op on iBook or Pismo, as we don't know how to handle
# the sleep functions yet. Instead, we shut down on the spot. 
#------------------------------------------------------------------------------

function pwrctl_Core99() 
{
	case "$1" in
	minimum)
	    	# min power, set disk to spin down after 1 minute
    		[ -f /sbin/hdparm ] && hdparm -p -S 12 /dev/hda
	;;
	medium)
	    	# medium power, set disk to spin down after 2.5 minutes
    		[ -f /sbin/hdparm ] && hdparm -p -S 30 /dev/hda
    	;;
	maximum)
		case "$2" in
		ac)
			# on mains, do not spin down
    			[ -f /sbin/hdparm ] && hdparm -p -S 0 /dev/hda
		;;
		*)
    			# on battery, set disk to spin down after 5 minutes
    			[ -f /sbin/hdparm ] && hdparm -p -S 60 /dev/hda
		;;
		esac
    	;;
	warning)
		do_warn
	;;
	lid-closed)
    	;;
	lid-opened)
    	;;
	sleep)
		# We may end up here if someone closed the lid ...
		# SIGPWR can be sent to init anyway with -s option, do the only
		# safe thing for now: shut the hell down on 2.2 kernels, or anything 
		# below a known safe 2.4 version. 
		KVER=`uname -r`
		case "$KVER" in
		2.2.*|2.3.*|2.4.[1-7]|2.4.[1-7]-*)
			$logger -p daemon.error -t pwrctl "$0: insufficient kernel verison - sleep function not implemented, shutting down!"
			echo "Kernel does not support sleep, shutting down!" | /usr/bin/wall
			/sbin/shutdown -h now
			;;
		*)
			;;
		esac
    	;;
	wakeup)
		# maybe force wakeup of media bay devices? 
	;;
	*)
		$logger -p daemon.error -t pwrctl "$0: invalid arg $1"
	;;
	esac
}

# -----------------------------------------------------------------------------
# On the 3400, for minimum power, we put the CPU into nap mode
# (rather than doze mode) when it is idle.  This reduces power
# consumption but means that DMA is no longer cache coherent.
# Therefore we have to disable DMA, including the ethernet.
# We also turn the ethernet off during sleep.
# -----------------------------------------------------------------------------

function pwrctl_3400() 
{
	case "$1" in
	minimum)
 	   	ifconfig eth0 down
    		[ -f /sbin/hdparm ] && hdparm -d0 -S 12 /dev/hda
    		[ "`cat /proc/ide/hdc/model`" != "(none)" ] && [ -f /sbin/hdparm ] && hdparm -d0 /dev/hdc
    		echo 1 >/proc/sys/kernel/powersave-nap
    	;;
	medium)
    		echo 0 >/proc/sys/kernel/powersave-nap
    		[ -f /sbin/hdparm ] && hdparm -d1 -p -S 30 /dev/hda
    		[ "`cat /proc/ide/hdc/model`" != "(none)" ] && [ -f /sbin/hdparm ] && hdparm -d1 /dev/hdc
    		ifconfig eth0 up
    	;;
	maximum)
    		echo 0 >/proc/sys/kernel/powersave-nap
		case "$2" in
		ac)
			# on mains, do not spin down
    			[ -f /sbin/hdparm ] && hdparm -d1 -p -S 0 /dev/hda
		;;
		*)
    			# on battery, set disk to spin down after 5 minutes
    			[ -f /sbin/hdparm ] && hdparm -d1 -p -S 60 /dev/hda
		;;
		esac
    		[ "`cat /proc/ide/hdc/model`" != "(none)" ] && [ -f /sbin/hdparm ] && hdparm -d1 /dev/hdc
    		ifconfig eth0 up
    	;;
	warning)
		do_warn
	;;
	sleep)
    		ifconfig eth0 down
    	;;
	wakeup)
    		ifconfig eth0 up
	;;
	*)
		$logger -p daemon.error -t pwrctl "$0: invalid arg $1"
	;;
	esac
}

# -----------------------------------------------------------------------------
# main
# -----------------------------------------------------------------------------

[ -x $localfun ] && {
	$logger -p daemon.info -t pwrctl "calling $localfun $*"

	$localfun $*

	case $? in
	0)
		$logger -p daemon.debug -t pwrctl "continuing with main"
	;;
	1)
		$logger -p daemon.debug -t pwrctl "skipping main"
		exit 0
	;;
	*)
		$logger -p daemon.error -t pwrctl "error in $localfun"
	;;
	esac
}

case "$PMUVERSION" in
9)	pwrctl_3400   $1 $2 ;;
10|11)	pwrctl_G3     $1 $2 ;;
12)	pwrctl_Core99 $1 $2 ;;
*) 
	$logger -p daemon.error -t pwrctl "no function for PMU $PMUVERSION"
;;
esac >>/var/log/pwrctls 2>&1

exit 0
