Hardware/LPC/F718XX.cs
author moel.mich
Sun, 08 May 2011 22:10:13 +0000
changeset 279 6bce967ba1b5
parent 228 458a6c3de579
child 323 3f2d9ebacf38
permissions -rw-r--r--
Fixed the bus and core clock reading on AMD family 10h model Ah CPUs. The new "Core Performance Boost" feature of these CPUs resulted in very low accuracy of the bus speed (and as a consequence also an inaccurate TSC multiplier). This fixed Issue 205.
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@166
    38
using System.Globalization;
moel@16
    39
using System.Text;
moel@16
    40
moel@16
    41
namespace OpenHardwareMonitor.Hardware.LPC {
moel@165
    42
  internal class F718XX : ISuperIO {
moel@16
    43
moel@195
    44
    private readonly ushort address;
moel@195
    45
    private readonly Chip chip;
moel@16
    46
moel@195
    47
    private readonly float?[] voltages;
moel@195
    48
    private readonly float?[] temperatures;
moel@195
    49
    private readonly float?[] fans;
moel@16
    50
moel@16
    51
    // Hardware Monitor
moel@16
    52
    private const byte ADDRESS_REGISTER_OFFSET = 0x05;
moel@16
    53
    private const byte DATA_REGISTER_OFFSET = 0x06;
moel@16
    54
moel@16
    55
    // Hardware Monitor Registers
moel@16
    56
    private const byte VOLTAGE_BASE_REG = 0x20;
moel@68
    57
    private const byte TEMPERATURE_CONFIG_REG = 0x69;
moel@68
    58
    private const byte TEMPERATURE_BASE_REG = 0x70;
moel@195
    59
    private readonly byte[] FAN_TACHOMETER_REG = 
moel@195
    60
      new byte[] { 0xA0, 0xB0, 0xC0, 0xD0 };
moel@16
    61
    
moel@16
    62
    private byte ReadByte(byte register) {
moel@236
    63
      Ring0.WriteIoPort(
moel@16
    64
        (ushort)(address + ADDRESS_REGISTER_OFFSET), register);
moel@236
    65
      return Ring0.ReadIoPort((ushort)(address + DATA_REGISTER_OFFSET));
moel@132
    66
    }
moel@16
    67
moel@228
    68
    public byte? ReadGPIO(int index) {
moel@228
    69
      return null;
moel@228
    70
    }
moel@228
    71
moel@228
    72
    public void WriteGPIO(int index, byte value) { }
moel@228
    73
moel@130
    74
    public F718XX(Chip chip, ushort address) {
moel@16
    75
      this.address = address;
moel@130
    76
      this.chip = chip;
moel@16
    77
moel@130
    78
      voltages = new float?[chip == Chip.F71858 ? 3 : 9];
moel@130
    79
      temperatures = new float?[3];
moel@130
    80
      fans = new float?[chip == Chip.F71882 || chip == Chip.F71858? 4 : 3];
moel@16
    81
    }
moel@16
    82
moel@130
    83
    public Chip Chip { get { return chip; } }
moel@130
    84
    public float?[] Voltages { get { return voltages; } }
moel@130
    85
    public float?[] Temperatures { get { return temperatures; } }
moel@130
    86
    public float?[] Fans { get { return fans; } }
moel@130
    87
moel@130
    88
    public string GetReport() {
moel@16
    89
      StringBuilder r = new StringBuilder();
moel@16
    90
moel@31
    91
      r.AppendLine("LPC " + this.GetType().Name);
moel@16
    92
      r.AppendLine();
moel@166
    93
      r.Append("Base Adress: 0x"); 
moel@166
    94
      r.AppendLine(address.ToString("X4", CultureInfo.InvariantCulture));
moel@16
    95
      r.AppendLine();
moel@162
    96
moel@236
    97
      if (!Ring0.WaitIsaBusMutex(100))
moel@162
    98
        return r.ToString();
moel@162
    99
moel@16
   100
      r.AppendLine("Hardware Monitor Registers");
moel@16
   101
      r.AppendLine();
moel@16
   102
      r.AppendLine("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
moel@16
   103
      r.AppendLine();
moel@16
   104
      for (int i = 0; i <= 0xF; i++) {
moel@166
   105
        r.Append(" "); 
moel@166
   106
        r.Append((i << 4).ToString("X2", CultureInfo.InvariantCulture)); 
moel@166
   107
        r.Append("  ");
moel@16
   108
        for (int j = 0; j <= 0xF; j++) {
moel@16
   109
          r.Append(" ");
moel@166
   110
          r.Append(ReadByte((byte)((i << 4) | j)).ToString("X2", 
moel@166
   111
            CultureInfo.InvariantCulture));
moel@16
   112
        }
moel@16
   113
        r.AppendLine();
moel@16
   114
      }
moel@16
   115
      r.AppendLine();
moel@162
   116
moel@236
   117
      Ring0.ReleaseIsaBusMutex();
moel@162
   118
moel@16
   119
      return r.ToString();
moel@16
   120
    }
moel@16
   121
moel@130
   122
    public void Update() {
moel@236
   123
      if (!Ring0.WaitIsaBusMutex(10))
moel@162
   124
        return;
moel@16
   125
moel@130
   126
      for (int i = 0; i < voltages.Length; i++) {
moel@130
   127
        int value = ReadByte((byte)(VOLTAGE_BASE_REG + i));
moel@132
   128
        voltages[i] = 0.008f * value;
moel@16
   129
      }
moel@68
   130
     
moel@130
   131
      for (int i = 0; i < temperatures.Length; i++) {
moel@68
   132
        switch (chip) {
moel@68
   133
          case Chip.F71858: {
moel@195
   134
              int tableMode = 0x3 & ReadByte(TEMPERATURE_CONFIG_REG);
moel@68
   135
              int high = 
moel@130
   136
                ReadByte((byte)(TEMPERATURE_BASE_REG + 2 * i));
moel@68
   137
              int low =
moel@130
   138
                ReadByte((byte)(TEMPERATURE_BASE_REG + 2 * i + 1));              
moel@68
   139
              if (high != 0xbb && high != 0xcc) {
moel@68
   140
                int bits = 0;
moel@68
   141
                switch (tableMode) {
moel@68
   142
                  case 0: bits = 0; break;
moel@68
   143
                  case 1: bits = 0; break;
moel@68
   144
                  case 2: bits = (high & 0x80) << 8; break;
moel@68
   145
                  case 3: bits = (low & 0x01) << 15; break;
moel@68
   146
                }
moel@68
   147
                bits |= high << 7;
moel@68
   148
                bits |= (low & 0xe0) >> 1;
moel@68
   149
                short value = (short)(bits & 0xfff0);
moel@130
   150
                temperatures[i] = value / 128.0f;
moel@68
   151
              } else {
moel@130
   152
                temperatures[i] = null;
moel@68
   153
              }
moel@68
   154
          } break;
moel@68
   155
          default: {
moel@68
   156
            sbyte value = (sbyte)ReadByte((byte)(
moel@130
   157
              TEMPERATURE_BASE_REG + 2 * (i + 1)));            
moel@68
   158
            if (value < sbyte.MaxValue && value > 0)
moel@130
   159
              temperatures[i] = value;
moel@130
   160
            else
moel@130
   161
              temperatures[i] = null;
moel@68
   162
          } break;
moel@68
   163
        }
moel@16
   164
      }
moel@16
   165
moel@130
   166
      for (int i = 0; i < fans.Length; i++) {
moel@130
   167
        int value = ReadByte(FAN_TACHOMETER_REG[i]) << 8;
moel@130
   168
        value |= ReadByte((byte)(FAN_TACHOMETER_REG[i] + 1));
moel@16
   169
moel@130
   170
        if (value > 0) 
moel@130
   171
          fans[i] = (value < 0x0fff) ? 1.5e6f / value : 0;
moel@130
   172
        else 
moel@130
   173
          fans[i] = null;        
moel@162
   174
      }
moel@162
   175
moel@236
   176
      Ring0.ReleaseIsaBusMutex();
moel@16
   177
    }
moel@16
   178
  }
moel@16
   179
}