Hardware/LPC/IT87XX.cs
author moel.mich
Tue, 25 May 2010 18:57:28 +0000
changeset 127 76aaf45a01c7
parent 122 3ef997c53b50
child 130 80065ab20b84
permissions -rw-r--r--
Added a workaround for the "You must keep the stream open for the lifetime of the Image." problem of the Image.FromStream method. This also reduced the overall memory usage (private working set).
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
}