# HG changeset patch
# User moel.mich
# Date 1266178590 0
# Node ID c150de283ca029a9d08c8a715cdb9ac94e7136b6
# Parent  5b7398d061b74ecae65210e86f08ffce42d6071d
Added core and bus clock support for Intel CPUs (Core 2).

diff -r 5b7398d061b7 -r c150de283ca0 GUI/SensorNotifyIcon.cs
--- a/GUI/SensorNotifyIcon.cs	Sat Feb 13 17:08:36 2010 +0000
+++ b/GUI/SensorNotifyIcon.cs	Sun Feb 14 20:16:30 2010 +0000
@@ -107,9 +107,9 @@
       set { 
         this.color = value;
         this.darkColor = Color.FromArgb(255,
-          Math.Max(this.color.R - 100, 0),
-          Math.Max(this.color.G - 100, 0),
-          Math.Max(this.color.B - 100, 0));
+          this.color.R / 3,
+          this.color.G / 3,
+          this.color.B / 3);
         Brush brush = this.brush;
         this.brush = new SolidBrush(this.color);
         if (brush != null)
diff -r 5b7398d061b7 -r c150de283ca0 Hardware/CPU/CPUGroup.cs
--- a/Hardware/CPU/CPUGroup.cs	Sat Feb 13 17:08:36 2010 +0000
+++ b/Hardware/CPU/CPUGroup.cs	Sun Feb 14 20:16:30 2010 +0000
@@ -131,10 +131,8 @@
 
         switch (cpuVendor) {
           case "GenuineIntel":
-            // check if processor supports a digital thermal sensor
-            if (maxCPUID >= 6 && (cpuidData[6, 0] & 1) != 0) 
-              hardware.Add(new IntelCPU(name, family, model, stepping, 
-                cpuidData, cpuidExtData));
+            hardware.Add(new IntelCPU(name, family, model, stepping, 
+              cpuidData, cpuidExtData));
             break;
           case "AuthenticAMD":                       
             // check if processor supports a digital thermal sensor            
diff -r 5b7398d061b7 -r c150de283ca0 Hardware/CPU/IntelCPU.cs
--- a/Hardware/CPU/IntelCPU.cs	Sat Feb 13 17:08:36 2010 +0000
+++ b/Hardware/CPU/IntelCPU.cs	Sun Feb 14 20:16:30 2010 +0000
@@ -51,6 +51,8 @@
     private Sensor[] coreTemperatures;
     private Sensor totalLoad;
     private Sensor[] coreLoads;
+    private Sensor[] coreClocks;
+    private Sensor busClock;
 
     private float tjMax = 0;
     private uint logicalProcessors;
@@ -58,9 +60,13 @@
     private uint coreCount;
 
     private CPULoad cpuLoad;
+
+    private ulong lastCount;    
+    private long lastTime;
     
     private const uint IA32_THERM_STATUS_MSR = 0x019C;
     private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
+    private const uint IA32_PERF_STATUS = 0x0198;
 
     public IntelCPU(string name, uint family, uint model, uint stepping, 
       uint[,] cpuidData, uint[,] cpuidExtData) {
@@ -89,58 +95,64 @@
 
       coreCount = logicalProcessors / logicalProcessorsPerCore;
 
-      switch (family) {
-        case 0x06: {
-          switch (model) {
-            case 0x0F: // Intel Core 65nm
-              switch (stepping) {
-                case 0x06: // B2
-                  switch (coreCount) {
-                    case 2:
+      // check if processor supports a digital thermal sensor
+      if (cpuidData.GetLength(0) > 6 && (cpuidData[6, 0] & 1) != 0) {
+
+        switch (family) {
+          case 0x06: {
+              switch (model) {
+                case 0x0F: // Intel Core 65nm
+                  switch (stepping) {
+                    case 0x06: // B2
+                      switch (coreCount) {
+                        case 2:
+                          tjMax = 80; break;
+                        case 4:
+                          tjMax = 90; break;
+                        default:
+                          tjMax = 85; break;
+                      }
                       tjMax = 80; break;
-                    case 4:
+                    case 0x0B: // G0
                       tjMax = 90; break;
+                    case 0x0D: // M0
+                      tjMax = 85; break;
                     default:
                       tjMax = 85; break;
-                  }
-                  tjMax = 80; break;
-                case 0x0B: // G0
+                  } break;
+                case 0x17: // Intel Core 45nm
+                  tjMax = 100; break;
+                case 0x1C: // Intel Atom 
                   tjMax = 90; break;
-                case 0x0D: // M0
-                  tjMax = 85; break;
+                case 0x1A:
+                  uint eax = 0, edx = 0;
+                  if (WinRing0.RdmsrPx(
+                      IA32_TEMPERATURE_TARGET, ref eax, ref edx, (UIntPtr)1)) {
+                    tjMax = (eax >> 16) & 0xFF;
+                  } else
+                    tjMax = 100;
+                  break;
                 default:
-                  tjMax = 85; break;
-              } break;            
-            case 0x17: // Intel Core 45nm
-              tjMax = 100; break;
-            case 0x1C: // Intel Atom 
-              tjMax = 90; break;
-            case 0x1A:
-              uint eax = 0, edx = 0;
-              if (WinRing0.RdmsrPx(
-                  IA32_TEMPERATURE_TARGET, ref eax, ref edx, (UIntPtr)1)) {
-                tjMax = (eax >> 16) & 0xFF;
-              } else
-                tjMax = 100;
-              break;
-            default:
-              tjMax = 100; break;
-          }
-        } break;
-        default: tjMax = 100; break;
+                  tjMax = 100; break;
+              }
+            } break;
+          default: tjMax = 100; break;
+        }
+
+        coreTemperatures = new Sensor[coreCount];
+        for (int i = 0; i < coreTemperatures.Length; i++) {
+          coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax,
+            SensorType.Temperature, this);
+        }
+      } else {
+        coreTemperatures = new Sensor[0];
       }
-
-      totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);     
-
-      coreTemperatures = new Sensor[coreCount];
+              
+      totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);   
       coreLoads = new Sensor[coreCount];
