Hardware/LPC/W836XX.cs
author moel.mich
Fri, 12 Feb 2010 22:46:31 +0000
changeset 42 47385d4fc990
child 53 ccba498488e8
permissions -rw-r--r--
Tray sensor display default color is black and color can be changed now. Fixed CPU load reading for AMD CPUs and added additional misc device for AMD core temperature reading.
moel@34
     1
/*
moel@34
     2
  
moel@34
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@34
     4
moel@34
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@34
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@34
     7
  the License. You may obtain a copy of the License at
moel@34
     8
 
moel@34
     9
  http://www.mozilla.org/MPL/
moel@34
    10
moel@34
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@34
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@34
    13
  for the specific language governing rights and limitations under the License.
moel@34
    14
moel@34
    15
  The Original Code is the Open Hardware Monitor code.
moel@34
    16
moel@34
    17
  The Initial Developer of the Original Code is 
moel@34
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@34
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@34
    20
  the Initial Developer. All Rights Reserved.
moel@34
    21
moel@34
    22
  Contributor(s):
moel@34
    23
moel@34
    24
  Alternatively, the contents of this file may be used under the terms of
moel@34
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@34
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@34
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@34
    28
  of those above. If you wish to allow use of your version of this file only
moel@34
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@34
    30
  use your version of this file under the terms of the MPL, indicate your
moel@34
    31
  decision by deleting the provisions above and replace them with the notice
moel@34
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@34
    33
  the provisions above, a recipient may use your version of this file under
moel@34
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@34
    35
 
moel@34
    36
*/
moel@34
    37
moel@34
    38
using System;
moel@34
    39
using System.Collections.Generic;
moel@34
    40
using System.Drawing;
moel@34
    41
using System.Text;
moel@34
    42
moel@34
    43
