Rewritten the PCI access for AMD CPUs.
authormoel.mich
Wed, 22 Sep 2010 19:12:12 +0000
changeset 1965e9a8595296c
parent 195 0ee888c485d5
child 197 fb66f749b7ff
Rewritten the PCI access for AMD CPUs.
Hardware/CPU/AMD0FCPU.cs
Hardware/CPU/AMD10CPU.cs
Hardware/CPU/AMDCPU.cs
Hardware/WinRing0.cs
OpenHardwareMonitorLib.csproj
     1.1 --- a/Hardware/CPU/AMD0FCPU.cs	Tue Sep 21 20:32:36 2010 +0000
     1.2 +++ b/Hardware/CPU/AMD0FCPU.cs	Wed Sep 22 19:12:12 2010 +0000
     1.3 @@ -36,23 +36,27 @@
     1.4  */
     1.5  
     1.6  using System;
     1.7 +using System.Globalization;
     1.8 +using System.Text;
     1.9  using System.Threading;
    1.10  
    1.11  namespace OpenHardwareMonitor.Hardware.CPU {
    1.12 -  internal sealed class AMD0FCPU : GenericCPU {
    1.13 -
    1.14 -    private readonly uint pciAddress;
    1.15 +  internal sealed class AMD0FCPU : AMDCPU {
    1.16 +    
    1.17      private readonly Sensor[] coreTemperatures;
    1.18      private readonly Sensor[] coreClocks;
    1.19      private readonly Sensor busClock;
    1.20  
    1.21 -    private const ushort PCI_AMD_VENDOR_ID = 0x1022;
    1.22 -    private const ushort PCI_AMD_0FH_MISCELLANEOUS_DEVICE_ID = 0x1103;
    1.23      private const uint FIDVID_STATUS = 0xC0010042;
    1.24 +
    1.25 +    private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
    1.26 +    private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1103;
    1.27      private const uint THERMTRIP_STATUS_REGISTER = 0xE4;
    1.28      private const byte THERM_SENSE_CORE_SEL_CPU0 = 0x4;
    1.29      private const byte THERM_SENSE_CORE_SEL_CPU1 = 0x0;
    1.30  
    1.31 +    private readonly uint miscellaneousControlAddress;
    1.32 +
    1.33      public AMD0FCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
    1.34        : base(processorIndex, cpuid, settings) 
    1.35      {
    1.36 @@ -80,8 +84,8 @@
    1.37          coreTemperatures = new Sensor[0];
    1.38        }
    1.39  
    1.40 -      pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID,
    1.41 -        PCI_AMD_0FH_MISCELLANEOUS_DEVICE_ID, (byte)processorIndex);
    1.42 +      miscellaneousControlAddress = GetPciAddress(
    1.43 +        MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
    1.44  
    1.45        busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
    1.46        coreClocks = new Sensor[coreCount];
    1.47 @@ -99,17 +103,31 @@
    1.48        return new [] { FIDVID_STATUS };
    1.49      }
    1.50  
    1.51 +    public override string GetReport() {
    1.52 +      StringBuilder r = new StringBuilder();
    1.53 +      r.Append(base.GetReport());
    1.54 +
    1.55 +      r.Append("Miscellaneous Control Address: ");
    1.56 +      r.AppendLine((miscellaneousControlAddress).ToString("X", 
    1.57 +        CultureInfo.InvariantCulture));
    1.58 +      r.AppendLine();
    1.59 +
    1.60 +      return r.ToString();
    1.61 +    }
    1.62 +
    1.63      public override void Update() {
    1.64        base.Update();
    1.65  
    1.66 -      if (pciAddress != 0xFFFFFFFF) {
    1.67 +      if (miscellaneousControlAddress != WinRing0.InvalidPciAddress) {
    1.68          for (uint i = 0; i < coreTemperatures.Length; i++) {
    1.69            if (WinRing0.WritePciConfigDwordEx(
    1.70 -            pciAddress, THERMTRIP_STATUS_REGISTER,
    1.71 +            miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
    1.72              i > 0 ? THERM_SENSE_CORE_SEL_CPU1 : THERM_SENSE_CORE_SEL_CPU0)) {
    1.73              uint value;
    1.74              if (WinRing0.ReadPciConfigDwordEx(
    1.75 -              pciAddress, THERMTRIP_STATUS_REGISTER, out value)) {
    1.76 +              miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, 
    1.77 +              out value)) 
    1.78 +            {
    1.79                coreTemperatures[i].Value = ((value >> 16) & 0xFF) + 
    1.80                  coreTemperatures[i].Parameters[0].Value;
    1.81                ActivateSensor(coreTemperatures[i]);
     2.1 --- a/Hardware/CPU/AMD10CPU.cs	Tue Sep 21 20:32:36 2010 +0000
     2.2 +++ b/Hardware/CPU/AMD10CPU.cs	Wed Sep 22 19:12:12 2010 +0000
     2.3 @@ -35,22 +35,25 @@
     2.4   
     2.5  */
     2.6  
     2.7 +using System;
     2.8 +using System.Globalization;
     2.9 +using System.Text;
    2.10 +
    2.11  namespace OpenHardwareMonitor.Hardware.CPU {
    2.12  
    2.13 -  internal sealed class AMD10CPU : GenericCPU {
    2.14 -
    2.15 -    private readonly uint pciAddress;
    2.16 +  internal sealed class AMD10CPU : AMDCPU {
    2.17  
    2.18      private readonly Sensor coreTemperature;
    2.19  
    2.20 -    private const ushort PCI_AMD_VENDOR_ID = 0x1022;
    2.21 -    private const ushort PCI_AMD_10H_MISCELLANEOUS_DEVICE_ID = 0x1203;
    2.22 -    private const ushort PCI_AMD_11H_MISCELLANEOUS_DEVICE_ID = 0x1303;
    2.23 -    private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
    2.24 +    private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
    2.25 +    private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1203;
    2.26 +    private const byte REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
    2.27 +    
    2.28 +    private readonly uint miscellaneousControlAddress;
    2.29  
    2.30      public AMD10CPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
    2.31        : base(processorIndex, cpuid, settings) 
    2.32 -    {      
    2.33 +    {            
    2.34        // AMD family 10h processors support only one temperature sensor
    2.35        coreTemperature = new Sensor(
    2.36          "Core" + (coreCount > 1 ? " #1 - #" + coreCount : ""), 0,
    2.37 @@ -58,11 +61,9 @@
    2.38              new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
    2.39            }, settings);
    2.40  
    2.41 -      pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID,
    2.42 -        PCI_AMD_10H_MISCELLANEOUS_DEVICE_ID, (byte)processorIndex);
    2.43 -      if (pciAddress == 0xFFFFFFFF) 
    2.44 -        pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID,
    2.45 -          PCI_AMD_11H_MISCELLANEOUS_DEVICE_ID, (byte)processorIndex);
    2.46 +      // get the pci address for the Miscellaneous Control registers 
    2.47 +      miscellaneousControlAddress = GetPciAddress(
    2.48 +        MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
    2.49  
    2.50        Update();                   
    2.51      }
    2.52 @@ -71,12 +72,24 @@
    2.53        return new uint[] { };
    2.54      }
    2.55  
    2.56 +    public override string GetReport() {
    2.57 +      StringBuilder r = new StringBuilder();
    2.58 +      r.Append(base.GetReport());
    2.59 +
    2.60 +      r.Append("Miscellaneous Control Address: ");
    2.61 +      r.AppendLine((miscellaneousControlAddress).ToString("X",
    2.62 +        CultureInfo.InvariantCulture));
    2.63 +      r.AppendLine();
    2.64 +
    2.65 +      return r.ToString();
    2.66 +    }
    2.67 +
    2.68      public override void Update() {
    2.69        base.Update();
    2.70  
    2.71 -      if (pciAddress != 0xFFFFFFFF) {
    2.72 +      if (miscellaneousControlAddress != WinRing0.InvalidPciAddress) {
    2.73          uint value;
    2.74 -        if (WinRing0.ReadPciConfigDwordEx(pciAddress,
    2.75 +        if (WinRing0.ReadPciConfigDwordEx(miscellaneousControlAddress,
    2.76            REPORTED_TEMPERATURE_CONTROL_REGISTER, out value)) {
    2.77            coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f +
    2.78              coreTemperature.Parameters[0].Value;
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/Hardware/CPU/AMDCPU.cs	Wed Sep 22 19:12:12 2010 +0000
     3.3 @@ -0,0 +1,66 @@
     3.4 +/*
     3.5 +  
     3.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     3.7 +
     3.8 +  The contents of this file are subject to the Mozilla Public License Version
     3.9 +  1.1 (the "License"); you may not use this file except in compliance with
    3.10 +  the License. You may obtain a copy of the License at
    3.11 + 
    3.12 +  http://www.mozilla.org/MPL/
    3.13 +
    3.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    3.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    3.16 +  for the specific language governing rights and limitations under the License.
    3.17 +
    3.18 +  The Original Code is the Open Hardware Monitor code.
    3.19 +
    3.20 +  The Initial Developer of the Original Code is 
    3.21 +  Michael Möller <m.moeller@gmx.ch>.
    3.22 +  Portions created by the Initial Developer are Copyright (C) 2009-2010
    3.23 +  the Initial Developer. All Rights Reserved.
    3.24 +
    3.25 +  Contributor(s):
    3.26 +
    3.27 +  Alternatively, the contents of this file may be used under the terms of
    3.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    3.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    3.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    3.31 +  of those above. If you wish to allow use of your version of this file only
    3.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    3.33 +  use your version of this file under the terms of the MPL, indicate your
    3.34 +  decision by deleting the provisions above and replace them with the notice
    3.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    3.36 +  the provisions above, a recipient may use your version of this file under
    3.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    3.38 + 
    3.39 +*/
    3.40 +
    3.41 +namespace OpenHardwareMonitor.Hardware.CPU {
    3.42 +
    3.43 +  internal abstract class AMDCPU : GenericCPU {
    3.44 +
    3.45 +    private const byte PCI_BUS = 0;
    3.46 +    private const byte PCI_BASE_DEVICE = 24;
    3.47 +    private const byte DEVICE_VENDOR_ID_REGISTER = 0;
    3.48 +    private const ushort AMD_VENDOR_ID = 0x1022;
    3.49 +
    3.50 +    public AMDCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
    3.51 +      : base(processorIndex, cpuid, settings) { }
    3.52 +
    3.53 +    protected uint GetPciAddress(byte function, ushort deviceId) {
    3.54 +      uint address = WinRing0.GetPciAddress(PCI_BUS,
    3.55 +        (byte)(PCI_BASE_DEVICE + processorIndex), function);
    3.56 +
    3.57 +      uint deviceVendor;
    3.58 +      if (!WinRing0.ReadPciConfigDwordEx(
    3.59 +        address, DEVICE_VENDOR_ID_REGISTER, out deviceVendor))
    3.60 +        return WinRing0.InvalidPciAddress;
    3.61 +
    3.62 +      if (deviceVendor != (deviceId << 16 | AMD_VENDOR_ID))
    3.63 +        return WinRing0.InvalidPciAddress;
    3.64 +
    3.65 +      return address;
    3.66 +    }
    3.67 +
    3.68 +  }
    3.69 +}
     4.1 --- a/Hardware/WinRing0.cs	Tue Sep 21 20:32:36 2010 +0000
     4.2 +++ b/Hardware/WinRing0.cs	Wed Sep 22 19:12:12 2010 +0000
     4.3 @@ -87,8 +87,6 @@
     4.4        UIntPtr threadAffinityMask);
     4.5      public delegate byte ReadIoPortByteDelegate(ushort port);
     4.6      public delegate void WriteIoPortByteDelegate(ushort port, byte value);
     4.7 -    public delegate uint FindPciDeviceByIdDelegate(ushort vendorId, 
     4.8 -      ushort deviceId, byte index);
     4.9      public delegate bool ReadPciConfigDwordExDelegate(uint pciAddress, 
    4.10        uint regAddress, out uint value);
    4.11      public delegate bool WritePciConfigDwordExDelegate(uint pciAddress, 
    4.12 @@ -114,8 +112,6 @@
    4.13        CreateDelegate<ReadIoPortByteDelegate>("ReadIoPortByte");
    4.14      public static readonly WriteIoPortByteDelegate WriteIoPortByte =
    4.15        CreateDelegate<WriteIoPortByteDelegate>("WriteIoPortByte");
    4.16 -    public static readonly FindPciDeviceByIdDelegate FindPciDeviceById =
    4.17 -      CreateDelegate<FindPciDeviceByIdDelegate>("FindPciDeviceById");
    4.18      public static readonly ReadPciConfigDwordExDelegate ReadPciConfigDwordEx =
    4.19        CreateDelegate<ReadPciConfigDwordExDelegate>("ReadPciConfigDwordEx");
    4.20      public static readonly WritePciConfigDwordExDelegate WritePciConfigDwordEx =
    4.21 @@ -164,6 +160,13 @@
    4.22  
    4.23      public static void ReleaseIsaBusMutex() {
    4.24        isaBusMutex.ReleaseMutex();
    4.25 -    }    
    4.26 +    }
    4.27 +
    4.28 +    public const uint InvalidPciAddress = 0xFFFFFFFF;
    4.29 +
    4.30 +    public static uint GetPciAddress(byte bus, byte device, byte function)	{
    4.31 +      return 
    4.32 +        (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7));
    4.33 +    }
    4.34    }
    4.35  }
     5.1 --- a/OpenHardwareMonitorLib.csproj	Tue Sep 21 20:32:36 2010 +0000
     5.2 +++ b/OpenHardwareMonitorLib.csproj	Wed Sep 22 19:12:12 2010 +0000
     5.3 @@ -61,6 +61,7 @@
     5.4      <Compile Include="Hardware\ATI\ATIGPU.cs" />
     5.5      <Compile Include="Hardware\ATI\ATIGroup.cs" />
     5.6      <Compile Include="Hardware\Computer.cs" />
     5.7 +    <Compile Include="Hardware\CPU\AMDCPU.cs" />
     5.8      <Compile Include="Hardware\CPU\GenericCPU.cs" />
     5.9      <Compile Include="Hardware\CPU\AMD0FCPU.cs" />
    5.10      <Compile Include="Hardware\CPU\AMD10CPU.cs" />