-      for (int i = 0; i < coreTemperatures.Length; i++) {
-        coreTemperatures[i] = new Sensor("Core #" + (i + 1), i, tjMax,
-          SensorType.Temperature, this);
-        coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, 
-          SensorType.Load, this);
-      }
-
+      for (int i = 0; i < coreLoads.Length; i++) 
+        coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1,
+          SensorType.Load, this);     
       cpuLoad = new CPULoad(coreCount, logicalProcessorsPerCore);
       if (cpuLoad.IsAvailable) {
         foreach (Sensor sensor in coreLoads)
@@ -148,6 +160,16 @@
         ActivateSensor(totalLoad);
       }
 
+      lastCount = 0;
+      lastTime = 0;
+      busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this);      
+      coreClocks = new Sensor[coreCount];
+      for (int i = 0; i < coreClocks.Length; i++) {
+        coreClocks[i] = 
+          new Sensor("Core #" + (i + 1), i + 1, SensorType.Clock, this);
+        ActivateSensor(coreClocks[i]);
+      }
+      
       Update();                   
     }
 
@@ -180,9 +202,9 @@
     }
 
     public void Update() {
-
-      uint eax = 0, edx = 0;      
+            
       for (int i = 0; i < coreTemperatures.Length; i++) {
+        uint eax = 0, edx = 0;
         if (WinRing0.RdmsrPx(
           IA32_THERM_STATUS_MSR, ref eax, ref edx, 
             (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) 
@@ -204,6 +226,42 @@
           coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
         totalLoad.Value = cpuLoad.GetTotalLoad();
       }
+     
+      uint lsb = 0, msb = 0;
+      bool valid = WinRing0.RdtscPx(ref lsb, ref msb, (UIntPtr)1);
+      long time = Stopwatch.GetTimestamp();
+      ulong count = ((ulong)msb << 32) | lsb;
+      double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
+      if (valid && delta > 0.5) {
+        double maxClock = (float)((count - lastCount) / (1e6 * delta));
+        double busClock = 0;
+        uint eax, edx;       
+        for (int i = 0; i < coreClocks.Length; i++) {
+          eax = 0; edx = 0;
+          System.Threading.Thread.Sleep(1);
+          if (WinRing0.RdmsrPx(IA32_PERF_STATUS, ref eax, ref edx,
+            (UIntPtr)(1 << (int)(logicalProcessorsPerCore * i)))) {
+            uint multiplier = (eax >> 8) & 0x1f;
+            uint maxMultiplier = (edx >> 8) & 0x1f;
+            // factor = multiplier * 2 to handle non integer multipliers 
+            uint factor = (multiplier << 1) | ((eax >> 14) & 1);
+            uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
+            if (maxFactor > 0) {
+              coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
+              busClock = (float)(2 * maxClock / maxFactor);
+            }
+          } else {
+            // if IA32_PERF_STATUS is not available, assume maxClock
+            coreClocks[i].Value = (float)maxClock;
+          }                  
+        }
+        if (busClock > 0) {
+          this.busClock.Value = (float)busClock;
+          ActivateSensor(this.busClock);
+        }
+      }
+      lastCount = count;
+      lastTime = time;
     }  
   }
 }
