Hardware/LPC/IT87XX.cs
author moel.mich
Mon, 24 May 2010 15:27:46 +0000
changeset 126 2354fdb91ac4
parent 122 3ef997c53b50
child 130 80065ab20b84
permissions -rw-r--r--
Extended the ITE super I/O voltage reading by adding hidden voltage sensors for unknown channels. Added a few known DFI and Gigabyte mainboard voltage configurations.
moel@16
     1
/*
moel@16
     2
  
moel@16
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@16
     4
moel@16
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@16
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@16
     7
  the License. You may obtain a copy of the License at
moel@16
     8
 
moel@16
     9
  http://www.mozilla.org/MPL/
moel@16
    10
moel@16
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@16
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@16
    13
  for the specific language governing rights and limitations under the License.
moel@16
    14
moel@16
    15
  The Original Code is the Open Hardware Monitor code.
moel@16
    16
moel@16
    17
  The Initial Developer of the Original Code is 
moel@16
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@16
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@16
    20
  the Initial Developer. All Rights Reserved.
moel@16
    21
moel@16
    22
  Contributor(s):
moel@16
    23
moel@16
    24
  Alternatively, the contents of this file may be used under the terms of
moel@16
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@16
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@16
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@16
    28
  of those above. If you wish to allow use of your version of this file only
moel@16
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@16
    30
  use your version of this file under the terms of the MPL, indicate your
moel@16
    31
  decision by deleting the provisions above and replace them with the notice
moel@16
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@16
    33
  the provisions above, a recipient may use your version of this file under
moel@16
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@16
    35
 
moel@16
    36
*/
moel@16
    37
moel@16
    38
using System;
moel@16
    39
using System.Collections.Generic;
moel@16
    40
using System.Drawing;
moel@16
    41
using System.Text;
moel@16
    42
moel@16
    43
