#!/bin/bash
# $Id: coolrun, v 1.2, 2011/01/23, gn Exp $
# UUID: c265003c-0f09-44b2-a346-56dc65e607fa
#
# Enable/disable ACPI powersave features on AMD Athlon/Athlon XP/Duron/Sempron
# processors using direct hardware access
#
# Copyright (C) 2006-2011, Grozdan Nikolov
# Thanks to Daniel Nofftz for the setpci powersaving values
#
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

if [ $UID != 0 ]; then
	echo "-> Please login as root!"
	exit 1
fi

export PATH=$PATH:/usr/local/bin:/usr/local/sbin:/sbin:/usr/sbin

if [ ! -x "$(which setpci 2>/dev/null)" ]; then
	echo "-> Utility 'setpci' is missing!"
	exit 1
fi

# Check HW platform
case $(uname -i) in
	i?86) true ;;
	*)
	echo "-> This script supports only the x86 hardware platform!"
	exit 1
	;;
esac

# Check for SMP systems
SMP=$(sed -n -e '/^processor/p' /proc/cpuinfo | wc -l 2>/dev/null)
if [ "$SMP" != 1 ]; then
	echo "-> This script supports only single CPU systems!"
	exit 1
fi

# Check for AMD CPU
case "$(cat /proc/cpuinfo | grep -m1 'vendor_id' | awk '{print $3}' 2>/dev/null)" in
	AuthenticAMD|AMD) true ;;
	*|"")
	echo "-> This script supports only AMD CPUs!"
	exit 1
	;;
esac

# Check for Athlon/Athlon XP/Duron/Sempron CPUs
case "$(cat /proc/cpuinfo | grep -m1 -w 'model name' | awk '{print $3,$4,$5,$6,$7}' 2>/dev/null)" in
	*Athlon*|*athlon*|*Duron*|*duron*|*Sempron*|*sempron*) true ;;
	*|"")
	echo "-> This script supports only AMD Athlon/Athlon XP/Duron/Sempron CPUs!"
	exit 1
	;;
esac

if [ -z "$1" ]; then
	echo "Usage: coolrun [-e|--enable|-d|--disable] chipset"
	echo "       For a list of supported chipsets,"
	echo "       use the '-c' option"
	exit 1
fi
 
