Hardware/Nvidia/NVAPI.cs
author moel.mich
Thu, 07 Jul 2011 21:53:09 +0000
changeset 309 65a1ae21325d
parent 195 0ee888c485d5
child 334 013e148e8f12
permissions -rw-r--r--
Added fan control for Nvidia GPUs based on a patch by Christian Valli?res.
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2011
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23   Christian Vallières
    24 
    25   Alternatively, the contents of this file may be used under the terms of
    26   either the GNU General Public License Version 2 or later (the "GPL"), or
    27   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    28   in which case the provisions of the GPL or the LGPL are applicable instead
    29   of those above. If you wish to allow use of your version of this file only
    30   under the terms of either the GPL or the LGPL, and not to allow others to
    31   use your version of this file under the terms of the MPL, indicate your
    32   decision by deleting the provisions above and replace them with the notice
    33   and other provisions required by the GPL or the LGPL. If you do not delete
    34   the provisions above, a recipient may use your version of this file under
    35   the terms of any one of the MPL, the GPL or the LGPL.
    36  
    37 */
    38 
    39 using System;
    40 using System.Runtime.InteropServices;
    41 using System.Text;
    42 
    43 namespace OpenHardwareMonitor.Hardware.Nvidia {
    44 
    45   internal enum NvStatus {
    46     OK = 0,
    47     ERROR = -1,
    48     LIBRARY_NOT_FOUND = -2,
    49     NO_IMPLEMENTATION = -3,
    50     API_NOT_INTIALIZED = -4,
    51     INVALID_ARGUMENT = -5,
    52     NVIDIA_DEVICE_NOT_FOUND = -6,
    53     END_ENUMERATION = -7,
    54     INVALID_HANDLE = -8,
    55     INCOMPATIBLE_STRUCT_VERSION = -9,
    56     HANDLE_INVALIDATED = -10,
    57     OPENGL_CONTEXT_NOT_CURRENT = -11,
    58     NO_GL_EXPERT = -12,
    59     INSTRUMENTATION_DISABLED = -13,
    60     EXPECTED_LOGICAL_GPU_HANDLE = -100,
    61     EXPECTED_PHYSICAL_GPU_HANDLE = -101,
    62     EXPECTED_DISPLAY_HANDLE = -102,
    63     INVALID_COMBINATION = -103,
    64     NOT_SUPPORTED = -104,
    65     PORTID_NOT_FOUND = -105,
    66     EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106,
    67     INVALID_PERF_LEVEL = -107,
    68     DEVICE_BUSY = -108,
    69     NV_PERSIST_FILE_NOT_FOUND = -109,
    70     PERSIST_DATA_NOT_FOUND = -110,
    71     EXPECTED_TV_DISPLAY = -111,
    72     EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112,
    73     NO_ACTIVE_SLI_TOPOLOGY = -113,
    74     SLI_RENDERING_MODE_NOTALLOWED = -114,
    75     EXPECTED_DIGITAL_FLAT_PANEL = -115,
    76     ARGUMENT_EXCEED_MAX_SIZE = -116,
    77     DEVICE_SWITCHING_NOT_ALLOWED = -117,
    78     TESTING_CLOCKS_NOT_SUPPORTED = -118,
    79     UNKNOWN_UNDERSCAN_CONFIG = -119,
    80     TIMEOUT_RECONFIGURING_GPU_TOPO = -120,
    81     DATA_NOT_FOUND = -121,
    82     EXPECTED_ANALOG_DISPLAY = -122,
    83     NO_VIDLINK = -123,
    84     REQUIRES_REBOOT = -124,
    85     INVALID_HYBRID_MODE = -125,
    86     MIXED_TARGET_TYPES = -126,
    87     SYSWOW64_NOT_SUPPORTED = -127,
    88     IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128,
    89     REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129,
    90     OUT_OF_MEMORY = -130,
    91     WAS_STILL_DRAWING = -131,
    92     FILE_NOT_FOUND = -132,
    93     TOO_MANY_UNIQUE_STATE_OBJECTS = -133,
    94     INVALID_CALL = -134,
    95     D3D10_1_LIBRARY_NOT_FOUND = -135,
    96     FUNCTION_NOT_FOUND = -136
    97   }
    98 
    99   internal enum NvThermalController {
   100     NONE = 0,
   101     GPU_INTERNAL,
   102     ADM1032,
   103     MAX6649,
   104     MAX1617,
   105     LM99,
   106     LM89,
   107     LM64,
   108     ADT7473,
   109     SBMAX6649,
   110     VBIOSEVT,
   111     OS,
   112     UNKNOWN = -1,
   113   }
   114 
   115   internal enum NvThermalTarget {
   116     NONE = 0,
   117     GPU = 1,
   118     MEMORY = 2,
   119     POWER_SUPPLY = 4,
   120     BOARD = 8,
   121     ALL = 15,
   122     UNKNOWN = -1
   123   };
   124 
   125   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   126   internal struct NvSensor {
   127     public NvThermalController Controller;
   128     public uint DefaultMinTemp;
   129     public uint DefaultMaxTemp;
   130     public uint CurrentTemp;
   131     public NvThermalTarget Target;
   132   }
   133 
   134   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   135   internal struct NvGPUThermalSettings {
   136     public uint Version;
   137     public uint Count;
   138     [MarshalAs(UnmanagedType.ByValArray,
   139       SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)]
   140     public NvSensor[] Sensor;
   141   }
   142 
   143   [StructLayout(LayoutKind.Sequential)]
   144   internal struct NvDisplayHandle {
   145     private readonly IntPtr ptr;
   146   }
   147 
   148   [StructLayout(LayoutKind.Sequential)]
   149   internal struct NvPhysicalGpuHandle {
   150     private readonly IntPtr ptr;
   151   }
   152 
   153   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   154   internal struct NvClocks {
   155     public uint Version;
   156     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_CLOCKS_PER_GPU)]
   157     public uint[] Clock;
   158   }
   159 
   160   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   161   internal struct NvPState {
   162     public bool Present;
   163     public int Percentage;
   164   }
   165 
   166   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   167   internal struct NvPStates {
   168     public uint Version;
   169     public uint Flags;
   170     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_PSTATES_PER_GPU)]
   171     public NvPState[] PStates;
   172   }
   173 
   174   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   175   internal struct NvUsages {
   176     public uint Version;
   177     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_USAGES_PER_GPU)]
   178     public uint[] Usage;
   179   }
   180 
   181   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   182   internal struct NvCooler {
   183     public int Type;
   184     public int Controller;
   185     public int DefaultMin;
   186     public int DefaultMax;
   187     public int CurrentMin;
   188     public int CurrentMax;
   189     public int CurrentLevel;
   190     public int DefaultPolicy;
   191     public int CurrentPolicy;
   192     public int Target;
   193     public int ControlType;
   194     public int Active;
   195   }
   196 
   197   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   198   internal struct NvGPUCoolerSettings {
   199     public uint Version;
   200     public uint Count;
   201     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_COOLER_PER_GPU)]
   202     public NvCooler[] Cooler;
   203   }
   204 
   205   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   206   internal struct NvLevel {
   207     public int Level;
   208     public int Policy;
   209   }
   210 
   211   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   212   internal struct NvGPUCoolerLevels {
   213     public uint Version;
   214     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_COOLER_PER_GPU)]
   215     public NvLevel[] Levels;
   216   }
   217 
   218   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   219   internal struct NvMemoryInfo {
   220     public uint Version;
   221     [MarshalAs(UnmanagedType.ByValArray, SizeConst =
   222       NVAPI.MAX_MEMORY_VALUES_PER_GPU)]
   223     public uint[] Values;
   224   }
   225 
   226   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   227   internal struct NvDisplayDriverVersion {
   228     public uint Version;
   229     public uint DriverVersion;
   230     public uint BldChangeListNum;
   231     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)]
   232     public string BuildBranch;
   233     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)]
   234     public string Adapter;
   235   }
   236 
   237   internal class NVAPI {
   238 
   239     public const int MAX_PHYSICAL_GPUS = 64;
   240     public const int SHORT_STRING_MAX = 64;
   241 
   242     public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
   243     public const int MAX_CLOCKS_PER_GPU = 0x120;
   244     public const int MAX_PSTATES_PER_GPU = 8;
   245     public const int MAX_USAGES_PER_GPU = 33;
   246     public const int MAX_COOLER_PER_GPU = 20;
   247     public const int MAX_MEMORY_VALUES_PER_GPU = 5;
   248 
   249     public static readonly uint GPU_THERMAL_SETTINGS_VER = (uint)
   250       Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
   251     public static readonly uint GPU_CLOCKS_VER = (uint)
   252       Marshal.SizeOf(typeof(NvClocks)) | 0x20000;
   253     public static readonly uint GPU_PSTATES_VER = (uint)
   254       Marshal.SizeOf(typeof(NvPStates)) | 0x10000;
   255     public static readonly uint GPU_USAGES_VER = (uint)
   256       Marshal.SizeOf(typeof(NvUsages)) | 0x10000;
   257     public static readonly uint GPU_COOLER_SETTINGS_VER = (uint)
   258       Marshal.SizeOf(typeof(NvGPUCoolerSettings)) | 0x20000;
   259     public static readonly uint GPU_MEMORY_INFO_VER = (uint)
   260       Marshal.SizeOf(typeof(NvMemoryInfo)) | 0x20000;
   261     public static readonly uint DISPLAY_DRIVER_VERSION_VER = (uint)
   262       Marshal.SizeOf(typeof(NvDisplayDriverVersion)) | 0x10000;
   263     public static readonly uint GPU_COOLER_LEVELS_VER = (uint)
   264       Marshal.SizeOf(typeof(NvGPUCoolerLevels)) | 0x10000;
   265 
   266     private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id);
   267     private delegate NvStatus NvAPI_InitializeDelegate();
   268     private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(
   269       NvPhysicalGpuHandle gpuHandle, StringBuilder name);
   270 
   271     public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate(
   272       NvPhysicalGpuHandle gpuHandle, int sensorIndex,
   273       ref NvGPUThermalSettings nvGPUThermalSettings);
   274     public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum,
   275       ref NvDisplayHandle displayHandle);
   276     public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(
   277       NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles,
   278       out uint gpuCount);
   279     public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate(
   280       [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
   281     public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate(
   282       NvPhysicalGpuHandle gpuHandle, out int value);
   283     public delegate NvStatus NvAPI_GPU_GetAllClocksDelegate(
   284       NvPhysicalGpuHandle gpuHandle, ref NvClocks nvClocks);
   285     public delegate NvStatus NvAPI_GPU_GetPStatesDelegate(
   286       NvPhysicalGpuHandle gpuHandle, ref NvPStates nvPStates);
   287     public delegate NvStatus NvAPI_GPU_GetUsagesDelegate(
   288       NvPhysicalGpuHandle gpuHandle, ref NvUsages nvUsages);
   289     public delegate NvStatus NvAPI_GPU_GetCoolerSettingsDelegate(
   290       NvPhysicalGpuHandle gpuHandle, int coolerIndex,
   291       ref NvGPUCoolerSettings nvGPUCoolerSettings);
   292     public delegate NvStatus NvAPI_GPU_SetCoolerLevelsDelegate(
   293       NvPhysicalGpuHandle gpuHandle, int coolerIndex,
   294       ref NvGPUCoolerLevels NvGPUCoolerLevels);
   295     public delegate NvStatus NvAPI_GPU_GetMemoryInfoDelegate(
   296       NvDisplayHandle displayHandle, ref NvMemoryInfo nvMemoryInfo);
   297     public delegate NvStatus NvAPI_GetDisplayDriverVersionDelegate(
   298       NvDisplayHandle displayHandle, [In, Out] ref NvDisplayDriverVersion
   299       nvDisplayDriverVersion);
   300     public delegate NvStatus NvAPI_GetInterfaceVersionStringDelegate(
   301       StringBuilder version);
   302 
   303     private static readonly bool available;
   304     private static readonly nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
   305     private static readonly NvAPI_InitializeDelegate NvAPI_Initialize;
   306     private static readonly NvAPI_GPU_GetFullNameDelegate
   307       _NvAPI_GPU_GetFullName;
   308     private static readonly NvAPI_GetInterfaceVersionStringDelegate
   309       _NvAPI_GetInterfaceVersionString;
   310 
   311     public static readonly NvAPI_GPU_GetThermalSettingsDelegate
   312       NvAPI_GPU_GetThermalSettings;
   313     public static readonly NvAPI_EnumNvidiaDisplayHandleDelegate
   314       NvAPI_EnumNvidiaDisplayHandle;
   315     public static readonly NvAPI_GetPhysicalGPUsFromDisplayDelegate
   316       NvAPI_GetPhysicalGPUsFromDisplay;
   317     public static readonly NvAPI_EnumPhysicalGPUsDelegate
   318       NvAPI_EnumPhysicalGPUs;
   319     public static readonly NvAPI_GPU_GetTachReadingDelegate
   320       NvAPI_GPU_GetTachReading;
   321     public static readonly NvAPI_GPU_GetAllClocksDelegate
   322       NvAPI_GPU_GetAllClocks;
   323     public static readonly NvAPI_GPU_GetPStatesDelegate
   324       NvAPI_GPU_GetPStates;
   325     public static readonly NvAPI_GPU_GetUsagesDelegate
   326       NvAPI_GPU_GetUsages;
   327     public static readonly NvAPI_GPU_GetCoolerSettingsDelegate
   328       NvAPI_GPU_GetCoolerSettings;
   329     public static readonly NvAPI_GPU_SetCoolerLevelsDelegate
   330       NvAPI_GPU_SetCoolerLevels;
   331     public static readonly NvAPI_GPU_GetMemoryInfoDelegate
   332       NvAPI_GPU_GetMemoryInfo;
   333     public static readonly NvAPI_GetDisplayDriverVersionDelegate
   334       NvAPI_GetDisplayDriverVersion;
   335 
   336     private NVAPI() { }
   337 
   338     public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
   339       out string name) {
   340       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   341       NvStatus status;
   342       if (_NvAPI_GPU_GetFullName != null)
   343         status = _NvAPI_GPU_GetFullName(gpuHandle, builder);
   344       else
   345         status = NvStatus.FUNCTION_NOT_FOUND;
   346       name = builder.ToString();
   347       return status;
   348     }
   349 
   350     public static NvStatus NvAPI_GetInterfaceVersionString(out string version) {
   351       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   352       NvStatus status;
   353       if (_NvAPI_GetInterfaceVersionString != null)
   354         status = _NvAPI_GetInterfaceVersionString(builder);
   355       else
   356         status = NvStatus.FUNCTION_NOT_FOUND;
   357       version = builder.ToString();
   358       return status;
   359     }
   360 
   361     private static string GetDllName() {
   362       if (IntPtr.Size == 4) {
   363         return "nvapi.dll";
   364       } else {
   365         return "nvapi64.dll";
   366       }
   367     }
   368 
   369     private static void GetDelegate<T>(uint id, out T newDelegate)
   370       where T : class {
   371       IntPtr ptr = nvapi_QueryInterface(id);
   372       if (ptr != IntPtr.Zero) {
   373         newDelegate =
   374           Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
   375       } else {
   376         newDelegate = null;
   377       }
   378     }
   379 
   380     static NVAPI() {
   381       DllImportAttribute attribute = new DllImportAttribute(GetDllName());
   382       attribute.CallingConvention = CallingConvention.Cdecl;
   383       attribute.PreserveSig = true;
   384       attribute.EntryPoint = "nvapi_QueryInterface";
   385       PInvokeDelegateFactory.CreateDelegate(attribute,
   386         out nvapi_QueryInterface);
   387 
   388       try {
   389         GetDelegate(0x0150E828, out NvAPI_Initialize);
   390       } catch (DllNotFoundException) { return; } 
   391         catch (EntryPointNotFoundException) { return; } 
   392         catch (ArgumentNullException) { return; }
   393 
   394       if (NvAPI_Initialize() == NvStatus.OK) {
   395         GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings);
   396         GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName);
   397         GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
   398         GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
   399         GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
   400         GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);
   401         GetDelegate(0x1BD69F49, out NvAPI_GPU_GetAllClocks);
   402         GetDelegate(0x60DED2ED, out NvAPI_GPU_GetPStates);
   403         GetDelegate(0x189A1FDF, out NvAPI_GPU_GetUsages);
   404         GetDelegate(0xDA141340, out NvAPI_GPU_GetCoolerSettings);
   405         GetDelegate(0x891FA0AE, out NvAPI_GPU_SetCoolerLevels);
   406         GetDelegate(0x774AA982, out NvAPI_GPU_GetMemoryInfo);
   407         GetDelegate(0xF951A4D1, out NvAPI_GetDisplayDriverVersion);
   408         GetDelegate(0x01053FA5, out _NvAPI_GetInterfaceVersionString);
   409 
   410         available = true;
   411       }
   412     }
   413 
   414     public static bool IsAvailable {
   415       get { return available; }
   416     }
   417 
   418   }
   419 }