namespace OpenHardwareMonitor.Hardware.LPC {
moel@31
    44
  public class IT87XX : LPCHardware, IHardware {
moel@16
    45
        
moel@16
    46
    private bool available = false;
moel@16
    47
    private ushort address;
moel@16
    48
moel@78
    49
    private readonly ushort addressReg;
moel@78
    50
    private readonly ushort dataReg;
moel@78
    51
moel@126
    52
    private List<Sensor> voltages = new List<Sensor>(9);    
moel@126
    53
    private List<Sensor> temperatures = new List<Sensor>(3);    
moel@16
    54
    private Sensor[] fans;
moel@16
    55
   
moel@16
    56
    // Consts
moel@16
    57
    private const byte ITE_VENDOR_ID = 0x90;
moel@16
    58
       
moel@16
    59
    // Environment Controller
moel@16
    60
    private const byte ADDRESS_REGISTER_OFFSET = 0x05;
moel@16
    61
    private const byte DATA_REGISTER_OFFSET = 0x06;
moel@16
    62
moel@16
    63
    // Environment Controller Registers    
moel@16
    64
    private const byte CONFIGURATION_REGISTER = 0x00;
moel@16
    65
    private const byte TEMPERATURE_BASE_REG = 0x29;
moel@16
    66
    private const byte VENDOR_ID_REGISTER = 0x58;
moel@16
    67
    private const byte FAN_TACHOMETER_16_BIT_ENABLE_REGISTER = 0x0c;
moel@16
    68
    private byte[] FAN_TACHOMETER_REG = 
moel@16
    69
      new byte[] { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
moel@16
    70
    private byte[] FAN_TACHOMETER_EXT_REG =
moel@16
    71
      new byte[] { 0x18, 0x19, 0x1a, 0x81, 0x83 };
moel@78
    72
    private const byte VOLTAGE_BASE_REG = 0x20;
moel@78
    73
moel@78
    74
    private byte ReadByte(byte register, out bool valid) {
moel@78
    75
      WinRing0.WriteIoPortByte(addressReg, register);
moel@78
    76
      byte value = WinRing0.ReadIoPortByte(dataReg);
moel@78
    77
      valid = register == WinRing0.ReadIoPortByte(addressReg);
moel@78
    78
      return value;
moel@78
    79
    }
moel@16
    80
moel@126
    81
    public IT87XX(Chip chip, ushort address, Mainboard.Manufacturer 
moel@126
    82
      mainboardManufacturer, Mainboard.Model mainboardModel) : base (chip) {
moel@16
    83
      
moel@16
    84
      this.address = address;
moel@78
    85
      this.addressReg = (ushort)(address + ADDRESS_REGISTER_OFFSET);
moel@78
    86
      this.dataReg = (ushort)(address + DATA_REGISTER_OFFSET);
moel@16
    87
      
moel@16
    88
      // Check vendor id
moel@78
    89
      bool valid;
moel@78
    90
      byte vendorId = ReadByte(VENDOR_ID_REGISTER, out valid);       
moel@78
    91
      if (!valid || vendorId != ITE_VENDOR_ID)
moel@16
    92
        return;
moel@16
    93
moel@16
    94
      // Bit 0x10 of the configuration register should always be 1
moel@78
    95
      if ((ReadByte(CONFIGURATION_REGISTER, out valid) & 0x10) == 0)
moel@78
    96
        return;
moel@78
    97
      if (!valid)
moel@16
    98
        return;
moel@16
    99
moel@126
   100
      string[] temperatureLabels;
moel@126
   101
      List<Voltage> voltageConfigs = new List<Voltage>();
moel@126
   102
      switch (mainboardManufacturer) {
moel@126
   103
        case Mainboard.Manufacturer.DFI:
moel@126
   104
          switch (mainboardModel) {
moel@126
   105
            case Mainboard.Model.LP_BI_P45_T2RS_Elite:
moel@126
   106
              voltageConfigs.Add(new Voltage("CPU VCore", 0));
moel@126
   107
              voltageConfigs.Add(new Voltage("FSB VTT", 1));
moel@126
   108
              voltageConfigs.Add(new Voltage("+3.3V", 2));
moel@126
   109
              voltageConfigs.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
moel@126
   110
              voltageConfigs.Add(new Voltage("+12V", 4, 30, 10, 0));
moel@126
   111
              voltageConfigs.Add(new Voltage("NB Core", 5));
moel@126
   112
              voltageConfigs.Add(new Voltage("VDIMM", 6));
moel@126
   113
              voltageConfigs.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0));
moel@126
   114
              voltageConfigs.Add(new Voltage("VBat", 8));
moel@126
   115
              temperatureLabels = new string[] {
moel@126
   116
                "CPU", "System", "Chipset" };
moel@126
   117
              break;
moel@126
   118
            case Mainboard.Model.LP_DK_P55_T3eH9:
moel@126
   119
              voltageConfigs.Add(new Voltage("CPU VCore", 0));
moel@126
   120
              voltageConfigs.Add(new Voltage("VTT", 1));
moel@126
   121
              voltageConfigs.Add(new Voltage("+3.3V", 2));
moel@126
   122
              voltageConfigs.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
moel@126
   123
              voltageConfigs.Add(new Voltage("+12V", 4, 30, 10, 0));
moel@126
   124
              voltageConfigs.Add(new Voltage("CPU PLL", 5));
moel@126
   125
              voltageConfigs.Add(new Voltage("DRAM", 6));
moel@126
   126
              voltageConfigs.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0));
moel@126
   127
              voltageConfigs.Add(new Voltage("VBat", 8));
moel@126
   128
              temperatureLabels = new string[] {
moel@126
   129
                "Chipset", "CPU PWM", "CPU" };
moel@126
   130
              break;
moel@126
   131
            default:
moel@126
   132
              voltageConfigs.Add(new Voltage("CPU VCore", 0));
moel@126
   133
              voltageConfigs.Add(new Voltage("VTT", 1, true));
moel@126
   134
              voltageConfigs.Add(new Voltage("+3.3V", 2, true));
moel@126
   135
              voltageConfigs.Add(new Voltage("+5V", 3, 6.8f, 10, 0, true));
moel@126
   136
              voltageConfigs.Add(new Voltage("+12V", 4, 30, 10, 0, true));
moel@126
   137
              voltageConfigs.Add(new Voltage("Voltage #6", 5, true));
moel@126
   138
              voltageConfigs.Add(new Voltage("DRAM", 6, true));
moel@126
   139
              voltageConfigs.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0, true));
