1.1 --- a/Hardware/CPU/AMD10CPU.cs Wed Sep 22 19:12:12 2010 +0000
1.2 +++ b/Hardware/CPU/AMD10CPU.cs Wed Sep 22 20:44:34 2010 +0000
1.3 @@ -38,16 +38,22 @@
1.4 using System;
1.5 using System.Globalization;
1.6 using System.Text;
1.7 +using System.Threading;
1.8
1.9 namespace OpenHardwareMonitor.Hardware.CPU {
1.10
1.11 internal sealed class AMD10CPU : AMDCPU {
1.12
1.13 private readonly Sensor coreTemperature;
1.14 + private readonly Sensor[] coreClocks;
1.15 + private readonly Sensor busClock;
1.16 +
1.17 + private const uint COFVID_STATUS = 0xC0010071;
1.18 + private const uint P_STATE_0 = 0xC0010064;
1.19
1.20 private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
1.21 private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1203;
1.22 - private const byte REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
1.23 + private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
1.24
1.25 private readonly uint miscellaneousControlAddress;
1.26
1.27 @@ -65,18 +71,27 @@
1.28 miscellaneousControlAddress = GetPciAddress(
1.29 MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
1.30
1.31 + busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
1.32 + coreClocks = new Sensor[coreCount];
1.33 + for (int i = 0; i < coreClocks.Length; i++) {
1.34 + coreClocks[i] = new Sensor(CoreString(i), i + 1, SensorType.Clock,
1.35 + this, settings);
1.36 + if (hasTSC)
1.37 + ActivateSensor(coreClocks[i]);
1.38 + }
1.39 +
1.40 Update();
1.41 }
1.42
1.43 protected override uint[] GetMSRs() {
1.44 - return new uint[] { };
1.45 + return new uint[] { P_STATE_0, COFVID_STATUS };
1.46 }
1.47
1.48 public override string GetReport() {
1.49 StringBuilder r = new StringBuilder();
1.50 r.Append(base.GetReport());
1.51
1.52 - r.Append("Miscellaneous Control Address: ");
1.53 + r.Append("Miscellaneous Control Address: 0x");
1.54 r.AppendLine((miscellaneousControlAddress).ToString("X",
1.55 CultureInfo.InvariantCulture));
1.56 r.AppendLine();
1.57 @@ -84,6 +99,10 @@
1.58 return r.ToString();
1.59 }
1.60
1.61 + private double MultiplierFromIDs(uint divisorID, uint frequencyID) {
1.62 + return 0.5 * (frequencyID + 0x10) / (1 << (int)divisorID);
1.63 + }
1.64 +
1.65 public override void Update() {
1.66 base.Update();
1.67
1.68 @@ -98,6 +117,44 @@
1.69 DeactivateSensor(coreTemperature);
1.70 }
1.71 }
1.72 - }
1.73 +
1.74 + if (hasTSC) {
1.75 + double newBusClock = 0;
1.76 +
1.77 + for (int i = 0; i < coreClocks.Length; i++) {
1.78 + Thread.Sleep(1);
1.79 +
1.80 + uint curEax, curEdx;
1.81 + uint maxEax, maxEdx;
1.82 + if (WinRing0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx,
1.83 + (UIntPtr)(1L << cpuid[i][0].Thread)) &&
1.84 + WinRing0.RdmsrTx(P_STATE_0, out maxEax, out maxEdx,
1.85 + (UIntPtr)(1L << cpuid[i][0].Thread)))
1.86 + {
1.87 + // 8:6 CpuDid: current core divisor ID
1.88 + // 5:0 CpuFid: current core frequency ID
1.89 + uint curCpuDid = (curEax >> 6) & 7;
1.90 + uint curCpuFid = curEax & 0x1F;
1.91 + double multiplier = MultiplierFromIDs(curCpuDid, curCpuFid);
1.92 +
1.93 + // we assume that the max multiplier (used for the TSC)
1.94 + // can be found in the P_STATE_0 MSR
1.95 + uint maxCpuDid = (maxEax >> 6) & 7;
1.96 + uint maxCpuFid = maxEax & 0x1F;
1.97 + double maxMultiplier = MultiplierFromIDs(maxCpuDid, maxCpuFid);
1.98 +
1.99 + coreClocks[i].Value = (float)(multiplier * MaxClock / maxMultiplier);
1.100 + newBusClock = (float)(MaxClock / maxMultiplier);
1.101 + } else {
1.102 + coreClocks[i].Value = (float)MaxClock;
1.103 + }
1.104 + }
1.105 +
1.106 + if (newBusClock > 0) {
1.107 + this.busClock.Value = (float)newBusClock;
1.108 + ActivateSensor(this.busClock);
1.109 + }
1.110 + }
1.111 + }
1.112 }
1.113 }