Hardware/CPU/AMD0FCPU.cs
author moel.mich
Sat, 02 Oct 2010 18:15:46 +0000
changeset 206 1fa8eddc24a7
parent 197 fb66f749b7ff
child 236 763675f19ff4
permissions -rw-r--r--
Replaced HttpUtility.UrlEncode with Uri.EscapeDataString and deleted the reference to the System.Web assembly. The System.Web assembly seems to be missing on some .NET 4.0 installations (and the overhead of using it is a bit large, just for the UrlEncode method).
moel@14
     1
/*
moel@14
     2
  
moel@14
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@14
     4
moel@14
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@14
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@14
     7
  the License. You may obtain a copy of the License at
moel@14
     8
 
moel@14
     9
  http://www.mozilla.org/MPL/
moel@14
    10
moel@14
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@14
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@14
    13
  for the specific language governing rights and limitations under the License.
moel@14
    14
moel@14
    15
  The Original Code is the Open Hardware Monitor code.
moel@14
    16
moel@14
    17
  The Initial Developer of the Original Code is 
moel@14
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@14
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@14
    20
  the Initial Developer. All Rights Reserved.
moel@14
    21
moel@14
    22
  Contributor(s):
moel@14
    23
moel@14
    24
  Alternatively, the contents of this file may be used under the terms of
moel@14
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@14
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@14
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@14
    28
  of those above. If you wish to allow use of your version of this file only
moel@14
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@14
    30
  use your version of this file under the terms of the MPL, indicate your
moel@14
    31
  decision by deleting the provisions above and replace them with the notice
moel@14
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@14
    33
  the provisions above, a recipient may use your version of this file under
moel@14
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@14
    35
 
moel@14
    36
*/
moel@14
    37
paulwerelds@192
    38
using System;
moel@196
    39
using System.Globalization;
moel@196
    40
using System.Text;
paulwerelds@192
    41
using System.Threading;
paulwerelds@192
    42
moel@191
    43