moel@126
   140
              voltageConfigs.Add(new Voltage("VBat", 8));
moel@126
   141
              temperatureLabels = new string[] {
moel@126
   142
                "Temperature #1", "Temperature #2", "Temperature #3" };
moel@126
   143
              break;
moel@126
   144
          }
moel@126
   145
          break;
moel@126
   146
moel@126
   147
        case Mainboard.Manufacturer.Gigabyte:
moel@126
   148
          switch (mainboardModel) {            
moel@126
   149
            case Mainboard.Model.EP45_DS3R:
moel@126
   150
            case Mainboard.Model.P35_DS3:
moel@126
   151
              voltageConfigs.Add(new Voltage("CPU VCore", 0));
moel@126
   152
              voltageConfigs.Add(new Voltage("DRAM", 1));
moel@126
   153
              voltageConfigs.Add(new Voltage("+3.3V", 2));
moel@126
   154
              voltageConfigs.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
moel@126
   155
              voltageConfigs.Add(new Voltage("+12V", 7, 27, 9.1f, 0));
moel@126
   156
              voltageConfigs.Add(new Voltage("VBat", 8));    
moel@126
   157
              break;
moel@126
   158
            case Mainboard.Model.GA_MA785GMT_UD2H:
moel@126
   159
              voltageConfigs.Add(new Voltage("CPU VCore", 0));
moel@126
   160
              voltageConfigs.Add(new Voltage("DRAM", 1));
moel@126
   161
              voltageConfigs.Add(new Voltage("+3.3V", 2));
moel@126
   162
              voltageConfigs.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
moel@126
   163
              voltageConfigs.Add(new Voltage("+12V", 4, 27, 9.1f, 0));
moel@126
   164
              voltageConfigs.Add(new Voltage("VBat", 8));   
moel@126
   165
              break;
moel@126
   166
            default:
moel@126
   167
              voltageConfigs.Add(new Voltage("CPU VCore", 0));
moel@126
   168
              voltageConfigs.Add(new Voltage("DRAM", 1, true));
moel@126
   169
              voltageConfigs.Add(new Voltage("+3.3V", 2, true));              
moel@126
   170
              voltageConfigs.Add(new Voltage("+5V", 3, 6.8f, 10, 0, true));
moel@126
   171
              voltageConfigs.Add(new Voltage("Voltage #5", 4, true));
moel@126
   172
              voltageConfigs.Add(new Voltage("Voltage #6", 5, true));
moel@126
   173
              voltageConfigs.Add(new Voltage("Voltage #7", 6, true));
moel@126
   174
              voltageConfigs.Add(new Voltage("+12V", 7, 27, 9.1f, 0, true));
moel@126
   175
              voltageConfigs.Add(new Voltage("VBat", 8));              
moel@126
   176
              break;
moel@126
   177
          }
moel@126
   178
          temperatureLabels = new string[] { "System", "CPU" };
moel@126
   179
          break; 
moel@126
   180
moel@126
   181
        default:
moel@126
   182
          voltageConfigs.Add(new Voltage("CPU VCore", 0));
moel@126
   183
          voltageConfigs.Add(new Voltage("Voltage #2", 1, true));
moel@126
   184
          voltageConfigs.Add(new Voltage("Voltage #3", 2, true));
moel@126
   185
          voltageConfigs.Add(new Voltage("Voltage #4", 3, true));
