Hardware/Nvidia/NVAPI.cs
author moel.mich
Mon, 22 Feb 2010 09:57:02 +0000
changeset 60 0e62c377c08c
parent 38 0e09d845eb00
child 61 cffcbf8a1401
permissions -rw-r--r--
Fintek super I/O chips with base address 0x..5 are detected now as well. Set Pack = 1 for NVAPI struct interop (should fix GPU enumeration).
moel@1
     1
/*
moel@1
     2
  
moel@1
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1
     4
moel@1
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@1
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@1
     7
  the License. You may obtain a copy of the License at
moel@1
     8
 
moel@1
     9
  http://www.mozilla.org/MPL/
moel@1
    10
moel@1
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@1
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1
    13
  for the specific language governing rights and limitations under the License.
moel@1
    14
moel@1
    15
  The Original Code is the Open Hardware Monitor code.
moel@1
    16
moel@1
    17
  The Initial Developer of the Original Code is 
moel@1
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@1
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
moel@1
    22
  Contributor(s):
moel@1
    23
moel@1
    24
  Alternatively, the contents of this file may be used under the terms of
moel@1
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    28
  of those above. If you wish to allow use of your version of this file only
moel@1
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    30
  use your version of this file under the terms of the MPL, indicate your
moel@1
    31
  decision by deleting the provisions above and replace them with the notice
moel@1
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    33
  the provisions above, a recipient may use your version of this file under
moel@1
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    35
 
moel@1
    36
*/
moel@1
    37
moel@1
    38
using System;
moel@1
    39
using System.Collections.Generic;
moel@1
    40
using System.Runtime.InteropServices;
moel@1
    41
using System.Text;
moel@1
    42
moel@1
    43
