# HG changeset patch
# User moel.mich
# Date 1350829443 0
# Node ID ba6abd47a80c429801664684e8eb911f2bbf9b4b
# Parent  ed5d5fc482ed3df665d736df42036053488a6ee3
Added support for fan control on ITE 87XX chips and a mainboard specific configuration for the Gigabyte GA 970A UD3 (both based on a patch from Eric Hokanson).

diff -r ed5d5fc482ed -r ba6abd47a80c Hardware/LPC/IT87XX.cs
--- a/Hardware/LPC/IT87XX.cs	Mon Oct 01 17:10:09 2012 +0000
+++ b/Hardware/LPC/IT87XX.cs	Sun Oct 21 14:24:03 2012 +0000
@@ -10,6 +10,7 @@
 
 using System.Globalization;
 using System.Text;
+using System;
 
 namespace OpenHardwareMonitor.Hardware.LPC {
   internal class IT87XX : ISuperIO {
@@ -45,10 +46,14 @@
     private const byte VENDOR_ID_REGISTER = 0x58;
     private const byte FAN_TACHOMETER_DIVISOR_REGISTER = 0x0B;
     private readonly byte[] FAN_TACHOMETER_REG = 
-      new byte[] { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
+      { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
     private readonly byte[] FAN_TACHOMETER_EXT_REG =
-      new byte[] { 0x18, 0x19, 0x1a, 0x81, 0x83 };
+      { 0x18, 0x19, 0x1a, 0x81, 0x83 };
     private const byte VOLTAGE_BASE_REG = 0x20;
+    private readonly byte[] FAN_PWM_CTRL_REG = { 0x15, 0x16, 0x17 };
+
+    private bool[] restoreDefaultFanPwmControlRequired = new bool[3];       
+    private byte[] initialFanPwmControl = new byte[3];
 
     private byte ReadByte(byte register, out bool valid) {
       Ring0.WriteIoPort(addressReg, register);
@@ -77,7 +82,40 @@
       Ring0.WriteIoPort((ushort)(gpioAddress + index), value);
     } 
 
-    public void SetControl(int index, byte? value) { }   
+    private void SaveDefaultFanPwmControl(int index) {
+      bool valid;
+      if (!restoreDefaultFanPwmControlRequired[index]) {
+        initialFanPwmControl[index] = 
+          ReadByte(FAN_PWM_CTRL_REG[index], out valid);
+        restoreDefaultFanPwmControlRequired[index] = true;
+      }
+    }
+
+    private void RestoreDefaultFanPwmControl(int index) {
+      if (restoreDefaultFanPwmControlRequired[index]) {
+        WriteByte(FAN_PWM_CTRL_REG[index], initialFanPwmControl[index]);
+        restoreDefaultFanPwmControlRequired[index] = false;
+      }
+    }
+
+    public void SetControl(int index, byte? value) {
+      if (index < 0 || index >= controls.Length)
+        throw new ArgumentOutOfRangeException("index");
+
+      if (!Ring0.WaitIsaBusMutex(10))
+        return;
+
+      if (value.HasValue) {
+        SaveDefaultFanPwmControl(index);
+
+        // set output value
+        WriteByte(FAN_PWM_CTRL_REG[index], (byte)(value.Value >> 1));  
+      } else {
+        RestoreDefaultFanPwmControl(index);
+      }
+
+      Ring0.ReleaseIsaBusMutex();
+    } 
 
     public IT87XX(Chip chip, ushort address, ushort gpioAddress, byte version) {
 
@@ -103,6 +141,7 @@
       voltages = new float?[9];
       temperatures = new float?[3];
       fans = new float?[chip == Chip.IT8705F ? 3 : 5];
+      controls = new float?[3];
 
       // IT8721F, IT8728F and IT8772E use a 12mV resultion ADC, all others 16mV
       if (chip == Chip.IT8721F || chip == Chip.IT8728F || chip == Chip.IT8771E 
@@ -270,6 +309,21 @@
         }
       }
 
+      for (int i = 0; i < controls.Length; i++) {
+        bool valid;
+        byte value = ReadByte(FAN_PWM_CTRL_REG[i], out valid);
+        if (!valid)
+          continue;
+
+        if ((value & 0x80) > 0) {
+          // automatic operation (value can't be read)
+          controls[i] = null;  
+        } else {
+          // software operation
+          controls[i] = (float)Math.Round((value & 0x7F) * 100.0f / 0x7F);
+        }
+      }
+
       Ring0.ReleaseIsaBusMutex();
     }
   } 
diff -r ed5d5fc482ed -r ba6abd47a80c Hardware/Mainboard/Identification.cs
--- a/Hardware/Mainboard/Identification.cs	Mon Oct 01 17:10:09 2012 +0000
+++ b/Hardware/Mainboard/Identification.cs	Sun Oct 21 14:24:03 2012 +0000
@@ -132,6 +132,8 @@
           return Model.G41MT_S2;
         case "G41MT-S2P":
           return Model.G41MT_S2P;
+        case "GA-970A-UD3":
+          return Model.GA_970A_UD3;
         case "GA-MA770T-UD3":
           return Model.GA_MA770T_UD3;
         case "GA-MA770T-UD3P":
diff -r ed5d5fc482ed -r ba6abd47a80c Hardware/Mainboard/Model.cs
--- a/Hardware/Mainboard/Model.cs	Mon Oct 01 17:10:09 2012 +0000
+++ b/Hardware/Mainboard/Model.cs	Sun Oct 21 14:24:03 2012 +0000
@@ -51,6 +51,7 @@
     G41M_Combo,
     G41MT_S2,
     G41MT_S2P,
+    GA_970A_UD3,
     GA_MA770T_UD3,
     GA_MA770T_UD3P,
     GA_MA785GM_US2H,
diff -r ed5d5fc482ed -r ba6abd47a80c Hardware/Mainboard/SuperIOHardware.cs
--- a/Hardware/Mainboard/SuperIOHardware.cs	Mon Oct 01 17:10:09 2012 +0000
+++ b/Hardware/Mainboard/SuperIOHardware.cs	Sun Oct 21 14:24:03 2012 +0000
@@ -352,6 +352,23 @@
                   f.Add(new Fan("CPU Fan", 0));
                   f.Add(new Fan("System Fan", 1));
                   break;
+                case Model.GA_970A_UD3: // IT8720F
+                  v.Add(new Voltage("CPU VCore", 0));
+                  v.Add(new Voltage("DRAM", 1));
+                  v.Add(new Voltage("+3.3V", 2));
+                  v.Add(new Voltage("+5V", 3, 6.8f, 10));
+                  v.Add(new Voltage("+12V", 4, 24.3f, 8.2f));
+                  v.Add(new Voltage("VBat", 8));
+                  t.Add(new Temperature("System", 0));
+                  t.Add(new Temperature("CPU", 1));
+                  f.Add(new Fan("CPU Fan", 0));
+                  f.Add(new Fan("System Fan #1", 1));
+                  f.Add(new Fan("System Fan #2", 2));
+                  f.Add(new Fan("Power Fan", 4));
+                  c.Add(new Ctrl("PWM 1", 0));
+                  c.Add(new Ctrl("PWM 2", 1));
+                  c.Add(new Ctrl("PWM 3", 2));
+                  break;
                 case Model.GA_MA770T_UD3: // IT8720F
                 case Model.GA_MA770T_UD3P: // IT8720F                
                 case Model.GA_MA790X_UD3P: // IT8720F
diff -r ed5d5fc482ed -r ba6abd47a80c Properties/AssemblyVersion.cs
--- a/Properties/AssemblyVersion.cs	Mon Oct 01 17:10:09 2012 +0000
+++ b/Properties/AssemblyVersion.cs	Sun Oct 21 14:24:03 2012 +0000
@@ -10,5 +10,5 @@
 
 using System.Reflection;
 
-[assembly: AssemblyVersion("0.5.1.4")]
-[assembly: AssemblyInformationalVersion("0.5.1.4 Alpha")]
\ No newline at end of file
+[assembly: AssemblyVersion("0.5.1.5")]
+[assembly: AssemblyInformationalVersion("0.5.1.5 Alpha")]
\ No newline at end of file