moel@126
   186
          voltageConfigs.Add(new Voltage("Voltage #5", 4, true));
moel@126
   187
          voltageConfigs.Add(new Voltage("Voltage #6", 5, true));
moel@126
   188
          voltageConfigs.Add(new Voltage("Voltage #7", 6, true));
moel@126
   189
          voltageConfigs.Add(new Voltage("Voltage #8", 7, true));
moel@126
   190
          voltageConfigs.Add(new Voltage("VBat", 8));
moel@126
   191
          temperatureLabels = new string[] {
moel@126
   192
            "Temperature #1", "Temperature #2", "Temperature #3" };
moel@126
   193
          break;
moel@126
   194
      }
moel@126
   195
moel@126
   196
      string formula = "Voltage = value + (value - Vf) * Ri / Rf.";
moel@126
   197
      foreach (Voltage voltage in voltageConfigs)
moel@126
   198
        voltages.Add(new Sensor(voltage.Name, voltage.Index, voltage.Hidden, 
moel@126
   199
          null, SensorType.Voltage, this, new ParameterDescription[] {
moel@126
   200
          new ParameterDescription("Ri [kΩ]", "Input resistance.\n" + 
moel@126
   201
            formula, voltage.Ri),
moel@126
   202
          new ParameterDescription("Rf [kΩ]", "Reference resistance.\n" + 
moel@126
   203
            formula, voltage.Rf),
moel@126
   204
          new ParameterDescription("Vf [V]", "Reference voltage.\n" + 
moel@126
   205
            formula, voltage.Vf)
moel@126
   206
          }));  
moel@126
   207
moel@126
   208
      for (int i = 0; i < temperatureLabels.Length; i++)
moel@126
   209
        if (temperatureLabels[i] != null) {
moel@126
   210
          temperatures.Add(new Sensor(temperatureLabels[i], i, null,
moel@126
   211
            SensorType.Temperature, this, new ParameterDescription[] {
moel@122
   212
            new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
moel@126
   213
          }));
moel@126
   214
        }
moel@16
   215
moel@16
   216
      fans = new Sensor[5];
moel@16
   217
      for (int i = 0; i < fans.Length; i++)
moel@126
   218
        fans[i] = new Sensor("Fan #" + (i + 1), i, SensorType.Fan, this);           
moel@16
   219
moel@16
   220
      available = true;
moel@16
   221
    }
moel@16
   222
moel@16
   223
    public bool IsAvailable {
moel@16
   224
      get { return available; } 
moel@16
   225
    }
moel@16
   226