namespace OpenHardwareMonitor.Hardware.Nvidia {
moel@1
    44
moel@1
    45
  public enum NvStatus {
moel@1
    46
    OK = 0,
moel@1
    47
    ERROR = -1,
moel@1
    48
    LIBRARY_NOT_FOUND = -2,
moel@1
    49
    NO_IMPLEMENTATION = -3,
moel@1
    50
    API_NOT_INTIALIZED = -4,
moel@1
    51
    INVALID_ARGUMENT = -5,
moel@1
    52
    NVIDIA_DEVICE_NOT_FOUND = -6,
moel@1
    53
    END_ENUMERATION = -7,
moel@1
    54
    INVALID_HANDLE = -8,
moel@1
    55
    INCOMPATIBLE_STRUCT_VERSION = -9,
moel@1
    56
    HANDLE_INVALIDATED = -10,
moel@1
    57
    OPENGL_CONTEXT_NOT_CURRENT = -11,
moel@1
    58
    NO_GL_EXPERT = -12,
moel@1
    59
    INSTRUMENTATION_DISABLED = -13,
moel@1
    60
    EXPECTED_LOGICAL_GPU_HANDLE = -100,
moel@1
    61
    EXPECTED_PHYSICAL_GPU_HANDLE = -101,
moel@1
    62
    EXPECTED_DISPLAY_HANDLE = -102,
moel@1
    63
    INVALID_COMBINATION = -103,
moel@1
    64
    NOT_SUPPORTED = -104,
moel@1
    65
    PORTID_NOT_FOUND = -105,
moel@1
    66
    EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106,
moel@1
    67
    INVALID_PERF_LEVEL = -107,
moel@1
    68
    DEVICE_BUSY = -108,
moel@1
    69
    NV_PERSIST_FILE_NOT_FOUND = -109,
moel@1
    70
    PERSIST_DATA_NOT_FOUND = -110,
moel@1
    71
    EXPECTED_TV_DISPLAY = -111,
moel@1
    72
    EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112,
moel@1
    73
    NO_ACTIVE_SLI_TOPOLOGY = -113,
moel@1
    74
    SLI_RENDERING_MODE_NOTALLOWED = -114,
moel@1
    75
    EXPECTED_DIGITAL_FLAT_PANEL = -115,
moel@1
    76
    ARGUMENT_EXCEED_MAX_SIZE = -116,
moel@1
    77
    DEVICE_SWITCHING_NOT_ALLOWED = -117,
moel@1
    78
    TESTING_CLOCKS_NOT_SUPPORTED = -118,
moel@1
    79
    UNKNOWN_UNDERSCAN_CONFIG = -119,
moel@1
    80
    TIMEOUT_RECONFIGURING_GPU_TOPO = -120,
moel@1
    81
    DATA_NOT_FOUND = -121,
moel@1
    82
    EXPECTED_ANALOG_DISPLAY = -122,
moel@1
    83
    NO_VIDLINK = -123,
moel@1
    84
    REQUIRES_REBOOT = -124,
moel@1
    85
    INVALID_HYBRID_MODE = -125,
moel@1
    86
    MIXED_TARGET_TYPES = -126,
moel@1
    87
    SYSWOW64_NOT_SUPPORTED = -127,
moel@1
    88
    IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128,
moel@1
    89
    REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129,
moel@1
    90
    OUT_OF_MEMORY = -130,
moel@1
    91
    WAS_STILL_DRAWING = -131,
moel@1
    92
    FILE_NOT_FOUND = -132,
moel@1
    93
    TOO_MANY_UNIQUE_STATE_OBJECTS = -133,
moel@1
    94
    INVALID_CALL = -134,
moel@1
    95
    D3D10_1_LIBRARY_NOT_FOUND = -135,
moel@1
    96
    FUNCTION_NOT_FOUND = -136
moel@1
    97
  }  
moel@1
    98
moel@1
    99
  public enum NvThermalController {
moel@1
   100
    NONE = 0,
moel@1
   101
    GPU_INTERNAL,  
moel@1
   102
    ADM1032,
moel@1
   103
    MAX6649,       
moel@1
   104
    MAX1617,      
moel@1
   105
    LM99,      
moel@1
   106
    LM89,         
moel@1
   107
    LM64,         
moel@1
   108
    ADT7473,
moel@1
   109
    SBMAX6649,
moel@1
   110
    VBIOSEVT,  
moel@1
   111
    OS,    
moel@1
   112
    UNKNOWN = -1,
moel@1
   113
  } 
moel@1
   114
moel@1
   115
  public enum NvThermalTarget {
moel@1
   116
    NONE = 0,
moel@1
   117
    GPU = 1,
moel@1
   118
    MEMORY = 2,
moel@1
   119
    POWER_SUPPLY = 4,
moel@1
   120
    BOARD = 8,
moel@1
   121
    ALL = 15,
moel@1
   122
    UNKNOWN = -1
moel@1
   123
  };
moel@1
   124
moel@60
   125
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@1
   126
  public struct NvSensor {
moel@1
   127
    public NvThermalController Controller;
moel@1
   128
    public int DefaultMinTemp;
moel@1
   129
    public int DefaultMaxTemp;
moel@1
   130
    public int CurrentTemp;
moel@1
   131
    public NvThermalTarget Target;     
moel@1
   132
  }
moel@1
   133
moel@60
   134
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@1
   135
  public struct NvGPUThermalSettings {
moel@1
   136
    public int Version;
moel@1
   137
    public int Count;
moel@1
   138
    [MarshalAs(UnmanagedType.ByValArray, 
moel@1
   139
      SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)]
moel@1
   140
    public NvSensor[] Sensor;
moel@1
   141
  }
moel@1
   142
moel@60
   143
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@1
   144
  public struct NvDisplayHandle {
moel@1
   145
    private int handle;
moel@1
   146
  }
moel@1
   147
moel@60
   148
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@1
   149
  public struct NvPhysicalGpuHandle {
moel@1
   150
    private int handle;
moel@1
   151
  }
moel@1
   152
moel@1
   153
  public class NVAPI {
moel@1
   154
          
moel@1
   155
    private const int SHORT_STRING_MAX = 64;
moel@1
   156
moel@1
   157
    public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
moel@1
   158
    public const int MAX_PHYSICAL_GPUS = 64;
moel@1
   159
    public static readonly int GPU_THERMAL_SETTINGS_VER =
moel@1
   160
      Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
moel@1
   161
            
moel@1
   162
    private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id);
moel@1
   163
    private delegate NvStatus NvAPI_InitializeDelegate();
moel@1
   164
    private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(
moel@1
   165
      NvPhysicalGpuHandle gpuHandle, StringBuilder name);
moel@1
   166
moel@1
   167
    public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate(
moel@1
   168
      NvPhysicalGpuHandle gpuHandle, int sensorIndex, 
moel@1
   169
      ref NvGPUThermalSettings nvGPUThermalSettings);
moel@1
   170
    public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum,
moel@1
   171
      ref NvDisplayHandle displayHandle);