namespace OpenHardwareMonitor.Hardware.LPC {
moel@34
    44
  public class W836XX : LPCHardware, IHardware {
moel@34
    45
moel@34
    46
    private ushort address;
moel@34
    47
    private byte revision;
moel@34
    48
moel@34
    49
    private bool available;
moel@34
    50
moel@34
    51
    private Sensor[] temperatures;
moel@34
    52
    private Sensor[] fans;
moel@34
    53
    private Sensor[] voltages;
moel@34
    54
moel@34
    55
    private float[] voltageGains;
moel@34
    56
    private string[] fanNames;
moel@34
    57
moel@34
    58
    // Consts 
moel@34
    59
    private const ushort WINBOND_VENDOR_ID = 0x5CA3;
moel@34
    60
    private const byte HIGH_BYTE = 0x80;
moel@34
    61
moel@34
    62
    // Hardware Monitor
moel@34
    63
    private const byte ADDRESS_REGISTER_OFFSET = 0x05;
moel@34
    64
    private const byte DATA_REGISTER_OFFSET = 0x06;
moel@34
    65
moel@34
    66
    // Hardware Monitor Registers
moel@34
    67
    private const byte VOLTAGE_BASE_REG = 0x20;
moel@34
    68
    private const byte BANK_SELECT_REGISTER = 0x04E;
moel@34
    69
    private const byte VENDOR_ID_REGISTER = 0x4F;
moel@34
    70
    private const byte TEMPERATURE_BASE_REG = 0x50;
moel@34
    71
    private const byte TEMPERATURE_SYS_REG = 0x27;    
moel@34
    72
moel@34
    73
    private byte[] FAN_TACHO_REG = new byte[] { 0x28, 0x29, 0x2A, 0x3F, 0x53 };
moel@34
    74
    private byte[] FAN_TACHO_BANK = new byte[] { 0, 0, 0, 0, 5 };       
moel@34
    75
    private byte[] FAN_BIT_REG = new byte[] { 0x47, 0x4B, 0x4C, 0x59, 0x5D };
moel@34
    76
    private byte[] FAN_DIV_BIT0 = new byte[] { 36, 38, 30, 8, 10 };
moel@34
    77
    private byte[] FAN_DIV_BIT1 = new byte[] { 37, 39, 31, 9, 11 };
moel@34
    78
    private byte[] FAN_DIV_BIT2 = new byte[] { 5, 6, 7, 23, 15 };
moel@34
    79
moel@34
    80
    private byte ReadByte(byte bank, byte register) {
moel@34
    81
      WinRing0.WriteIoPortByte(
moel@34
    82
         (ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER);
moel@34
    83
      WinRing0.WriteIoPortByte(
moel@34
    84
         (ushort)(address + DATA_REGISTER_OFFSET), bank);
moel@34
    85
      WinRing0.WriteIoPortByte(
moel@34
    86
         (ushort)(address + ADDRESS_REGISTER_OFFSET), register);
moel@34
    87
      return WinRing0.ReadIoPortByte(
moel@34
    88
        (ushort)(address + DATA_REGISTER_OFFSET));
moel@34
    89
    } 
moel@34
    90
moel@34
    91
    public W836XX(Chip chip, byte revision, ushort address) 
moel@34
    92
      : base(chip)
moel@34
    93
    {
moel@34
    94
      this.address = address;
moel@34
    95
      this.revision = revision;
moel@34
    96
moel@34
    97
      available = IsWinbondVendor();
moel@34
    98
moel@34
    99
      temperatures = new Sensor[3];
moel@34
   100
      temperatures[0] = new Sensor("CPU", 0, SensorType.Temperature, this);
moel@34
   101
      temperatures[1] = new Sensor("Auxiliary", 1, SensorType.Temperature, this);
moel@34
   102
      temperatures[2] = new Sensor("System", 2, SensorType.Temperature, this);
moel@34
   103
moel@34
   104
      switch (chip) {
moel@34
   105
        case Chip.W83627DHG:
moel@34
   106
        case Chip.W83627DHGP:
moel@34
   107
        case Chip.W83627EHF:
moel@34
   108
        case Chip.W83667HG:
moel@34
   109
        case Chip.W83667HGB: 
moel@34
   110
          fanNames = new string[] { "System", "CPU", "Auxiliary", 
moel@34
   111
            "CPU #2", "Auxiliary #2" };
moel@34
   112
          voltageGains = new float[] { 1, 1, 1, 2, 1, 1, 1, 2 };
moel@34
   113
          voltages = new Sensor[3];
moel@34
   114
          voltages[0] = new Sensor("CPU VCore", 0, SensorType.Voltage, this);
moel@34
   115
          voltages[1] = new Sensor("+3.3V", 3, SensorType.Voltage, this);
moel@34
   116
          voltages[2] = new Sensor("Battery", 7, SensorType.Voltage, this);
moel@34
   117
          break;
moel@34
   118
        case Chip.W83627HF: 
moel@34
   119
          fanNames = new string[] { "Fan #1", "Fan #2", "Fan #3" };
moel@34
   120
          voltageGains = new float[] { 2, 1, 2, 1, 1, 1, 1, 2 };
moel@34
   121
          voltages = new Sensor[3];
moel@34
   122
          voltages[0] = new Sensor("CPU VCore", 0, SensorType.Voltage, this);
moel@34
   123
          voltages[1] = new Sensor("+3.3V", 2, SensorType.Voltage, this);
moel@34
   124
          voltages[2] = new Sensor("Battery", 7, SensorType.Voltage, this);
moel@34
   125
          break;
moel@34
   126
        default: fanNames = new string[0];
moel@34
   127
          break;
moel@34
   128
      }
moel@34
   129
      
moel@34
   130
      fans = new Sensor[fanNames.Length];
moel@34
   131
      for (int i = 0; i < fanNames.Length; i++)
moel@34
   132
        fans[i] = new Sensor(fanNames[i], i, SensorType.Fan, this);
moel@34
   133
    }
moel@34
   134
moel@34
   135
    public bool IsAvailable {
moel@34
   136
      get { return available; }
moel@34
   137
    }        
moel@34
   138
moel@34
   139
    private bool IsWinbondVendor() {
moel@34
   140
      ushort vendorId =
moel@34
   141
        (ushort)((ReadByte(HIGH_BYTE, VENDOR_ID_REGISTER) << 8) |
moel@34
   142
           ReadByte(0, VENDOR_ID_REGISTER));
moel@34
   143
      return vendorId == WINBOND_VENDOR_ID;
moel@34
   144
    }
moel@34
   145
moel@34
   146
    public void Update() {
moel@34
   147
      foreach (Sensor sensor in voltages) {
moel@34
   148
        if (sensor.Index < 7) {
moel@34
   149
          int value = ReadByte(0, (byte)(VOLTAGE_BASE_REG + sensor.Index));
moel@34
   150
          sensor.Value = 0.008f * voltageGains[sensor.Index] * value;
moel@34
   151
          if (sensor.Value > 0)
moel@34
   152
            ActivateSensor(sensor);
moel@34
   153
          else
moel@34
   154
            DeactivateSensor(sensor);
moel@34
   155
        } else {
moel@34
   156
          // Battery voltage
moel@34
   157
          bool valid = (ReadByte(0, 0x5D) & 0x01) > 0;
moel@34
   158
          if (valid) {
moel@34
   159
            sensor.Value = 
moel@34
   160
              0.008f * voltageGains[sensor.Index] * ReadByte(5, 0x51);
moel@34
   161
            ActivateSensor(sensor);
moel@34
   162
          } else
moel@34
   163
            DeactivateSensor(sensor);
moel@34
   164
        }
moel@34
   165
      }
moel@34
   166
moel@34
   167
      foreach (Sensor sensor in temperatures) {
moel@34
   168
        int value;
moel@34
   169
        if (sensor.Index < 2) {
moel@34
   170
          value = (sbyte)ReadByte((byte)(sensor.Index + 1), TEMPERATURE_BASE_REG);
moel@34
   171
          value = (value << 1) | ReadByte((byte)(sensor.Index + 1),
moel@34
   172
            (byte)(TEMPERATURE_BASE_REG + 1)) >> 7;
moel@34
   173
        } else {
moel@34
   174
          value = (sbyte)ReadByte(0, TEMPERATURE_SYS_REG) << 1;
moel@34
   175
        }
moel@34
   176
        sensor.Value = value / 2.0f;
moel@34
   177
        if (value < 0xFE)
moel@34
   178
          ActivateSensor(sensor);
moel@34
   179
        else
moel@34
   180
          DeactivateSensor(sensor);
moel@34
   181
      }
moel@34
   182
moel@34
   183
      long bits = 0;
moel@34
   184
      for (int i = 0; i < FAN_BIT_REG.Length; i++)
moel@34
   185
        bits = (bits << 8) | ReadByte(0, FAN_BIT_REG[i]);
moel@34
   186
      foreach (Sensor sensor in fans) {
moel@34
   187
        int count = ReadByte(FAN_TACHO_BANK[sensor.Index], 
moel@34
   188
          FAN_TACHO_REG[sensor.Index]);
moel@34
   189
        int divisorBits = (int)(
moel@34
   190
          (((bits >> FAN_DIV_BIT2[sensor.Index]) & 1) << 2) |
moel@34
   191
          (((bits >> FAN_DIV_BIT1[sensor.Index]) & 1) << 1) |
moel@34
   192
           ((bits >> FAN_DIV_BIT0[sensor.Index]) & 1));
moel@34
   193
        int divisor = 1 << divisorBits;
moel@34
   194
        float value = (count < 0xff) ? 1.35e6f / (count * divisor) : 0;
moel@34
   195
        sensor.Value = value;
moel@34
   196
        if (value > 0)
moel@34
   197
          ActivateSensor(sensor);        
moel@34
   198
      }     
moel@34
   199
    }
moel@34
   200
moel@34
   201
    public string GetReport() {
moel@34
   202
      StringBuilder r = new StringBuilder();
moel@34
   203
moel@34
   204
      r.AppendLine("LPC " + this.GetType().Name);
moel@34
   205
      r.AppendLine();
moel@34
   206
      r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
moel@34
   207
      r.Append("Chip revision: 0x"); r.AppendLine(revision.ToString("X"));
moel@34
   208
      r.Append("Base Adress: 0x"); r.AppendLine(address.ToString("X4"));
moel@34
   209
      r.AppendLine();
moel@34
   210
      r.AppendLine("Hardware Monitor Registers");
moel@34
   211
      r.AppendLine();
moel@34
   212
      r.AppendLine("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
moel@34
   213
      r.AppendLine();
moel@34
   214
      for (int i = 0; i < 0x7; i++) {
moel@34
   215
        r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append("  ");
moel@34
   216
        for (int j = 0; j <= 0xF; j++) {
moel@34
   217
          r.Append(" ");
moel@34
   218
          r.Append(ReadByte(0, (byte)((i << 4) | j)).ToString("X2"));
moel@34
   219
        }
moel@34
   220
        r.AppendLine();
moel@34
   221
      }
moel@34
   222
      for (int k = 1; k <= 5; k++) {
moel@34
   223
        r.AppendLine("Bank " + k);
moel@34
   224
        for (int i = 0x5; i < 0x6; i++) {
moel@34
   225
          r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append("  ");
moel@34
   226
          for (int j = 0; j <= 0xF; j++) {
moel@34
   227
            r.Append(" ");
moel@34
   228
            r.Append(ReadByte((byte)(k),
moel@34
   229
              (byte)((i << 4) | j)).ToString("X2"));
moel@34
   230
          }
moel@34
   231
          r.AppendLine();
moel@34
   232
        }
moel@34
   233
      }
moel@34
   234
      r.AppendLine();
moel@34
   235
moel@34
   236
      return r.ToString();
moel@34
   237
    }
moel@34
   238
  }
moel@34
   239
}