moel@110
   227
    public override string GetReport() {
moel@16
   228
      StringBuilder r = new StringBuilder();
moel@16
   229
moel@31
   230
      r.AppendLine("LPC " + this.GetType().Name);
moel@16
   231
      r.AppendLine();
moel@16
   232
      r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
moel@16
   233
      r.Append("Chip Name: "); r.AppendLine(name);
moel@16
   234
      r.Append("Base Address: 0x"); r.AppendLine(address.ToString("X4"));
moel@16
   235
      r.AppendLine();
moel@16
   236
      r.AppendLine("Environment Controller Registers");
moel@16
   237
      r.AppendLine();
moel@16
   238
moel@16
   239
      r.AppendLine("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
moel@16
   240
      r.AppendLine();
moel@16
   241
      for (int i = 0; i <= 0xA; i++) {
moel@16
   242
        r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append("  ");
moel@16
   243
        for (int j = 0; j <= 0xF; j++) {
moel@16
   244
          r.Append(" ");
moel@78
   245
          bool valid;
moel@78
   246
          byte value = ReadByte((byte)((i << 4) | j), out valid);
moel@78
   247
          if (valid)
moel@78
   248
            r.Append(value.ToString("X2"));
moel@78
   249
          else
moel@78
   250
            r.Append("??");
moel@16
   251
        }
moel@16
   252
        r.AppendLine();
moel@16
   253
      }
moel@16
   254
      r.AppendLine();
moel@16
   255
moel@16
   256
      return r.ToString();
moel@16
   257
    }
moel@16
   258
moel@110
   259
    public override void Update() {
moel@16
   260
moel@16
   261
      foreach (Sensor sensor in voltages) {
moel@78
   262
        bool valid;
moel@126
   263
        float value = 0.001f * ((int)ReadByte(
moel@126
   264
          (byte)(VOLTAGE_BASE_REG + sensor.Index), out valid) << 4);
moel@78
   265
        if (!valid)
moel@78
   266
          continue;
moel@78
   267
moel@126
   268
        sensor.Value = value + (value - sensor.Parameters[2].Value) *
moel@126
   269
          sensor.Parameters[0].Value / sensor.Parameters[1].Value;
moel@126
   270
        if (value > 0)
moel@84
   271
          ActivateSensor(sensor);        
moel@16
   272
      }
moel@16
   273
moel@16
   274
      foreach (Sensor sensor in temperatures) {
moel@78
   275
        bool valid;
moel@78
   276
        sbyte value = (sbyte)ReadByte(
moel@78
   277
          (byte)(TEMPERATURE_BASE_REG + sensor.Index), out valid);
moel@78
   278
        if (!valid)
moel@78
   279
          continue;
moel@78
   280
moel@63
   281
        sensor.Value = value + sensor.Parameters[0].Value;
moel@16
   282
        if (value < sbyte.MaxValue && value > 0)
moel@84
   283
          ActivateSensor(sensor);        
moel@16
   284
      }
moel@16
   285
moel@16
   286
      foreach (Sensor sensor in fans) {
moel@78
   287
        bool valid;
moel@78
   288
        int value = ReadByte(FAN_TACHOMETER_REG[sensor.Index], out valid);
moel@78
   289
        if (!valid) 
moel@78
   290
          continue;
moel@78
   291
        value |= ReadByte(FAN_TACHOMETER_EXT_REG[sensor.Index], out valid) << 8;
moel@78
   292
        if (!valid)
moel@78
   293
          continue;
moel@16
   294
moel@36
   295
        if (value > 0x3f) {
moel@16
   296
          sensor.Value = (value < 0xffff) ? 1.35e6f / ((value) * 2) : 0;
moel@34
   297
          if (sensor.Value > 0)
moel@34
   298
            ActivateSensor(sensor);
moel@16
   299
        } else {
moel@84
   300
          sensor.Value = null;
moel@16
   301
        }
moel@16
   302
      }      
moel@126
   303
    }
moel@126
   304
moel@126
   305
    private class Voltage {
moel@126
   306
      public readonly string Name;
moel@126
   307
      public readonly int Index;
moel@126
   308
      public readonly float Ri;
moel@126
   309
      public readonly float Rf;
moel@126
   310
      public readonly float Vf;
moel@126
   311
      public readonly bool Hidden;
moel@126
   312
moel@126
   313
      public Voltage(string name, int index) :
moel@126
   314
        this(name, index, 0, 1, 0, false) { }
moel@126
   315
moel@126
   316
      public Voltage(string name, int index, bool hidden) :
moel@126
   317
        this(name, index, 0, 1, 0, hidden) { }
moel@126
   318
moel@126
   319
      public Voltage(string name, int index, float ri, float rf, float vf) :
moel@126
   320
        this(name, index, ri, rf, vf, false) { }
moel@126
   321
moel@126
   322
      public Voltage(string name, int index, float ri, float rf, float vf, 
moel@126
   323
        bool hidden) 
moel@126
   324
      {
moel@126
   325
        this.Name = name;
moel@126
   326
        this.Index = index;
moel@126
   327
        this.Ri = ri;
moel@126
   328
        this.Rf = rf;
moel@126
   329
        this.Vf = vf;
moel@126
   330
        this.Hidden = hidden;
moel@126
   331
      }
moel@126
   332
    }
moel@16
   333
  }
moel@16
   334
}