A first (experimental) implementation for the AMD 10h family CPU clock speeds.
1.1 --- a/Hardware/CPU/AMD0FCPU.cs Wed Sep 22 19:12:12 2010 +0000
1.2 +++ b/Hardware/CPU/AMD0FCPU.cs Wed Sep 22 20:44:34 2010 +0000
1.3 @@ -107,7 +107,7 @@
1.4 StringBuilder r = new StringBuilder();
1.5 r.Append(base.GetReport());
1.6
1.7 - r.Append("Miscellaneous Control Address: ");
1.8 + r.Append("Miscellaneous Control Address: 0x");
1.9 r.AppendLine((miscellaneousControlAddress).ToString("X",
1.10 CultureInfo.InvariantCulture));
1.11 r.AppendLine();
2.1 --- a/Hardware/CPU/AMD10CPU.cs Wed Sep 22 19:12:12 2010 +0000
2.2 +++ b/Hardware/CPU/AMD10CPU.cs Wed Sep 22 20:44:34 2010 +0000
2.3 @@ -38,16 +38,22 @@
2.4 using System;
2.5 using System.Globalization;
2.6 using System.Text;
2.7 +using System.Threading;
2.8
2.9 namespace OpenHardwareMonitor.Hardware.CPU {
2.10
2.11 internal sealed class AMD10CPU : AMDCPU {
2.12
2.13 private readonly Sensor coreTemperature;
2.14 + private readonly Sensor[] coreClocks;
2.15 + private readonly Sensor busClock;
2.16 +
2.17 + private const uint COFVID_STATUS = 0xC0010071;
2.18 + private const uint P_STATE_0 = 0xC0010064;
2.19
2.20 private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
2.21 private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1203;
2.22 - private const byte REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
2.23 + private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
2.24
2.25 private readonly uint miscellaneousControlAddress;
2.26
2.27 @@ -65,18 +71,27 @@
2.28 miscellaneousControlAddress = GetPciAddress(
2.29 MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
2.30
2.31 + busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
2.32 + coreClocks = new Sensor[coreCount];
2.33 + for (int i = 0; i < coreClocks.Length; i++) {
2.34 + coreClocks[i] = new Sensor(CoreString(i), i + 1, SensorType.Clock,
2.35 + this, settings);
2.36 + if (hasTSC)
2.37 + ActivateSensor(coreClocks[i]);
2.38 + }
2.39 +
2.40 Update();
2.41 }
2.42
2.43 protected override uint[] GetMSRs() {
2.44 - return new uint[] { };
2.45 + return new uint[] { P_STATE_0, COFVID_STATUS };
2.46 }
2.47
2.48 public override string GetReport() {
2.49 StringBuilder r = new StringBuilder();
2.50 r.Append(base.GetReport());
2.51
2.52 - r.Append("Miscellaneous Control Address: ");
2.53 + r.Append("Miscellaneous Control Address: 0x");
2.54 r.AppendLine((miscellaneousControlAddress).ToString("X",
2.55 CultureInfo.InvariantCulture));
2.56 r.AppendLine();
2.57 @@ -84,6 +99,10 @@
2.58 return r.ToString();
2.59 }
2.60
2.61 + private double MultiplierFromIDs(uint divisorID, uint frequencyID) {
2.62 + return 0.5 * (frequencyID + 0x10) / (1 << (int)divisorID);
2.63 + }
2.64 +
2.65 public override void Update() {
2.66 base.Update();
2.67
2.68 @@ -98,6 +117,44 @@
2.69 DeactivateSensor(coreTemperature);
2.70 }
2.71 }
2.72 - }
2.73 +
2.74 + if (hasTSC) {
2.75 + double newBusClock = 0;
2.76 +
2.77 + for (int i = 0; i < coreClocks.Length; i++) {
2.78 + Thread.Sleep(1);
2.79 +
2.80 + uint curEax, curEdx;
2.81 + uint maxEax, maxEdx;
2.82 + if (WinRing0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx,
2.83 + (UIntPtr)(1L << cpuid[i][0].Thread)) &&
2.84 + WinRing0.RdmsrTx(P_STATE_0, out maxEax, out maxEdx,
2.85 + (UIntPtr)(1L << cpuid[i][0].Thread)))
2.86 + {
2.87 + // 8:6 CpuDid: current core divisor ID
2.88 + // 5:0 CpuFid: current core frequency ID
2.89 + uint curCpuDid = (curEax >> 6) & 7;
2.90 + uint curCpuFid = curEax & 0x1F;
2.91 + double multiplier = MultiplierFromIDs(curCpuDid, curCpuFid);
2.92 +
2.93 + // we assume that the max multiplier (used for the TSC)
2.94 + // can be found in the P_STATE_0 MSR
2.95 + uint maxCpuDid = (maxEax >> 6) & 7;
2.96 + uint maxCpuFid = maxEax & 0x1F;
2.97 + double maxMultiplier = MultiplierFromIDs(maxCpuDid, maxCpuFid);
2.98 +
2.99 + coreClocks[i].Value = (float)(multiplier * MaxClock / maxMultiplier);
2.100 + newBusClock = (float)(MaxClock / maxMultiplier);
2.101 + } else {
2.102 + coreClocks[i].Value = (float)MaxClock;
2.103 + }
2.104 + }
2.105 +
2.106 + if (newBusClock > 0) {
2.107 + this.busClock.Value = (float)newBusClock;
2.108 + ActivateSensor(this.busClock);
2.109 + }
2.110 + }
2.111 + }
2.112 }
2.113 }
3.1 --- a/Hardware/CPU/AMDCPU.cs Wed Sep 22 19:12:12 2010 +0000
3.2 +++ b/Hardware/CPU/AMDCPU.cs Wed Sep 22 20:44:34 2010 +0000
3.3 @@ -48,14 +48,17 @@
3.4 : base(processorIndex, cpuid, settings) { }
3.5
3.6 protected uint GetPciAddress(byte function, ushort deviceId) {
3.7 +
3.8 + // assemble the pci address
3.9 uint address = WinRing0.GetPciAddress(PCI_BUS,
3.10 (byte)(PCI_BASE_DEVICE + processorIndex), function);
3.11
3.12 + // verify that we have the correct bus, device and function
3.13 uint deviceVendor;
3.14 if (!WinRing0.ReadPciConfigDwordEx(
3.15 address, DEVICE_VENDOR_ID_REGISTER, out deviceVendor))
3.16 return WinRing0.InvalidPciAddress;
3.17 -
3.18 +
3.19 if (deviceVendor != (deviceId << 16 | AMD_VENDOR_ID))
3.20 return WinRing0.InvalidPciAddress;
3.21
4.1 --- a/Properties/AssemblyVersion.cs Wed Sep 22 19:12:12 2010 +0000
4.2 +++ b/Properties/AssemblyVersion.cs Wed Sep 22 20:44:34 2010 +0000
4.3 @@ -37,5 +37,5 @@
4.4
4.5 using System.Reflection;
4.6
4.7 -[assembly: AssemblyVersion("0.1.37.14")]
4.8 -[assembly: AssemblyInformationalVersion("0.1.37.14 Alpha")]
4.9 \ No newline at end of file
4.10 +[assembly: AssemblyVersion("0.1.37.16")]
4.11 +[assembly: AssemblyInformationalVersion("0.1.37.16 Alpha")]
4.12 \ No newline at end of file