# HG changeset patch
# User moel.mich
# Date 1285182732 0
# Node ID 5e9a8595296c80ac445f5868ff56e53f124be606
# Parent  0ee888c485d5019ea8e48d5394f4917b7a01be0f
Rewritten the PCI access for AMD CPUs.

diff -r 0ee888c485d5 -r 5e9a8595296c Hardware/CPU/AMD0FCPU.cs
--- a/Hardware/CPU/AMD0FCPU.cs	Tue Sep 21 20:32:36 2010 +0000
+++ b/Hardware/CPU/AMD0FCPU.cs	Wed Sep 22 19:12:12 2010 +0000
@@ -36,23 +36,27 @@
 */
 
 using System;
+using System.Globalization;
+using System.Text;
 using System.Threading;
 
 namespace OpenHardwareMonitor.Hardware.CPU {
-  internal sealed class AMD0FCPU : GenericCPU {
-
-    private readonly uint pciAddress;
+  internal sealed class AMD0FCPU : AMDCPU {
+    
     private readonly Sensor[] coreTemperatures;
     private readonly Sensor[] coreClocks;
     private readonly Sensor busClock;
 
-    private const ushort PCI_AMD_VENDOR_ID = 0x1022;
-    private const ushort PCI_AMD_0FH_MISCELLANEOUS_DEVICE_ID = 0x1103;
     private const uint FIDVID_STATUS = 0xC0010042;
+
+    private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
+    private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1103;
     private const uint THERMTRIP_STATUS_REGISTER = 0xE4;
     private const byte THERM_SENSE_CORE_SEL_CPU0 = 0x4;
     private const byte THERM_SENSE_CORE_SEL_CPU1 = 0x0;
 
+    private readonly uint miscellaneousControlAddress;
+
     public AMD0FCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
       : base(processorIndex, cpuid, settings) 
     {
@@ -80,8 +84,8 @@
         coreTemperatures = new Sensor[0];
       }
 
-      pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID,
-        PCI_AMD_0FH_MISCELLANEOUS_DEVICE_ID, (byte)processorIndex);
+      miscellaneousControlAddress = GetPciAddress(
+        MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
 
       busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
       coreClocks = new Sensor[coreCount];
@@ -99,17 +103,31 @@
       return new [] { FIDVID_STATUS };
     }
 
+    public override string GetReport() {
+      StringBuilder r = new StringBuilder();
+      r.Append(base.GetReport());
+
+      r.Append("Miscellaneous Control Address: ");
+      r.AppendLine((miscellaneousControlAddress).ToString("X", 
+        CultureInfo.InvariantCulture));
+      r.AppendLine();
+
+      return r.ToString();
+    }
+
     public override void Update() {
       base.Update();
 
-      if (pciAddress != 0xFFFFFFFF) {
+      if (miscellaneousControlAddress != WinRing0.InvalidPciAddress) {
         for (uint i = 0; i < coreTemperatures.Length; i++) {
           if (WinRing0.WritePciConfigDwordEx(
-            pciAddress, THERMTRIP_STATUS_REGISTER,
+            miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
             i > 0 ? THERM_SENSE_CORE_SEL_CPU1 : THERM_SENSE_CORE_SEL_CPU0)) {
             uint value;
             if (WinRing0.ReadPciConfigDwordEx(
-              pciAddress, THERMTRIP_STATUS_REGISTER, out value)) {
+              miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, 
+              out value)) 
+            {
               coreTemperatures[i].Value = ((value >> 16) & 0xFF) + 
                 coreTemperatures[i].Parameters[0].Value;
               ActivateSensor(coreTemperatures[i]);
diff -r 0ee888c485d5 -r 5e9a8595296c Hardware/CPU/AMD10CPU.cs
--- a/Hardware/CPU/AMD10CPU.cs	Tue Sep 21 20:32:36 2010 +0000
+++ b/Hardware/CPU/AMD10CPU.cs	Wed Sep 22 19:12:12 2010 +0000
@@ -35,22 +35,25 @@
  
 */
 
+using System;
+using System.Globalization;
+using System.Text;
+
 namespace OpenHardwareMonitor.Hardware.CPU {
 
-  internal sealed class AMD10CPU : GenericCPU {
-
-    private readonly uint pciAddress;
+  internal sealed class AMD10CPU : AMDCPU {
 
     private readonly Sensor coreTemperature;
 
-    private const ushort PCI_AMD_VENDOR_ID = 0x1022;
-    private const ushort PCI_AMD_10H_MISCELLANEOUS_DEVICE_ID = 0x1203;
-    private const ushort PCI_AMD_11H_MISCELLANEOUS_DEVICE_ID = 0x1303;
-    private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
+    private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
+    private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1203;
+    private const byte REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
+    
+    private readonly uint miscellaneousControlAddress;
 
     public AMD10CPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
       : base(processorIndex, cpuid, settings) 
-    {      
+    {            
       // AMD family 10h processors support only one temperature sensor
       coreTemperature = new Sensor(
         "Core" + (coreCount > 1 ? " #1 - #" + coreCount : ""), 0,
@@ -58,11 +61,9 @@
             new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
           }, settings);
 
-      pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID,
-        PCI_AMD_10H_MISCELLANEOUS_DEVICE_ID, (byte)processorIndex);
-      if (pciAddress == 0xFFFFFFFF) 
-        pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID,
-          PCI_AMD_11H_MISCELLANEOUS_DEVICE_ID, (byte)processorIndex);
+      // get the pci address for the Miscellaneous Control registers 
+      miscellaneousControlAddress = GetPciAddress(
+        MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
 
       Update();                   
     }
@@ -71,12 +72,24 @@
       return new uint[] { };
     }
 
+    public override string GetReport() {
+      StringBuilder r = new StringBuilder();
+      r.Append(base.GetReport());
+
+      r.Append("Miscellaneous Control Address: ");
+      r.AppendLine((miscellaneousControlAddress).ToString("X",
+        CultureInfo.InvariantCulture));
+      r.AppendLine();
+
+      return r.ToString();
+    }
+
     public override void Update() {
       base.Update();
 
-      if (pciAddress != 0xFFFFFFFF) {
+      if (miscellaneousControlAddress != WinRing0.InvalidPciAddress) {
         uint value;
-        if (WinRing0.ReadPciConfigDwordEx(pciAddress,
+        if (WinRing0.ReadPciConfigDwordEx(miscellaneousControlAddress,
           REPORTED_TEMPERATURE_CONTROL_REGISTER, out value)) {
           coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f +
             coreTemperature.Parameters[0].Value;
diff -r 0ee888c485d5 -r 5e9a8595296c Hardware/CPU/AMDCPU.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/CPU/AMDCPU.cs	Wed Sep 22 19:12:12 2010 +0000
@@ -0,0 +1,66 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+namespace OpenHardwareMonitor.Hardware.CPU {
+
+  internal abstract class AMDCPU : GenericCPU {
+
+    private const byte PCI_BUS = 0;
+    private const byte PCI_BASE_DEVICE = 24;
+    private const byte DEVICE_VENDOR_ID_REGISTER = 0;
+    private const ushort AMD_VENDOR_ID = 0x1022;
+
+    public AMDCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
+      : base(processorIndex, cpuid, settings) { }
+
+    protected uint GetPciAddress(byte function, ushort deviceId) {
+      uint address = WinRing0.GetPciAddress(PCI_BUS,
+        (byte)(PCI_BASE_DEVICE + processorIndex), function);
+
+      uint deviceVendor;
+      if (!WinRing0.ReadPciConfigDwordEx(
+        address, DEVICE_VENDOR_ID_REGISTER, out deviceVendor))
+        return WinRing0.InvalidPciAddress;
+
+      if (deviceVendor != (deviceId << 16 | AMD_VENDOR_ID))
+        return WinRing0.InvalidPciAddress;
+
+      return address;
+    }
+
+  }
+}
diff -r 0ee888c485d5 -r 5e9a8595296c Hardware/WinRing0.cs
--- a/Hardware/WinRing0.cs	Tue Sep 21 20:32:36 2010 +0000
+++ b/Hardware/WinRing0.cs	Wed Sep 22 19:12:12 2010 +0000
@@ -87,8 +87,6 @@
       UIntPtr threadAffinityMask);
     public delegate byte ReadIoPortByteDelegate(ushort port);
     public delegate void WriteIoPortByteDelegate(ushort port, byte value);
-    public delegate uint FindPciDeviceByIdDelegate(ushort vendorId, 
-      ushort deviceId, byte index);
     public delegate bool ReadPciConfigDwordExDelegate(uint pciAddress, 
       uint regAddress, out uint value);
     public delegate bool WritePciConfigDwordExDelegate(uint pciAddress, 
@@ -114,8 +112,6 @@
       CreateDelegate<ReadIoPortByteDelegate>("ReadIoPortByte");
     public static readonly WriteIoPortByteDelegate WriteIoPortByte =
       CreateDelegate<WriteIoPortByteDelegate>("WriteIoPortByte");
-    public static readonly FindPciDeviceByIdDelegate FindPciDeviceById =
-      CreateDelegate<FindPciDeviceByIdDelegate>("FindPciDeviceById");
     public static readonly ReadPciConfigDwordExDelegate ReadPciConfigDwordEx =
       CreateDelegate<ReadPciConfigDwordExDelegate>("ReadPciConfigDwordEx");
     public static readonly WritePciConfigDwordExDelegate WritePciConfigDwordEx =
@@ -164,6 +160,13 @@
 
     public static void ReleaseIsaBusMutex() {
       isaBusMutex.ReleaseMutex();
-    }    
+    }
+
+    public const uint InvalidPciAddress = 0xFFFFFFFF;
+
+    public static uint GetPciAddress(byte bus, byte device, byte function)	{
+      return 
+        (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7));
+    }
   }
 }
diff -r 0ee888c485d5 -r 5e9a8595296c OpenHardwareMonitorLib.csproj
--- a/OpenHardwareMonitorLib.csproj	Tue Sep 21 20:32:36 2010 +0000
+++ b/OpenHardwareMonitorLib.csproj	Wed Sep 22 19:12:12 2010 +0000
@@ -61,6 +61,7 @@
     <Compile Include="Hardware\ATI\ATIGPU.cs" />
     <Compile Include="Hardware\ATI\ATIGroup.cs" />
     <Compile Include="Hardware\Computer.cs" />
+    <Compile Include="Hardware\CPU\AMDCPU.cs" />
     <Compile Include="Hardware\CPU\GenericCPU.cs" />
     <Compile Include="Hardware\CPU\AMD0FCPU.cs" />
     <Compile Include="Hardware\CPU\AMD10CPU.cs" />