Hardware/CPU/AMD0FCPU.cs
author sl
Sun, 03 Feb 2013 18:01:50 +0100
changeset 391 ca4c0e7ae75d
parent 272 037a2d66082f
permissions -rw-r--r--
Converted project to VisualStudio 2012.
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
moel@14
     1
/*
moel@344
     2
 
moel@344
     3
  This Source Code Form is subject to the terms of the Mozilla Public
moel@344
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
moel@344
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
moel@344
     6
 
moel@344
     7
  Copyright (C) 2009-2010 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344
     8
  Copyright (C) 2010 Paul Werelds <paul@werelds.net>
moel@14
     9
moel@14
    10
*/
moel@14
    11
paulwerelds@192
    12
using System;
moel@196
    13
using System.Globalization;
moel@196
    14
using System.Text;
paulwerelds@192
    15
using System.Threading;
paulwerelds@192
    16
moel@191
    17
namespace OpenHardwareMonitor.Hardware.CPU {
moel@196
    18
  internal sealed class AMD0FCPU : AMDCPU {
moel@196
    19
    
moel@195
    20
    private readonly Sensor[] coreTemperatures;
moel@195
    21
    private readonly Sensor[] coreClocks;
moel@195
    22
    private readonly Sensor busClock;
moel@14
    23
paulwerelds@192
    24
    private const uint FIDVID_STATUS = 0xC0010042;
moel@196
    25
moel@196
    26
    private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
moel@196
    27
    private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1103;
moel@14
    28
    private const uint THERMTRIP_STATUS_REGISTER = 0xE4;
moel@272
    29
    
moel@272
    30
    private readonly byte thermSenseCoreSelCPU0;
moel@272
    31
    private readonly byte thermSenseCoreSelCPU1;
moel@196
    32
    private readonly uint miscellaneousControlAddress;
moel@196
    33
moel@191
    34
    public AMD0FCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
moel@191
    35
      : base(processorIndex, cpuid, settings) 
moel@191
    36
    {
moel@77
    37
      float offset = -49.0f;
moel@63
    38
moel@63
    39
      // AM2+ 65nm +21 offset
moel@90
    40
      uint model = cpuid[0][0].Model;
moel@63
    41
      if (model >= 0x69 && model != 0xc1 && model != 0x6c && model != 0x7c) 
moel@63
    42
        offset += 21;
moel@63
    43
moel@272
    44
      if (model < 40) {
moel@272
    45
        // AMD Athlon 64 Processors
moel@272
    46
        thermSenseCoreSelCPU0 = 0x0;
moel@272
    47
        thermSenseCoreSelCPU1 = 0x4;
moel@272
    48
      } else {
moel@272
    49
        // AMD NPT Family 0Fh Revision F, G have the core selection swapped
moel@272
    50
        thermSenseCoreSelCPU0 = 0x4;
moel@272
    51
        thermSenseCoreSelCPU1 = 0x0;
moel@272
    52
      }
moel@272
    53
moel@90
    54
      // check if processor supports a digital thermal sensor 
moel@90
    55
      if (cpuid[0][0].ExtData.GetLength(0) > 7 && 
moel@90
    56
        (cpuid[0][0].ExtData[7, 3] & 1) != 0) 
moel@90
    57
      {
moel@90
    58
        coreTemperatures = new Sensor[coreCount];
moel@90
    59
        for (int i = 0; i < coreCount; i++) {
moel@90
    60
          coreTemperatures[i] =
moel@134
    61
            new Sensor("Core #" + (i + 1), i, SensorType.Temperature,
moel@195
    62
              this, new [] { new ParameterDescription("Offset [°C]", 
moel@90
    63
                  "Temperature offset of the thermal sensor.\n" + 
moel@90
    64
                  "Temperature = Value + Offset.", offset)
moel@165
    65
          }, settings);
moel@90
    66
        }
moel@90
    67
      } else {
moel@90
    68
        coreTemperatures = new Sensor[0];
moel@26
    69
      }
moel@24
    70
moel@196
    71
      miscellaneousControlAddress = GetPciAddress(
moel@196
    72
        MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
moel@14
    73
paulwerelds@192
    74
      busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
paulwerelds@192
    75
      coreClocks = new Sensor[coreCount];
paulwerelds@192
    76
      for (int i = 0; i < coreClocks.Length; i++) {
paulwerelds@193
    77
        coreClocks[i] = new Sensor(CoreString(i), i + 1, SensorType.Clock,
paulwerelds@193
    78
          this, settings);
moel@201
    79
        if (HasTimeStampCounter)
paulwerelds@192
    80
          ActivateSensor(coreClocks[i]);
paulwerelds@192
    81
      }
paulwerelds@192
    82
moel@14
    83
      Update();                   
moel@14
    84
    }
moel@14
    85
moel@191
    86
    protected override uint[] GetMSRs() {
moel@195
    87
      return new [] { FIDVID_STATUS };
moel@14
    88
    }
moel@14
    89
moel@196
    90
    public override string GetReport() {
moel@196
    91
      StringBuilder r = new StringBuilder();
moel@196
    92
      r.Append(base.GetReport());
moel@196
    93
moel@197
    94
      r.Append("Miscellaneous Control Address: 0x");
moel@196
    95
      r.AppendLine((miscellaneousControlAddress).ToString("X", 
moel@196
    96
        CultureInfo.InvariantCulture));
moel@196
    97
      r.AppendLine();
moel@196
    98
moel@196
    99
      return r.ToString();
moel@196
   100
    }
moel@196
   101
moel@110
   102
    public override void Update() {
moel@191
   103
      base.Update();
moel@191
   104
moel@236
   105
      if (miscellaneousControlAddress != Ring0.InvalidPciAddress) {
moel@42
   106
        for (uint i = 0; i < coreTemperatures.Length; i++) {
moel@236
   107
          if (Ring0.WritePciConfig(
moel@196
   108
            miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
moel@272
   109
            i > 0 ? thermSenseCoreSelCPU1 : thermSenseCoreSelCPU0)) {
moel@42
   110
            uint value;
moel@236
   111
            if (Ring0.ReadPciConfig(
moel@196
   112
              miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, 
moel@196
   113
              out value)) 
moel@196
   114
            {
moel@63
   115
              coreTemperatures[i].Value = ((value >> 16) & 0xFF) + 
moel@63
   116
                coreTemperatures[i].Parameters[0].Value;
moel@42
   117
              ActivateSensor(coreTemperatures[i]);
moel@42
   118
            } else {
moel@42
   119
              DeactivateSensor(coreTemperatures[i]);
moel@42
   120
            }
moel@24
   121
          }
moel@14
   122
        }
moel@24
   123
      }
paulwerelds@192
   124
moel@201
   125
      if (HasTimeStampCounter) {
paulwerelds@192
   126
        double newBusClock = 0;
paulwerelds@192
   127
paulwerelds@192
   128
        for (int i = 0; i < coreClocks.Length; i++) {
paulwerelds@192
   129
          Thread.Sleep(1);
paulwerelds@192
   130
paulwerelds@192
   131
          uint eax, edx;
moel@236
   132
          if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx,
moel@238
   133
            1UL << cpuid[i][0].Thread)) {
paulwerelds@192
   134
            // CurrFID can be found in eax bits 0-5, MaxFID in 16-21
paulwerelds@192
   135
            // 8-13 hold StartFID, we don't use that here.
paulwerelds@192
   136
            double curMP = 0.5 * ((eax & 0x3F) + 8);
paulwerelds@192
   137
            double maxMP = 0.5 * ((eax >> 16 & 0x3F) + 8);
moel@201
   138
            coreClocks[i].Value = 
moel@201
   139
              (float)(curMP * TimeStampCounterFrequency / maxMP);
moel@201
   140
            newBusClock = (float)(TimeStampCounterFrequency / maxMP);
paulwerelds@194
   141
          } else {
paulwerelds@194
   142
            // Fail-safe value - if the code above fails, we'll use this instead
moel@201
   143
            coreClocks[i].Value = (float)TimeStampCounterFrequency;
paulwerelds@192
   144
          }
paulwerelds@192
   145
        }
paulwerelds@192
   146
paulwerelds@192
   147
        if (newBusClock > 0) {
paulwerelds@192
   148
          this.busClock.Value = (float)newBusClock;
paulwerelds@192
   149
          ActivateSensor(this.busClock);
paulwerelds@192
   150
        }
paulwerelds@192
   151
      }
moel@191
   152
    }  
moel@191
   153
 
moel@14
   154
  }
moel@14
   155
}