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