moel@1: /* moel@1: moel@1: Version: MPL 1.1/GPL 2.0/LGPL 2.1 moel@1: moel@1: The contents of this file are subject to the Mozilla Public License Version moel@1: 1.1 (the "License"); you may not use this file except in compliance with moel@1: the License. You may obtain a copy of the License at moel@1: moel@1: http://www.mozilla.org/MPL/ moel@1: moel@1: Software distributed under the License is distributed on an "AS IS" basis, moel@1: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License moel@1: for the specific language governing rights and limitations under the License. moel@1: moel@1: The Original Code is the Open Hardware Monitor code. moel@1: moel@1: The Initial Developer of the Original Code is moel@1: Michael Möller . moel@1: Portions created by the Initial Developer are Copyright (C) 2009-2010 moel@1: the Initial Developer. All Rights Reserved. moel@1: moel@1: Contributor(s): moel@1: moel@1: Alternatively, the contents of this file may be used under the terms of moel@1: either the GNU General Public License Version 2 or later (the "GPL"), or moel@1: the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), moel@1: in which case the provisions of the GPL or the LGPL are applicable instead moel@1: of those above. If you wish to allow use of your version of this file only moel@1: under the terms of either the GPL or the LGPL, and not to allow others to moel@1: use your version of this file under the terms of the MPL, indicate your moel@1: decision by deleting the provisions above and replace them with the notice moel@1: and other provisions required by the GPL or the LGPL. If you do not delete moel@1: the provisions above, a recipient may use your version of this file under moel@1: the terms of any one of the MPL, the GPL or the LGPL. moel@1: moel@1: */ moel@1: moel@1: using System; moel@1: using System.Collections.Generic; moel@1: using System.Runtime.InteropServices; moel@1: using System.Text; moel@1: moel@1: namespace OpenHardwareMonitor.Hardware.Nvidia { moel@1: moel@1: public enum NvStatus { moel@1: OK = 0, moel@1: ERROR = -1, moel@1: LIBRARY_NOT_FOUND = -2, moel@1: NO_IMPLEMENTATION = -3, moel@1: API_NOT_INTIALIZED = -4, moel@1: INVALID_ARGUMENT = -5, moel@1: NVIDIA_DEVICE_NOT_FOUND = -6, moel@1: END_ENUMERATION = -7, moel@1: INVALID_HANDLE = -8, moel@1: INCOMPATIBLE_STRUCT_VERSION = -9, moel@1: HANDLE_INVALIDATED = -10, moel@1: OPENGL_CONTEXT_NOT_CURRENT = -11, moel@1: NO_GL_EXPERT = -12, moel@1: INSTRUMENTATION_DISABLED = -13, moel@1: EXPECTED_LOGICAL_GPU_HANDLE = -100, moel@1: EXPECTED_PHYSICAL_GPU_HANDLE = -101, moel@1: EXPECTED_DISPLAY_HANDLE = -102, moel@1: INVALID_COMBINATION = -103, moel@1: NOT_SUPPORTED = -104, moel@1: PORTID_NOT_FOUND = -105, moel@1: EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106, moel@1: INVALID_PERF_LEVEL = -107, moel@1: DEVICE_BUSY = -108, moel@1: NV_PERSIST_FILE_NOT_FOUND = -109, moel@1: PERSIST_DATA_NOT_FOUND = -110, moel@1: EXPECTED_TV_DISPLAY = -111, moel@1: EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112, moel@1: NO_ACTIVE_SLI_TOPOLOGY = -113, moel@1: SLI_RENDERING_MODE_NOTALLOWED = -114, moel@1: EXPECTED_DIGITAL_FLAT_PANEL = -115, moel@1: ARGUMENT_EXCEED_MAX_SIZE = -116, moel@1: DEVICE_SWITCHING_NOT_ALLOWED = -117, moel@1: TESTING_CLOCKS_NOT_SUPPORTED = -118, moel@1: UNKNOWN_UNDERSCAN_CONFIG = -119, moel@1: TIMEOUT_RECONFIGURING_GPU_TOPO = -120, moel@1: DATA_NOT_FOUND = -121, moel@1: EXPECTED_ANALOG_DISPLAY = -122, moel@1: NO_VIDLINK = -123, moel@1: REQUIRES_REBOOT = -124, moel@1: INVALID_HYBRID_MODE = -125, moel@1: MIXED_TARGET_TYPES = -126, moel@1: SYSWOW64_NOT_SUPPORTED = -127, moel@1: IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128, moel@1: REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129, moel@1: OUT_OF_MEMORY = -130, moel@1: WAS_STILL_DRAWING = -131, moel@1: FILE_NOT_FOUND = -132, moel@1: TOO_MANY_UNIQUE_STATE_OBJECTS = -133, moel@1: INVALID_CALL = -134, moel@1: D3D10_1_LIBRARY_NOT_FOUND = -135, moel@1: FUNCTION_NOT_FOUND = -136 moel@1: } moel@1: moel@1: public enum NvThermalController { moel@1: NONE = 0, moel@1: GPU_INTERNAL, moel@1: ADM1032, moel@1: MAX6649, moel@1: MAX1617, moel@1: LM99, moel@1: LM89, moel@1: LM64, moel@1: ADT7473, moel@1: SBMAX6649, moel@1: VBIOSEVT, moel@1: OS, moel@1: UNKNOWN = -1, moel@1: } moel@1: moel@1: public enum NvThermalTarget { moel@1: NONE = 0, moel@1: GPU = 1, moel@1: MEMORY = 2, moel@1: POWER_SUPPLY = 4, moel@1: BOARD = 8, moel@1: ALL = 15, moel@1: UNKNOWN = -1 moel@1: }; moel@1: moel@61: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@1: public struct NvSensor { moel@1: public NvThermalController Controller; moel@1: public int DefaultMinTemp; moel@1: public int DefaultMaxTemp; moel@1: public int CurrentTemp; moel@1: public NvThermalTarget Target; moel@1: } moel@1: moel@61: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@1: public struct NvGPUThermalSettings { moel@1: public int Version; moel@1: public int Count; moel@1: [MarshalAs(UnmanagedType.ByValArray, moel@1: SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)] moel@1: public NvSensor[] Sensor; moel@1: } moel@1: moel@61: [StructLayout(LayoutKind.Sequential)] moel@1: public struct NvDisplayHandle { moel@61: private IntPtr ptr; moel@1: } moel@1: moel@61: [StructLayout(LayoutKind.Sequential)] moel@1: public struct NvPhysicalGpuHandle { moel@61: private IntPtr ptr; moel@1: } moel@1: moel@1: public class NVAPI { moel@1: moel@1: private const int SHORT_STRING_MAX = 64; moel@1: moel@1: public const int MAX_THERMAL_SENSORS_PER_GPU = 3; moel@1: public const int MAX_PHYSICAL_GPUS = 64; moel@1: public static readonly int GPU_THERMAL_SETTINGS_VER = moel@1: Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000; moel@1: moel@1: private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id); moel@1: private delegate NvStatus NvAPI_InitializeDelegate(); moel@1: private delegate NvStatus NvAPI_GPU_GetFullNameDelegate( moel@1: NvPhysicalGpuHandle gpuHandle, StringBuilder name); moel@1: moel@1: public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate( moel@1: NvPhysicalGpuHandle gpuHandle, int sensorIndex, moel@1: ref NvGPUThermalSettings nvGPUThermalSettings); moel@1: public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum, moel@1: ref NvDisplayHandle displayHandle); moel@1: public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate( moel@1: NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, moel@1: out int gpuCount); moel@1: public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate( moel@1: [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount); moel@38: public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate( moel@38: NvPhysicalGpuHandle gpuHandle, out int value); moel@1: moel@1: private static bool available = false; moel@1: private static nvapi_QueryInterfaceDelegate nvapi_QueryInterface; moel@1: private static NvAPI_InitializeDelegate NvAPI_Initialize; moel@1: private static NvAPI_GPU_GetFullNameDelegate _NvAPI_GPU_GetFullName; moel@1: moel@1: public static NvAPI_GPU_GetThermalSettingsDelegate moel@1: NvAPI_GPU_GetThermalSettings; moel@1: public static NvAPI_EnumNvidiaDisplayHandleDelegate moel@1: NvAPI_EnumNvidiaDisplayHandle; moel@1: public static NvAPI_GetPhysicalGPUsFromDisplayDelegate moel@1: NvAPI_GetPhysicalGPUsFromDisplay; moel@1: public static NvAPI_EnumPhysicalGPUsDelegate moel@1: NvAPI_EnumPhysicalGPUs; moel@38: public static NvAPI_GPU_GetTachReadingDelegate moel@38: NvAPI_GPU_GetTachReading; moel@1: moel@1: public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle, moel@1: out string name) { moel@1: StringBuilder builder = new StringBuilder(SHORT_STRING_MAX); moel@101: NvStatus status; moel@101: if (_NvAPI_GPU_GetFullName != null) moel@101: status = _NvAPI_GPU_GetFullName(gpuHandle, builder); moel@101: else moel@101: status = NvStatus.FUNCTION_NOT_FOUND; moel@1: name = builder.ToString(); moel@1: return status; moel@1: } moel@1: moel@1: private static string GetDllName() { moel@1: if (IntPtr.Size == 4) { moel@1: return "nvapi.dll"; moel@1: } else { moel@1: return "nvapi64.dll"; moel@1: } moel@1: } moel@1: moel@1: private static void GetDelegate(uint id, out T newDelegate) moel@1: where T : class moel@1: { moel@1: IntPtr ptr = nvapi_QueryInterface(id); moel@38: if (ptr != IntPtr.Zero) { moel@38: newDelegate = moel@38: Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T; moel@38: } else { moel@38: newDelegate = null; moel@38: } moel@1: } moel@1: moel@1: static NVAPI() { moel@1: DllImportAttribute attribute = new DllImportAttribute(GetDllName()); moel@1: attribute.CallingConvention = CallingConvention.Cdecl; moel@1: attribute.PreserveSig = true; moel@1: attribute.EntryPoint = "nvapi_QueryInterface"; moel@1: PInvokeDelegateFactory.CreateDelegate(attribute, moel@1: out nvapi_QueryInterface); moel@1: moel@1: try { moel@1: GetDelegate(0x0150E828, out NvAPI_Initialize); moel@1: } catch (DllNotFoundException) { return; } moel@121: catch (EntryPointNotFoundException) { return; } moel@1: catch (ArgumentNullException) { return; } moel@1: moel@1: if (NvAPI_Initialize() == NvStatus.OK) { moel@1: GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings); moel@1: GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName); moel@1: GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle); moel@1: GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay); moel@1: GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs); moel@38: GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading); moel@1: available = true; moel@1: } moel@1: } moel@1: moel@1: public static bool IsAvailable { moel@1: get { return available; } moel@1: } moel@1: moel@1: } moel@1: }