diff -r 5b7398d061b7 -r c150de283ca0 Hardware/WinRing0.cs
--- a/Hardware/WinRing0.cs	Sat Feb 13 17:08:36 2010 +0000
+++ b/Hardware/WinRing0.cs	Sun Feb 14 20:16:30 2010 +0000
@@ -94,6 +94,8 @@
       uint regAddress, out uint value);
     public delegate bool WritePciConfigDwordExDelegate(uint pciAddress, 
       uint regAddress, uint value);
+    public delegate bool RdtscPxDelegate(ref uint eax, ref uint edx,
+      UIntPtr processAffinityMask);
 
     private static InitializeOlsDelegate InitializeOls;
     private static DeinitializeOlsDelegate DeinitializeOls;
@@ -108,7 +110,8 @@
     public static SetPciMaxBusIndexDelegate SetPciMaxBusIndex;
     public static FindPciDeviceByIdDelegate FindPciDeviceById;
     public static ReadPciConfigDwordExDelegate ReadPciConfigDwordEx;
-    public static WritePciConfigDwordExDelegate WritePciConfigDwordEx;    
+    public static WritePciConfigDwordExDelegate WritePciConfigDwordEx;
+    public static RdtscPxDelegate RdtscPx;
 
     private static void GetDelegate<T>(string entryPoint, out T newDelegate) 
       where T : class 
@@ -135,6 +138,7 @@
       GetDelegate("FindPciDeviceById", out FindPciDeviceById);
       GetDelegate("ReadPciConfigDwordEx", out ReadPciConfigDwordEx);
       GetDelegate("WritePciConfigDwordEx", out WritePciConfigDwordEx);
+      GetDelegate("RdtscPx", out RdtscPx);
 
       try {
         if (InitializeOls != null && InitializeOls())
diff -r 5b7398d061b7 -r c150de283ca0 Properties/AssemblyInfo.cs
--- a/Properties/AssemblyInfo.cs	Sat Feb 13 17:08:36 2010 +0000
+++ b/Properties/AssemblyInfo.cs	Sun Feb 14 20:16:30 2010 +0000
@@ -69,5 +69,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.1.19.0")]
-[assembly: AssemblyFileVersion("0.1.19.0")]
+[assembly: AssemblyVersion("0.1.20.0")]
+[assembly: AssemblyFileVersion("0.1.20.0")]