moel@1
   172
    public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(
moel@1
   173
      NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, 
moel@1
   174
      out int gpuCount);
moel@1
   175
    public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate(
moel@1
   176
      [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
moel@38
   177
    public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate(
moel@38
   178
      NvPhysicalGpuHandle gpuHandle, out int value);
moel@1
   179
moel@1
   180
    private static bool available = false;
moel@1
   181
    private static nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
moel@1
   182
    private static NvAPI_InitializeDelegate NvAPI_Initialize;
moel@1
   183
    private static NvAPI_GPU_GetFullNameDelegate _NvAPI_GPU_GetFullName;
moel@1
   184
moel@1
   185
    public static NvAPI_GPU_GetThermalSettingsDelegate 
moel@1
   186
      NvAPI_GPU_GetThermalSettings;
moel@1
   187
    public static NvAPI_EnumNvidiaDisplayHandleDelegate
moel@1
   188
      NvAPI_EnumNvidiaDisplayHandle;
moel@1
   189
    public static NvAPI_GetPhysicalGPUsFromDisplayDelegate
moel@1
   190
      NvAPI_GetPhysicalGPUsFromDisplay;
moel@1
   191
    public static NvAPI_EnumPhysicalGPUsDelegate
moel@1
   192
      NvAPI_EnumPhysicalGPUs;
moel@38
   193
    public static NvAPI_GPU_GetTachReadingDelegate
moel@38
   194
      NvAPI_GPU_GetTachReading;
moel@1
   195
moel@1
   196
    public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
moel@1
   197
      out string name) {
moel@1
   198
      StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
moel@1
   199
      NvStatus status = _NvAPI_GPU_GetFullName(gpuHandle, builder);
moel@1
   200
      name = builder.ToString();
moel@1
   201
      return status;
moel@1
   202
    }
moel@1
   203
moel@1
   204
    private static string GetDllName() {
moel@1
   205
      if (IntPtr.Size == 4) {
moel@1
   206
        return "nvapi.dll";
moel@1
   207
      } else {
moel@1
   208
        return "nvapi64.dll";
moel@1
   209
      }
moel@1
   210
    }
moel@1
   211
moel@1
   212
    private static void GetDelegate<T>(uint id, out T newDelegate) 
moel@1
   213
      where T : class 
moel@1
   214
    {
moel@1
   215
      IntPtr ptr = nvapi_QueryInterface(id);
moel@38
   216
      if (ptr != IntPtr.Zero) {
moel@38
   217
        newDelegate =
moel@38
   218
          Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
moel@38
   219
      } else {
moel@38
   220
        newDelegate = null;
moel@38
   221
      }
moel@1
   222
    }
moel@1
   223
moel@1
   224
    static NVAPI() { 
moel@1
   225
      DllImportAttribute attribute = new DllImportAttribute(GetDllName());
moel@1
   226
      attribute.CallingConvention = CallingConvention.Cdecl;
moel@1
   227
      attribute.PreserveSig = true;
moel@1
   228
      attribute.EntryPoint = "nvapi_QueryInterface";
moel@1
   229
      PInvokeDelegateFactory.CreateDelegate(attribute,
moel@1
   230
        out nvapi_QueryInterface);
moel@1
   231
moel@1
   232
      try {
moel@1
   233
        GetDelegate(0x0150E828, out NvAPI_Initialize);
moel@1
   234
      } catch (DllNotFoundException) { return; } 
moel@1
   235
        catch (ArgumentNullException) { return; }
moel@1
   236
moel@1
   237
      if (NvAPI_Initialize() == NvStatus.OK) {
moel@1
   238
        GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings);
moel@1
   239
        GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName);
moel@1
   240
        GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
moel@1
   241
        GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
moel@1
   242
        GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
moel@38
   243
        GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);        
moel@1
   244
        available = true;
moel@1
   245
      }
moel@1
   246
    }
moel@1
   247
moel@1
   248
    public static bool IsAvailable {
moel@1
   249
      get { return available; }
moel@1
   250
    }
moel@1
   251
moel@1
   252
  }
moel@1
   253
}