Hardware/Nvidia/NVAPI.cs
author moel.mich
Tue, 09 Feb 2010 19:42:33 +0000
changeset 38 0e09d845eb00
parent 1 361e324a0ed4
child 60 0e62c377c08c
permissions -rw-r--r--
Added support for NVIDIA fan rpm. Changed NVIDIA GPU enumeration.
     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.Collections.Generic;
    40 using System.Runtime.InteropServices;
    41 using System.Text;
    42 
    43 namespace OpenHardwareMonitor.Hardware.Nvidia {
    44 
    45   public 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   public 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   public 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)]
   126   public struct NvSensor {
   127     public NvThermalController Controller;
   128     public int DefaultMinTemp;
   129     public int DefaultMaxTemp;
   130     public int CurrentTemp;
   131     public NvThermalTarget Target;     
   132   }
   133 
   134   [StructLayout(LayoutKind.Sequential)]
   135   public struct NvGPUThermalSettings {
   136     public int Version;
   137     public int Count;
   138     [MarshalAs(UnmanagedType.ByValArray, 
   139       SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)]
   140     public NvSensor[] Sensor;
   141   }
   142 
   143   [StructLayout(LayoutKind.Sequential)]
   144   public struct NvDisplayHandle {
   145     private int handle;
   146   }
   147 
   148   [StructLayout(LayoutKind.Sequential)]
   149   public struct NvPhysicalGpuHandle {
   150     private int handle;
   151   }
   152 
   153   public class NVAPI {
   154           
   155     private const int SHORT_STRING_MAX = 64;
   156 
   157     public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
   158     public const int MAX_PHYSICAL_GPUS = 64;
   159     public static readonly int GPU_THERMAL_SETTINGS_VER =
   160       Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
   161             
   162     private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id);
   163     private delegate NvStatus NvAPI_InitializeDelegate();
   164     private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(
   165       NvPhysicalGpuHandle gpuHandle, StringBuilder name);
   166 
   167     public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate(
   168       NvPhysicalGpuHandle gpuHandle, int sensorIndex, 
   169       ref NvGPUThermalSettings nvGPUThermalSettings);
   170     public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum,
   171       ref NvDisplayHandle displayHandle);
   172     public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(
   173       NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, 
   174       out int gpuCount);
   175     public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate(
   176       [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
   177     public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate(
   178       NvPhysicalGpuHandle gpuHandle, out int value);
   179 
   180     private static bool available = false;
   181     private static nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
   182     private static NvAPI_InitializeDelegate NvAPI_Initialize;
   183     private static NvAPI_GPU_GetFullNameDelegate _NvAPI_GPU_GetFullName;
   184 
   185     public static NvAPI_GPU_GetThermalSettingsDelegate 
   186       NvAPI_GPU_GetThermalSettings;
   187     public static NvAPI_EnumNvidiaDisplayHandleDelegate
   188       NvAPI_EnumNvidiaDisplayHandle;
   189     public static NvAPI_GetPhysicalGPUsFromDisplayDelegate
   190       NvAPI_GetPhysicalGPUsFromDisplay;
   191     public static NvAPI_EnumPhysicalGPUsDelegate
   192       NvAPI_EnumPhysicalGPUs;
   193     public static NvAPI_GPU_GetTachReadingDelegate
   194       NvAPI_GPU_GetTachReading;
   195 
   196     public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
   197       out string name) {
   198       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   199       NvStatus status = _NvAPI_GPU_GetFullName(gpuHandle, builder);
   200       name = builder.ToString();
   201       return status;
   202     }
   203 
   204     private static string GetDllName() {
   205       if (IntPtr.Size == 4) {
   206         return "nvapi.dll";
   207       } else {
   208         return "nvapi64.dll";
   209       }
   210     }
   211 
   212     private static void GetDelegate<T>(uint id, out T newDelegate) 
   213       where T : class 
   214     {
   215       IntPtr ptr = nvapi_QueryInterface(id);
   216       if (ptr != IntPtr.Zero) {
   217         newDelegate =
   218           Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
   219       } else {
   220         newDelegate = null;
   221       }
   222     }
   223 
   224     static NVAPI() { 
   225       DllImportAttribute attribute = new DllImportAttribute(GetDllName());
   226       attribute.CallingConvention = CallingConvention.Cdecl;
   227       attribute.PreserveSig = true;
   228       attribute.EntryPoint = "nvapi_QueryInterface";
   229       PInvokeDelegateFactory.CreateDelegate(attribute,
   230         out nvapi_QueryInterface);
   231 
   232       try {
   233         GetDelegate(0x0150E828, out NvAPI_Initialize);
   234       } catch (DllNotFoundException) { return; } 
   235         catch (ArgumentNullException) { return; }
   236 
   237       if (NvAPI_Initialize() == NvStatus.OK) {
   238         GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings);
   239         GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName);
   240         GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
   241         GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
   242         GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
   243         GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);        
   244         available = true;
   245       }
   246     }
   247 
   248     public static bool IsAvailable {
   249       get { return available; }
   250     }
   251 
   252   }
   253 }