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