# The real thing...
case "$1" in
	-c)
	echo ""
	echo "This script enables/disables the ACPI power saving features"
	echo "of the AMD Athlon/Athlon XP/Duron/Sempron CPUs"
	echo "Depending on your motherboard/hardware componenets,"
	echo "enabling the power saving mode may cause:"
	echo " * Noisy or distorted sound playback"
	echo " * Slowdown in harddisk performance"
	echo " * Random system locks or instability"
	echo " * Sometimes (massive) file system corruption (uncommon)"
	echo "Before using coolrun, you must recognize these potential"
	echo "dangers! Use this script AT YOUR OWN RISK!"
	echo "Neither I, the author of coolrun, nor Daniel Nofftz, the author"
	echo "of the Athlon Powersaving HOWTO and provider of the power"
	echo "saving values, can be held responsible for any damages"
	echo "brought to your system while using this script!"
	echo ""
	echo "Supported chipsets for AMD CPUs"
	echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
	echo "Vendor:   VIA Technologies, Inc."
	echo "Chipsets: KT133 - KT133A - KX133 - KL133 - KLE133 - KM133"
	echo "          KN133 - KT266 - KT266A - KM266 - KT333 - KT333CF"
	echo "          KM333 - KT400A - KM400 - KM400A - KT600 - KT880"
	echo ""
	echo "Vendor:   Silicon Integrated Systems (SiS)"
	echo "Chipsets: SiS730 - SiS730S - SiS733 - SiS735 - SiS740 - SiS741"
	echo "          SiS741GX - SiS745 - SiS746 - SiS746GX - SiS748 - SiS755"
	echo ""
	echo "Vendor:   nVIDIA Corporation"
	echo "Chipsets: nForce - nForce2"
	echo ""
	echo "Vendor:   Advanced Micro Devices (AMD)"
	echo "Chipsets: AMD751 - AMD760 - AMD761"
	echo ""
	exit 0
	;;
	-e|--enable)
	if [ -z "$2" ]; then
		echo "-> No chipset specified!"
		echo "-> For a list of supported chipsets, use 'coolrun -c'"
		exit 1
	fi
	case $(echo "$2" | tr '[:upper:]' '[:lower:]') in
		kt133|kt133a|kx133|kl133|kle133|km133|kn133)
		echo "Note: this will only work on Linux kernels with ACPI support"
		echo "Activating AMD powersaving features on chipset: VIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 52=$(printf %x $((0x$(setpci -H1 -s 0:0.0 52) | 0x80)))
		;;
		kt266|kt266a|km266|kt333|km333)
		echo "Activating AMD powersaving features on chipset: VIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 92=$(printf %x $((0x$(setpci -H1 -s 0:0.0 92) | 0x80)))
		setpci -v -H1 -s 0:0.0 95=$(printf %x $((0x$(setpci -H1 -s 0:0.0 95) | 0x02)))
		;;
		kt333cf|kt400|kt400a|km400|km400a|kt600)
		echo "Activating AMD powersaving features on chipset: VIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 D2=$(printf %x $((0x$(setpci -H1 -s 0:0.0 D2) | 0x80)))
		setpci -v -H1 -s 0:0.0 D5=$(printf %x $((0x$(setpci -H1 -s 0:0.0 D5) | 0x02)))
		;;
		kt880)
		echo "Activating AMD powersaving features on chipset: VIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 82=$(printf %x $((0x$(setpci -H1 -s 0:0.0 82) | 0x80)))
		setpci -v -H1 -s 0:0.0 85=$(printf %x $((0x$(setpci -H1 -s 0:0.0 85) | 0x02)))
		;;
		sis730|sis730s|sis733)
		echo "Activating AMD powersaving features on chipset: SiS $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 6B=$(printf %x $((0x$(setpci -H1 -s 0:0.0 6B) | 0x01)))
		;;
		sis735|sis740|sis745|sis755)
		echo "Activating AMD powersaving features on chipset: SiS $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 6A=$(printf %x $((0x$(setpci -H1 -s 0:0.0 6A) | 0x0001)))
		;;
		sis741|sis741gx|sis746|sis746gx|sis748)
		echo "Activating AMD powersaving features on chipset: SiS $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 6A=$(printf %x $((0x$(setpci -H1 -s 0:0.0 6A) | 0x0003)))
		;;
		nforce)
		echo "Activating AMD powersaving features on chipset: nVIDIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 E7=$(printf %x $((0x$(setpci -H1 -s 0:0.0 E7) | 0x06)))
		;;
		nforce2)
		echo "Activating AMD powersaving features on chipset: nVIDIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 6F=$(printf %x $((0x$(setpci -H1 -s 0:0.0 6F) | 0x10)))
		;;
		amd751|amd760|amd761)
		echo "Activating AMD powersaving features on chipset: AMD $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 0x62=$(printf %x $((0x$(setpci -H1 -s 0:0.0 62) | 0x06)))
		;;
		*)
		echo "-> Unknown chipset: '$2'"
		echo "-> For a list of supported chipsets, use 'coolrun -c'"
		exit 1
		;;
	esac
	;;
	-d|--disable)
	if [ -z "$2" ]; then
		echo "-> No chipset specified!"
		echo "-> For a list of supported chipsets, use 'coolrun -c'"
		exit 1
	fi
	case $(echo "$2" | tr '[:upper:]' '[:lower:]') in
		kt133|kt133a|kx133|kl133|kle133|km133|kn133)
		echo "Note: this will only work on Linux kernels with ACPI support"
		echo "Deactivating AMD powersaving features on chipset: VIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 6B=$(printf %x $((0x$(setpci -H1 -s 0:0.0 6B) & 0x7f)))
		;;
		kt266|kt266a|km266|kt333|km333)
		echo "Deactivating AMD powersaving features on chipset: VIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 92=$(printf %x $((0x$(setpci -H1 -s 0:0.0 92) & 0x7f)))
		setpci -v -H1 -s 0:0.0 95=$(printf %x $((0x$(setpci -H1 -s 0:0.0 95) & 0xfd)))
		;;
		kt333cf|kt400|kt400a|km400|km400a|kt600)
		echo "Deactivating AMD powersaving features on chipset: VIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 D2=$(printf %x $((0x$(setpci -H1 -s 0:0.0 D2) & 0x7f)))
		setpci -v -H1 -s 0:0.0 D5=$(printf %x $((0x$(setpci -H1 -s 0:0.0 D5) & 0xfd)))
		;;
		kt880)
		echo "Deactivating AMD powersaving features on chipset: VIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 82=$(printf %x $((0x$(setpci -H1 -s 0:0.0 82) & 0x7f)))
		setpci -v -H1 -s 0:0.0 85=$(printf %x $((0x$(setpci -H1 -s 0:0.0 85) & 0xfd)))
		;;
		sis730|sis730s|sis733)
		echo "Deactivating AMD powersaving features on chipset: SiS $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 6B=$(printf %x $((0x$(setpci -H1 -s 0:0.0 6B) & 0xfe)))
		;;
		sis735|sis740|sis745|sis755)
		echo "Deactivating AMD powersaving features on chipset: SiS $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 6A=$(printf %x $((0x$(setpci -H1 -s 0:0.0 6A) & 0xfffe)))
		;;
		sis741|sis741gx|sis746|sis746gx|sis748)
		echo "Deactivating AMD powersaving features on chipset: SiS $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 6A=$(printf %x $((0x$(setpci -H1 -s 0:0.0 6A) & 0xfffe)))
		;;
		nforce)
		echo "Deactivating AMD powersaving features on chipset: nVIDIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 E7=$(printf %x $((0x$(setpci -H1 -s 0:0.0 E7) & 0xf9))
		;;
		nforce2)
		echo "Deactivating AMD powersaving features on chipset: nVIDIA $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 6F=$(printf %x $((0x$(setpci -H1 -s 0:0.0 6F) & 0xef)))
		;;
		amd751|amd760|amd761)
		echo "Deactivating AMD powersaving features on chipset: AMD $(echo $2 | tr '[:lower:]' '[:upper:]')"
		setpci -v -H1 -s 0:0.0 0x62=$(printf %x $((0x$(setpci -H1 -s 0:0.0 62) & 0xf9)))
		;;
		*)
		echo "-> Unknown chipset: '$2'"
		echo "-> For a list of supported chipsets, use 'coolrun -c'"
		exit 1
		;;
	esac
	;;
	*)
	echo "-> Unknown option: '$1'"
	exit 1
	;;
esac

exit 0