Hardware/CPU/AMD0FCPU.cs
author moel.mich
Thu, 11 Nov 2010 21:22:24 +0000
changeset 241 52007c404f32
parent 236 763675f19ff4
child 272 037a2d66082f
permissions -rw-r--r--
Fixed a problem, where the MainForm location and size was lost when the application is started minimized and exited without ever showing the form. This caused MainForm_Load to be never called (location and size was not loaded), but the default size and location were still saved. The new implementation only saves the location and size when one of the two is changed.
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@236
   121
      if (miscellaneousControlAddress != Ring0.InvalidPciAddress) {
moel@42
   122
        for (uint i = 0; i < coreTemperatures.Length; i++) {
moel@236
   123
          if (Ring0.WritePciConfig(
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@236
   127
            if (Ring0.ReadPciConfig(
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;
moel@236
   148
          if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx,
moel@238
   149
            1UL << 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
}