namespace OpenHardwareMonitor.Hardware.CPU {
moel@196
    44
  internal sealed class AMD0FCPU : AMDCPU {
moel@196
    45
    
moel@195
    46
    private readonly Sensor[] coreTemperatures;
moel@195
    47
    private readonly Sensor[] coreClocks;
moel@195
    48
    private readonly Sensor busClock;
moel@14
    49
paulwerelds@192
    50
    private const uint FIDVID_STATUS = 0xC0010042;
moel@196
    51
moel@196
    52
    private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
moel@196
    53
    private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1103;
moel@14
    54
    private const uint THERMTRIP_STATUS_REGISTER = 0xE4;
moel@50
    55
    private const byte THERM_SENSE_CORE_SEL_CPU0 = 0x4;
moel@14
    56
    private const byte THERM_SENSE_CORE_SEL_CPU1 = 0x0;
moel@14
    57
moel@196
    58
    private readonly uint miscellaneousControlAddress;
moel@196
    59
moel@191
    60
    public AMD0FCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
moel@191
    61
      : base(processorIndex, cpuid, settings) 
moel@191
    62
    {
moel@77
    63
      float offset = -49.0f;
moel@63
    64
moel@63
    65
      // AM2+ 65nm +21 offset
moel@90
    66
      uint model = cpuid[0][0].Model;
moel@63
    67
      if (model >= 0x69 && model != 0xc1 && model != 0x6c && model != 0x7c) 
moel@63
    68
        offset += 21;
moel@63
    69
moel@90
    70
      // check if processor supports a digital thermal sensor 
moel@90
    71
      if (cpuid[0][0].ExtData.GetLength(0) > 7 && 
moel@90
    72
        (cpuid[0][0].ExtData[7, 3] & 1) != 0) 
moel@90
    73
      {
moel@90
    74
        coreTemperatures = new Sensor[coreCount];
moel@90
    75
        for (int i = 0; i < coreCount; i++) {
moel@90
    76
          coreTemperatures[i] =
moel@134
    77
            new Sensor("Core #" + (i + 1), i, SensorType.Temperature,
moel@195
    78
              this, new [] { new ParameterDescription("Offset [°C]", 
moel@90
    79
                  "Temperature offset of the thermal sensor.\n" + 
moel@90
    80
                  "Temperature = Value + Offset.", offset)
moel@165
    81
          }, settings);
moel@90
    82
        }
moel@90
    83
      } else {
moel@90
    84
        coreTemperatures = new Sensor[0];
moel@26
    85
      }
moel@24
    86
moel@196
    87
      miscellaneousControlAddress = GetPciAddress(
moel@196
    88
        MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
moel@14
    89
paulwerelds@192
    90
      busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
paulwerelds@192
    91
      coreClocks = new Sensor[coreCount];
paulwerelds@192
    92
      for (int i = 0; i < coreClocks.Length; i++) {
paulwerelds@193
    93
        coreClocks[i] = new Sensor(CoreString(i), i + 1, SensorType.Clock,
paulwerelds@193
    94
          this, settings);
moel@201
    95
        if (HasTimeStampCounter)
paulwerelds@192
    96
          ActivateSensor(coreClocks[i]);
paulwerelds@192
    97
      }
paulwerelds@192
    98
moel@14
    99
      Update();                   
moel@14
   100
    }
moel@14
   101
moel@191
   102
    protected override uint[] GetMSRs() {
moel@195
   103
      return new [] { FIDVID_STATUS };
moel@14
   104
    }
moel@14
   105
moel@196
   106
    public override string GetReport() {
moel@196
   107
      StringBuilder r = new StringBuilder();
moel@196
   108
      r.Append(base.GetReport());
moel@196
   109
moel@197
   110
      r.Append("Miscellaneous Control Address: 0x");
moel@196
   111
      r.AppendLine((miscellaneousControlAddress).ToString("X", 
moel@196
   112
        CultureInfo.InvariantCulture));
moel@196
   113
      r.AppendLine();
moel@196
   114
moel@196
   115
      return r.ToString();
moel@196
   116
    }
moel@196
   117
moel@110
   118
    public override void Update() {
moel@191
   119
      base.Update();
moel@191
   120
moel@196
   121
      if (miscellaneousControlAddress != WinRing0.InvalidPciAddress) {
moel@42
   122
        for (uint i = 0; i < coreTemperatures.Length; i++) {
moel@42
   123
          if (WinRing0.WritePciConfigDwordEx(
moel@196
   124
            miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
moel@42
   125
            i > 0 ? THERM_SENSE_CORE_SEL_CPU1 : THERM_SENSE_CORE_SEL_CPU0)) {
moel@42
   126
            uint value;
moel@42
   127
            if (WinRing0.ReadPciConfigDwordEx(
moel@196
   128
              miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, 
moel@196
   129
              out value)) 
moel@196
   130
            {
moel@63
   131
              coreTemperatures[i].Value = ((value >> 16) & 0xFF) + 
moel@63
   132
                coreTemperatures[i].Parameters[0].Value;
moel@42
   133
              ActivateSensor(coreTemperatures[i]);
moel@42
   134
            } else {
moel@42
   135
              DeactivateSensor(coreTemperatures[i]);
moel@42
   136
            }
moel@24
   137
          }
moel@14
   138
        }
moel@24
   139
      }
paulwerelds@192
   140
moel@201
   141
      if (HasTimeStampCounter) {
paulwerelds@192
   142
        double newBusClock = 0;
paulwerelds@192
   143
paulwerelds@192
   144
        for (int i = 0; i < coreClocks.Length; i++) {
paulwerelds@192
   145
          Thread.Sleep(1);
paulwerelds@192
   146
paulwerelds@192
   147
          uint eax, edx;
paulwerelds@193
   148
          if (WinRing0.RdmsrTx(FIDVID_STATUS, out eax, out edx,
paulwerelds@193
   149
            (UIntPtr)(1L << cpuid[i][0].Thread))) {
paulwerelds@192
   150
            // CurrFID can be found in eax bits 0-5, MaxFID in 16-21
paulwerelds@192
   151
            // 8-13 hold StartFID, we don't use that here.
paulwerelds@192
   152
            double curMP = 0.5 * ((eax & 0x3F) + 8);
paulwerelds@192
   153
            double maxMP = 0.5 * ((eax >> 16 & 0x3F) + 8);
moel@201
   154
            coreClocks[i].Value = 
moel@201
   155
              (float)(curMP * TimeStampCounterFrequency / maxMP);
moel@201
   156
            newBusClock = (float)(TimeStampCounterFrequency / maxMP);
paulwerelds@194
   157
          } else {
paulwerelds@194
   158
            // Fail-safe value - if the code above fails, we'll use this instead
moel@201
   159
            coreClocks[i].Value = (float)TimeStampCounterFrequency;
paulwerelds@192
   160
          }
paulwerelds@192
   161
        }
paulwerelds@192
   162
paulwerelds@192
   163
        if (newBusClock > 0) {
paulwerelds@192
   164
          this.busClock.Value = (float)newBusClock;
paulwerelds@192
   165
          ActivateSensor(this.busClock);
paulwerelds@192
   166
        }
paulwerelds@192
   167
      }
moel@191
   168
    }  
moel@191
   169
 
moel@14
   170
  }
moel@14
   171
}