Hardware/CPU/AMD10CPU.cs
changeset 197 fb66f749b7ff
parent 196 5e9a8595296c
child 201 958e9fe8afdf
     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  }