Hardware/Nvidia/NVAPI.cs
author moel.mich
Thu, 16 Feb 2012 22:10:30 +0000
changeset 341 5172a92c5c20
parent 309 65a1ae21325d
child 344 3145aadca3d2
permissions -rw-r--r--
Added experimental support for ITE IT8771E super I/O chips.
     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-2012
    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     public delegate NvStatus NvAPI_GPU_GetPCIIdentifiersDelegate(
   303       NvPhysicalGpuHandle gpuHandle, out uint deviceId, out uint subSystemId, 
   304       out uint revisionId, out uint extDeviceId);
   305 
   306     private static readonly bool available;
   307     private static readonly nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
   308     private static readonly NvAPI_InitializeDelegate NvAPI_Initialize;
   309     private static readonly NvAPI_GPU_GetFullNameDelegate
   310       _NvAPI_GPU_GetFullName;
   311     private static readonly NvAPI_GetInterfaceVersionStringDelegate
   312       _NvAPI_GetInterfaceVersionString;
   313 
   314     public static readonly NvAPI_GPU_GetThermalSettingsDelegate
   315       NvAPI_GPU_GetThermalSettings;
   316     public static readonly NvAPI_EnumNvidiaDisplayHandleDelegate
   317       NvAPI_EnumNvidiaDisplayHandle;
   318     public static readonly NvAPI_GetPhysicalGPUsFromDisplayDelegate
   319       NvAPI_GetPhysicalGPUsFromDisplay;
   320     public static readonly NvAPI_EnumPhysicalGPUsDelegate
   321       NvAPI_EnumPhysicalGPUs;
   322     public static readonly NvAPI_GPU_GetTachReadingDelegate
   323       NvAPI_GPU_GetTachReading;
   324     public static readonly NvAPI_GPU_GetAllClocksDelegate
   325       NvAPI_GPU_GetAllClocks;
   326     public static readonly NvAPI_GPU_GetPStatesDelegate
   327       NvAPI_GPU_GetPStates;
   328     public static readonly NvAPI_GPU_GetUsagesDelegate
   329       NvAPI_GPU_GetUsages;
   330     public static readonly NvAPI_GPU_GetCoolerSettingsDelegate
   331       NvAPI_GPU_GetCoolerSettings;
   332     public static readonly NvAPI_GPU_SetCoolerLevelsDelegate
   333       NvAPI_GPU_SetCoolerLevels;
   334     public static readonly NvAPI_GPU_GetMemoryInfoDelegate
   335       NvAPI_GPU_GetMemoryInfo;
   336     public static readonly NvAPI_GetDisplayDriverVersionDelegate
   337       NvAPI_GetDisplayDriverVersion;
   338     public static readonly NvAPI_GPU_GetPCIIdentifiersDelegate
   339       NvAPI_GPU_GetPCIIdentifiers;
   340 
   341     private NVAPI() { }
   342 
   343     public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
   344       out string name) {
   345       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   346       NvStatus status;
   347       if (_NvAPI_GPU_GetFullName != null)
   348         status = _NvAPI_GPU_GetFullName(gpuHandle, builder);
   349       else
   350         status = NvStatus.FUNCTION_NOT_FOUND;
   351       name = builder.ToString();
   352       return status;
   353     }
   354 
   355     public static NvStatus NvAPI_GetInterfaceVersionString(out string version) {
   356       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   357       NvStatus status;
   358       if (_NvAPI_GetInterfaceVersionString != null)
   359         status = _NvAPI_GetInterfaceVersionString(builder);
   360       else
   361         status = NvStatus.FUNCTION_NOT_FOUND;
   362       version = builder.ToString();
   363       return status;
   364     }
   365 
   366     private static string GetDllName() {
   367       if (IntPtr.Size == 4) {
   368         return "nvapi.dll";
   369       } else {
   370         return "nvapi64.dll";
   371       }
   372     }
   373 
   374     private static void GetDelegate<T>(uint id, out T newDelegate)
   375       where T : class {
   376       IntPtr ptr = nvapi_QueryInterface(id);
   377       if (ptr != IntPtr.Zero) {
   378         newDelegate =
   379           Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
   380       } else {
   381         newDelegate = null;
   382       }
   383     }
   384 
   385     static NVAPI() {
   386       DllImportAttribute attribute = new DllImportAttribute(GetDllName());
   387       attribute.CallingConvention = CallingConvention.Cdecl;
   388       attribute.PreserveSig = true;
   389       attribute.EntryPoint = "nvapi_QueryInterface";
   390       PInvokeDelegateFactory.CreateDelegate(attribute,
   391         out nvapi_QueryInterface);
   392 
   393       try {
   394         GetDelegate(0x0150E828, out NvAPI_Initialize);
   395       } catch (DllNotFoundException) { return; } 
   396         catch (EntryPointNotFoundException) { return; } 
   397         catch (ArgumentNullException) { return; }
   398 
   399       if (NvAPI_Initialize() == NvStatus.OK) {
   400         GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings);
   401         GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName);
   402         GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
   403         GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
   404         GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
   405         GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);
   406         GetDelegate(0x1BD69F49, out NvAPI_GPU_GetAllClocks);
   407         GetDelegate(0x60DED2ED, out NvAPI_GPU_GetPStates);
   408         GetDelegate(0x189A1FDF, out NvAPI_GPU_GetUsages);
   409         GetDelegate(0xDA141340, out NvAPI_GPU_GetCoolerSettings);
   410         GetDelegate(0x891FA0AE, out NvAPI_GPU_SetCoolerLevels);
   411         GetDelegate(0x774AA982, out NvAPI_GPU_GetMemoryInfo);
   412         GetDelegate(0xF951A4D1, out NvAPI_GetDisplayDriverVersion);
   413         GetDelegate(0x01053FA5, out _NvAPI_GetInterfaceVersionString);
   414         GetDelegate(0x2DDFB66E, out NvAPI_GPU_GetPCIIdentifiers);
   415 
   416         available = true;
   417       }
   418     }
   419 
   420     public static bool IsAvailable {
   421       get { return available; }
   422     }
   423 
   424   }
   425 }