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