# HG changeset patch
# User moel.mich
# Date 1308492840 0
# Node ID d14ce71cef445b3afcb1375b677e5e5a6bcbe111
# Parent  ee03b05bce9f2bde6e7059fdbc44dc585e503fa3
Added initial support for AMD family 12h and 15h CPUs.

diff -r ee03b05bce9f -r d14ce71cef44 Hardware/CPU/AMD10CPU.cs
--- a/Hardware/CPU/AMD10CPU.cs	Sun Jun 19 12:59:07 2011 +0000
+++ b/Hardware/CPU/AMD10CPU.cs	Sun Jun 19 14:14:00 2011 +0000
@@ -61,7 +61,9 @@
     private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
     private const ushort FAMILY_10H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1203;
     private const ushort FAMILY_11H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1303;
-    private const ushort FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1703; 
+    private const ushort FAMILY_12H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1703;
+    private const ushort FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1703;
+    private const ushort FAMILY_15H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1603; 
     private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
     private const uint CLOCK_POWER_TIMING_CONTROL_0_REGISTER = 0xD4;
 
@@ -76,7 +78,7 @@
     public AMD10CPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
       : base(processorIndex, cpuid, settings) 
     {            
-      // AMD family 10h/11h processors support only one temperature sensor
+      // AMD family 1Xh processors support only one temperature sensor
       coreTemperature = new Sensor(
         "Core" + (coreCount > 1 ? " #1 - #" + coreCount : ""), 0,
         SensorType.Temperature, this, new [] {
@@ -88,8 +90,12 @@
           FAMILY_10H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
         case 0x11: miscellaneousControlDeviceId =
           FAMILY_11H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
+        case 0x12: miscellaneousControlDeviceId =
+          FAMILY_12H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
         case 0x14: miscellaneousControlDeviceId = 
           FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
+        case 0x15: miscellaneousControlDeviceId =
+          FAMILY_15H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
         default: miscellaneousControlDeviceId = 0; break;
       }
 
@@ -196,23 +202,8 @@
       while (Stopwatch.GetTimestamp() < timeEnd) { }
       Ring0.Rdmsr(PERF_CTR_0, out lsbEnd, out msbEnd);
       Ring0.Rdmsr(COFVID_STATUS, out eax, out edx);
+      double coreMultiplier = GetCoreMultiplier(eax);
 
-      double coreMultiplier;
-      if (family == 0x14) {               
-        uint divisorIdMSD = (eax >> 4) & 0x1F;
-        uint divisorIdLSD = eax & 0xF;
-        uint value = 0;
-        Ring0.ReadPciConfig(miscellaneousControlAddress,
-          CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
-        uint frequencyId = value & 0x1F;
-
-        coreMultiplier = 
-          MultiplierFromIDs(divisorIdMSD, divisorIdLSD, frequencyId);
-      } else {
-        uint cpuDid = (eax >> 6) & 7;
-        uint cpuFid = eax & 0x1F;
-        coreMultiplier = MultiplierFromIDs(cpuDid, cpuFid);
-      }
       ulong countBegin = ((ulong)msbBegin << 32) | lsbBegin;
       ulong countEnd = ((ulong)msbEnd << 32) | lsbEnd;
 
@@ -252,16 +243,48 @@
       return r.ToString();
     }
 
-    // calculate the multiplier for family 10h based on Did and Fid
-    private static double MultiplierFromIDs(uint divisorID, uint frequencyID) {
-      return 0.5 * (frequencyID + 0x10) / (1 << (int)divisorID);
-    }
-
-    // calculate the multiplier for family 14h based on DidMSD, DidLSD and Fid
-    private static double MultiplierFromIDs(uint divisorIdMSD, 
-      uint divisorIdLSD, uint frequencyId) 
-    {
-      return (frequencyId + 0x10) / (divisorIdMSD + (divisorIdLSD * 0.25) + 1);
+    private double GetCoreMultiplier(uint cofvidEax) {
+      switch (family) {
+        case 0x10:
+        case 0x11:
+          // 8:6 CpuDid: current core divisor ID
+          // 5:0 CpuFid: current core frequency ID
+          uint cpuDid = (cofvidEax >> 6) & 7;
+          uint cpuFid = cofvidEax & 0x1F;
+          return 0.5 * (cpuFid + 0x10) / (1 << (int)cpuDid);
+        case 0x12:
+          // 8:4 CpuFid: current CPU core frequency ID
+          // 3:0 CpuDid: current CPU core divisor ID
+          uint CpuFid = (cofvidEax >> 4) & 0x1F;
+          uint CpuDid = cofvidEax & 0xF;
+          double divisor;
+          switch (CpuDid) {
+            case 0: divisor = 1; break;
+            case 1: divisor = 1.5; break;
+            case 2: divisor = 2; break;
+            case 3: divisor = 3; break;
+            case 4: divisor = 4; break;
+            case 5: divisor = 6; break;
+            case 6: divisor = 8; break;
+            case 7: divisor = 12; break;
+            case 8: divisor = 16; break;
+            default: divisor = 1; break;
+          }
+          return (CpuFid + 0x10) / divisor;
+        case 0x14:
+          // 8:4: current CPU core divisor ID most significant digit
+          // 3:0: current CPU core divisor ID least significant digit
+          uint divisorIdMSD = (cofvidEax >> 4) & 0x1F;
+          uint divisorIdLSD = cofvidEax & 0xF;
+          uint value = 0;
+          Ring0.ReadPciConfig(miscellaneousControlAddress,
+            CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
+          uint frequencyId = value & 0x1F;
+          return (frequencyId + 0x10) /
+            (divisorIdMSD + (divisorIdLSD * 0.25) + 1);
+        default:
+          return 1;
+      }
     }
 
     private string ReadFirstLine(Stream stream) {
@@ -314,22 +337,7 @@
             1UL << cpuid[i][0].Thread)) 
           {
             double multiplier;
-            if (family == 0x14) {
-              uint divisorIdMSD = (curEax >> 4) & 0x1F;
-              uint divisorIdLSD = curEax & 0xF;
-              uint value = 0;
-              Ring0.ReadPciConfig(miscellaneousControlAddress,
-                CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
-              uint frequencyId = value & 0x1F;
-              multiplier =
-                MultiplierFromIDs(divisorIdMSD, divisorIdLSD, frequencyId);
-            } else {
-              // 8:6 CpuDid: current core divisor ID
-              // 5:0 CpuFid: current core frequency ID
-              uint cpuDid = (curEax >> 6) & 7;
-              uint cpuFid = curEax & 0x1F;
-              multiplier = MultiplierFromIDs(cpuDid, cpuFid);
-            }
+            multiplier = GetCoreMultiplier(curEax);
 
             coreClocks[i].Value = 
               (float)(multiplier * TimeStampCounterFrequency / 
diff -r ee03b05bce9f -r d14ce71cef44 Hardware/CPU/CPUGroup.cs
--- a/Hardware/CPU/CPUGroup.cs	Sun Jun 19 12:59:07 2011 +0000
+++ b/Hardware/CPU/CPUGroup.cs	Sun Jun 19 14:14:00 2011 +0000
@@ -125,7 +125,9 @@
                 break;
               case 0x10:
               case 0x11:
+              case 0x12:
               case 0x14:
+              case 0x15:
                 hardware.Add(new AMD10CPU(index, coreThreads, settings));
                 break;
               default:
diff -r ee03b05bce9f -r d14ce71cef44 Properties/AssemblyVersion.cs
--- a/Properties/AssemblyVersion.cs	Sun Jun 19 12:59:07 2011 +0000
+++ b/Properties/AssemblyVersion.cs	Sun Jun 19 14:14:00 2011 +0000
@@ -37,5 +37,5 @@
 
 using System.Reflection;
 
-[assembly: AssemblyVersion("0.3.2.1")]
-[assembly: AssemblyInformationalVersion("0.3.2.1 Alpha")]
\ No newline at end of file
+[assembly: AssemblyVersion("0.3.2.2")]
+[assembly: AssemblyInformationalVersion("0.3.2.2 Alpha")]
\ No newline at end of file