# HG changeset patch # User moel.mich # Date 1295559114 0 # Node ID 6dc755f1970e70a5182762203d0aee5d29719047 # Parent 59024371cd504a8f5ae980b65eb943be1e867808 Added a minimal control interface to allow manual fan control and implemented the interface for ATI GPUs. diff -r 59024371cd50 -r 6dc755f1970e GUI/MainForm.cs --- a/GUI/MainForm.cs Wed Dec 08 19:23:13 2010 +0000 +++ b/GUI/MainForm.cs Thu Jan 20 21:31:54 2011 +0000 @@ -461,6 +461,34 @@ }; sensorContextMenu.MenuItems.Add(item); } + if (node.Sensor.Control != null) { + IControl control = node.Sensor.Control; + MenuItem controlItem = new MenuItem("Control"); + MenuItem defaultItem = new MenuItem("Default"); + defaultItem.Checked = control.ControlMode == ControlMode.Default; + controlItem.MenuItems.Add(defaultItem); + defaultItem.Click += delegate(object obj, EventArgs args) { + control.SetDefault(); + }; + MenuItem manualItem = new MenuItem("Manual"); + controlItem.MenuItems.Add(manualItem); + manualItem.Checked = control.ControlMode == ControlMode.Software; + for (int i = 0; i <= 100; i += 5) { + if (i <= control.MaxSoftwareValue && + i >= control.MinSoftwareValue) + { + MenuItem item = new MenuItem(i + " %"); + manualItem.MenuItems.Add(item); + item.Checked = control.ControlMode == ControlMode.Software && + Math.Round(control.SoftwareValue) == i; + int softwareValue = i; + item.Click += delegate(object obj, EventArgs args) { + control.SetSoftware(softwareValue); + }; + } + } + sensorContextMenu.MenuItems.Add(controlItem); + } sensorContextMenu.Show(treeView, new Point(m.X, m.Y)); } diff -r 59024371cd50 -r 6dc755f1970e Hardware/ATI/ADL.cs --- a/Hardware/ATI/ADL.cs Wed Dec 08 19:23:13 2010 +0000 +++ b/Hardware/ATI/ADL.cs Thu Jan 20 21:31:54 2011 +0000 @@ -122,6 +122,7 @@ public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE = 2; public const int ADL_DL_FANCTRL_SUPPORTS_RPM_READ = 4; public const int ADL_DL_FANCTRL_SUPPORTS_RPM_WRITE = 8; + public const int ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED = 1; public const int ATI_VENDOR_ID1 = 1002; public const int ATI_VENDOR_ID2 = 0x1002; @@ -149,6 +150,10 @@ public delegate int ADL_Overdrive5_FanSpeedInfo_GetDelegate( int adapterIndex, int thermalControllerIndex, ref ADLFanSpeedInfo fanSpeedInfo); + public delegate int ADL_Overdrive5_FanSpeedToDefault_SetDelegate( + int adapterIndex, int thermalControllerIndex); + public delegate int ADL_Overdrive5_FanSpeed_SetDelegate(int adapterIndex, + int thermalControllerIndex, ref ADLFanSpeedValue fanSpeedValue); private static ADL_Main_Control_CreateDelegate _ADL_Main_Control_Create; @@ -173,6 +178,10 @@ ADL_Overdrive5_FanSpeed_Get; public static ADL_Overdrive5_FanSpeedInfo_GetDelegate ADL_Overdrive5_FanSpeedInfo_Get; + public static ADL_Overdrive5_FanSpeedToDefault_SetDelegate + ADL_Overdrive5_FanSpeedToDefault_Set; + public static ADL_Overdrive5_FanSpeed_SetDelegate + ADL_Overdrive5_FanSpeed_Set; private static string dllName; @@ -215,6 +224,10 @@ out ADL_Overdrive5_FanSpeed_Get); GetDelegate("ADL_Overdrive5_FanSpeedInfo_Get", out ADL_Overdrive5_FanSpeedInfo_Get); + GetDelegate("ADL_Overdrive5_FanSpeedToDefault_Set", + out ADL_Overdrive5_FanSpeedToDefault_Set); + GetDelegate("ADL_Overdrive5_FanSpeed_Set", + out ADL_Overdrive5_FanSpeed_Set); } static ADL() { diff -r 59024371cd50 -r 6dc755f1970e Hardware/ATI/ATIGPU.cs --- a/Hardware/ATI/ATIGPU.cs Wed Dec 08 19:23:13 2010 +0000 +++ b/Hardware/ATI/ATIGPU.cs Thu Jan 20 21:31:54 2011 +0000 @@ -51,7 +51,10 @@ private readonly Sensor memoryClock; private readonly Sensor coreVoltage; private readonly Sensor coreLoad; - private readonly Sensor fanControl; + private readonly Sensor controlSensor; + private readonly Control fanControl; + + private ADLFanSpeedValue initialFanSpeedValue; public ATIGPU(string name, int adapterIndex, int busNumber, int deviceNumber, ISettings settings) @@ -61,16 +64,61 @@ this.busNumber = busNumber; this.deviceNumber = deviceNumber; + this.initialFanSpeedValue = new ADLFanSpeedValue(); + this.initialFanSpeedValue.SpeedType = + ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; + ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0, + ref this.initialFanSpeedValue); + this.temperature = new Sensor("GPU Core", 0, SensorType.Temperature, this, settings); this.fan = new Sensor("GPU Fan", 0, SensorType.Fan, this, settings); this.coreClock = new Sensor("GPU Core", 0, SensorType.Clock, this, settings); this.memoryClock = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings); this.coreVoltage = new Sensor("GPU Core", 0, SensorType.Voltage, this, settings); this.coreLoad = new Sensor("GPU Core", 0, SensorType.Load, this, settings); - this.fanControl = new Sensor("GPU Fan", 0, SensorType.Control, this, settings); + this.controlSensor = new Sensor("GPU Fan", 0, SensorType.Control, this, settings); + + ADLFanSpeedInfo afsi = new ADLFanSpeedInfo(); + if (ADL.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref afsi) + != ADL.ADL_OK) + { + afsi.MaxPercent = 100; + afsi.MinPercent = 0; + } + + this.fanControl = new Control(controlSensor, settings, afsi.MinPercent, + afsi.MaxPercent); + this.fanControl.ControlModeChanged += ControlModeChanged; + this.fanControl.SoftwareControlValueChanged += + SoftwareControlValueChanged; + ControlModeChanged(fanControl); + this.controlSensor.Control = fanControl; Update(); } + private void SoftwareControlValueChanged(IControl control) { + if (control.ControlMode == ControlMode.Software) { + ADLFanSpeedValue adlf = new ADLFanSpeedValue(); + adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; + adlf.Flags = ADL.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED; + adlf.FanSpeed = (int)control.SoftwareValue; + ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0, ref adlf); + } + } + + private void ControlModeChanged(IControl control) { + if (control.ControlMode == ControlMode.Default) { + ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0, + ref this.initialFanSpeedValue); + } else { + ADLFanSpeedValue adlf = new ADLFanSpeedValue(); + adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; + adlf.Flags = ADL.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED; + adlf.FanSpeed = (int)control.SoftwareValue; + ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0, ref adlf); + } + } + public int BusNumber { get { return busNumber; } } public int DeviceNumber { get { return deviceNumber; } } @@ -116,10 +164,10 @@ adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; if (ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0, ref adlf) == ADL.ADL_OK) { - fanControl.Value = adlf.FanSpeed; - ActivateSensor(fanControl); + controlSensor.Value = adlf.FanSpeed; + ActivateSensor(controlSensor); } else { - fanControl.Value = null; + controlSensor.Value = null; } ADLPMActivity adlp = new ADLPMActivity(); @@ -150,5 +198,14 @@ coreLoad.Value = null; } } + + public void Close() { + this.fanControl.ControlModeChanged -= ControlModeChanged; + this.fanControl.SoftwareControlValueChanged -= + SoftwareControlValueChanged; + + ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0, + ref this.initialFanSpeedValue); + } } } diff -r 59024371cd50 -r 6dc755f1970e Hardware/ATI/ATIGroup.cs --- a/Hardware/ATI/ATIGroup.cs Wed Dec 08 19:23:13 2010 +0000 +++ b/Hardware/ATI/ATIGroup.cs Thu Jan 20 21:31:54 2011 +0000 @@ -144,6 +144,8 @@ public void Close() { try { + foreach (ATIGPU gpu in hardware) + gpu.Close(); ADL.ADL_Main_Control_Destroy(); } catch (Exception) { } } diff -r 59024371cd50 -r 6dc755f1970e Hardware/Control.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/Control.cs Thu Jan 20 21:31:54 2011 +0000 @@ -0,0 +1,143 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Globalization; + +namespace OpenHardwareMonitor.Hardware { + + internal delegate void ControlEventHandler(Control control); + + internal class Control : IControl { + + private readonly Identifier identifier; + private readonly ISettings settings; + private ControlMode mode; + private float softwareValue; + private float minSoftwareValue; + private float maxSoftwareValue; + + public Control(ISensor sensor, ISettings settings, float minSoftwareValue, + float maxSoftwareValue) + { + this.identifier = new Identifier(sensor.Identifier, "control"); + this.settings = settings; + this.minSoftwareValue = minSoftwareValue; + this.maxSoftwareValue = maxSoftwareValue; + + if (!float.TryParse(settings.GetValue( + new Identifier(identifier, "value").ToString(), "0"), + NumberStyles.Float, CultureInfo.InvariantCulture, + out this.softwareValue)) + { + this.softwareValue = 0; + } + int mode; + if (!int.TryParse(settings.GetValue( + new Identifier(identifier, "mode").ToString(), + ((int)ControlMode.Default).ToString(CultureInfo.InvariantCulture)), + NumberStyles.Integer, CultureInfo.InvariantCulture, + out mode)) + { + this.mode = ControlMode.Default; + } else { + this.mode = (ControlMode)mode; + } + } + + public Identifier Identifier { + get { + return identifier; + } + } + + public ControlMode ControlMode { + get { + return mode; + } + private set { + if (mode != value) { + mode = value; + if (ControlModeChanged != null) + ControlModeChanged(this); + this.settings.SetValue(new Identifier(identifier, "mode").ToString(), + ((int)mode).ToString(CultureInfo.InvariantCulture)); + } + } + } + + public float SoftwareValue { + get { + return softwareValue; + } + private set { + if (softwareValue != value) { + softwareValue = value; + if (SoftwareControlValueChanged != null) + SoftwareControlValueChanged(this); + this.settings.SetValue(new Identifier(identifier, + "value").ToString(), + value.ToString(CultureInfo.InvariantCulture)); + } + } + } + + public void SetDefault() { + ControlMode = ControlMode.Default; + } + + public float MinSoftwareValue { + get { + return minSoftwareValue; + } + } + + public float MaxSoftwareValue { + get { + return maxSoftwareValue; + } + } + + public void SetSoftware(float value) { + ControlMode = ControlMode.Software; + SoftwareValue = value; + } + + internal event ControlEventHandler ControlModeChanged; + internal event ControlEventHandler SoftwareControlValueChanged; + } +} diff -r 59024371cd50 -r 6dc755f1970e Hardware/Hardware.cs --- a/Hardware/Hardware.cs Wed Dec 08 19:23:13 2010 +0000 +++ b/Hardware/Hardware.cs Thu Jan 20 21:31:54 2011 +0000 @@ -55,13 +55,13 @@ get { return active.ToArray(); } } - protected void ActivateSensor(Sensor sensor) { + protected void ActivateSensor(ISensor sensor) { if (active.Add(sensor)) if (SensorAdded != null) SensorAdded(sensor); } - protected void DeactivateSensor(Sensor sensor) { + protected void DeactivateSensor(ISensor sensor) { if (active.Remove(sensor)) if (SensorRemoved != null) SensorRemoved(sensor); diff -r 59024371cd50 -r 6dc755f1970e Hardware/IControl.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/IControl.cs Thu Jan 20 21:31:54 2011 +0000 @@ -0,0 +1,61 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +namespace OpenHardwareMonitor.Hardware { + + public enum ControlMode { + Default, + Software + } + + public interface IControl { + + Identifier Identifier { get; } + + ControlMode ControlMode { get; } + + float SoftwareValue { get; } + + void SetDefault(); + + float MinSoftwareValue { get; } + float MaxSoftwareValue { get; } + + void SetSoftware(float value); + + } +} diff -r 59024371cd50 -r 6dc755f1970e Hardware/ISensor.cs --- a/Hardware/ISensor.cs Wed Dec 08 19:23:13 2010 +0000 +++ b/Hardware/ISensor.cs Thu Jan 20 21:31:54 2011 +0000 @@ -87,6 +87,8 @@ void ResetMax(); IEnumerable Values { get; } + + IControl Control { get; } } } diff -r 59024371cd50 -r 6dc755f1970e Hardware/LPC/IT87XX.cs --- a/Hardware/LPC/IT87XX.cs Wed Dec 08 19:23:13 2010 +0000 +++ b/Hardware/LPC/IT87XX.cs Thu Jan 20 21:31:54 2011 +0000 @@ -82,6 +82,12 @@ return value; } + private bool WriteByte(byte register, byte value) { + Ring0.WriteIoPort(addressReg, register); + Ring0.WriteIoPort(dataReg, value); + return register == Ring0.ReadIoPort(addressReg); + } + public byte? ReadGPIO(int index) { if (index >= gpioCount) return null; diff -r 59024371cd50 -r 6dc755f1970e Hardware/Sensor.cs --- a/Hardware/Sensor.cs Wed Dec 08 19:23:13 2010 +0000 +++ b/Hardware/Sensor.cs Thu Jan 20 21:31:54 2011 +0000 @@ -57,6 +57,7 @@ private readonly Queue values = new Queue(MAX_MINUTES * 15); private readonly ISettings settings; + private IControl control; private float sum; private int count; @@ -186,5 +187,14 @@ foreach (IParameter parameter in parameters) parameter.Accept(visitor); } + + public IControl Control { + get { + return control; + } + internal set { + this.control = value; + } + } } } diff -r 59024371cd50 -r 6dc755f1970e OpenHardwareMonitorLib.csproj --- a/OpenHardwareMonitorLib.csproj Wed Dec 08 19:23:13 2010 +0000 +++ b/OpenHardwareMonitorLib.csproj Thu Jan 20 21:31:54 2011 +0000 @@ -59,6 +59,8 @@ + +