Fixed the ATI GPU fan control. The settings now restore correctly to default settings (previously the "manual mode" was kept on some systems).
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
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
9 http://www.mozilla.org/MPL/
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.
15 The Original Code is the Open Hardware Monitor code.
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) 2010-2011
20 the Initial Developer. All Rights Reserved.
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.
40 using System.Reflection;
41 using System.Runtime.InteropServices;
42 using System.Threading;
45 namespace OpenHardwareMonitor.Hardware {
46 internal static class Ring0 {
48 private static KernelDriver driver;
49 private static Mutex isaBusMutex;
50 private static readonly StringBuilder report = new StringBuilder();
52 private const uint OLS_TYPE = 40000;
53 private static IOControlCode
54 IOCTL_OLS_GET_REFCOUNT = new IOControlCode(OLS_TYPE, 0x801,
55 IOControlCode.Access.Any),
56 IOCTL_OLS_GET_DRIVER_VERSION = new IOControlCode(OLS_TYPE, 0x800,
57 IOControlCode.Access.Any),
58 IOCTL_OLS_READ_MSR = new IOControlCode(OLS_TYPE, 0x821,
59 IOControlCode.Access.Any),
60 IOCTL_OLS_WRITE_MSR = new IOControlCode(OLS_TYPE, 0x822,
61 IOControlCode.Access.Any),
62 IOCTL_OLS_READ_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x833,
63 IOControlCode.Access.Read),
64 IOCTL_OLS_WRITE_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x836,
65 IOControlCode.Access.Write),
66 IOCTL_OLS_READ_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x851,
67 IOControlCode.Access.Read),
68 IOCTL_OLS_WRITE_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x852,
69 IOControlCode.Access.Write),
70 IOCTL_OLS_READ_MEMORY = new IOControlCode(OLS_TYPE, 0x841,
71 IOControlCode.Access.Read);
73 private static bool ExtractDriver(string fileName) {
74 string resourceName = "OpenHardwareMonitor.Hardware." +
75 (IntPtr.Size == 4 ? "WinRing0.sys" : "WinRing0x64.sys");
78 Assembly.GetExecutingAssembly().GetManifestResourceNames();
80 for (int i = 0; i < names.Length; i++) {
81 if (names[i].Replace('\\', '.') == resourceName) {
82 using (Stream stream = Assembly.GetExecutingAssembly().
83 GetManifestResourceStream(names[i]))
85 buffer = new byte[stream.Length];
86 stream.Read(buffer, 0, buffer.Length);
94 using (FileStream target = new FileStream(fileName, FileMode.Create)) {
95 target.Write(buffer, 0, buffer.Length);
101 public static void Open() {
102 // no implementation for unix systems
103 int p = (int)Environment.OSVersion.Platform;
104 if ((p == 4) || (p == 128))
110 // clear the current report
113 driver = new KernelDriver("WinRing0_1_2_0");
116 if (!driver.IsOpen) {
117 // driver is not loaded, try to reinstall and open
120 string fileName = Path.GetTempFileName();
121 if (ExtractDriver(fileName)) {
122 if (driver.Install(fileName)) {
123 File.Delete(fileName);
126 if (!driver.IsOpen) {
128 report.AppendLine("Status: Opening driver failed");
131 report.AppendLine("Status: Installing driver \"" +
132 fileName + "\" failed" +
133 (File.Exists(fileName) ? " and file exists" : ""));
135 report.Append("Exception: " + Marshal.GetExceptionForHR(
136 Marshal.GetHRForLastWin32Error()).Message);
140 "Status: Extracting driver to \"" + fileName + "\" failed");
147 isaBusMutex = new Mutex(false, "Global\\Access_ISABUS.HTP.Method");
150 public static bool IsOpen {
151 get { return driver != null; }
154 public static void Close() {
159 driver.DeviceIOControl(IOCTL_OLS_GET_REFCOUNT, null, ref refCount);
171 public static string GetReport() {
172 if (report.Length > 0) {
173 StringBuilder r = new StringBuilder();
174 r.AppendLine("Ring0");
183 public static bool WaitIsaBusMutex(int millisecondsTimeout) {
185 return isaBusMutex.WaitOne(millisecondsTimeout, false);
186 } catch (AbandonedMutexException) { return false; }
187 catch (InvalidOperationException) { return false; }
190 public static void ReleaseIsaBusMutex() {
191 isaBusMutex.ReleaseMutex();
194 public static bool Rdmsr(uint index, out uint eax, out uint edx) {
195 if (driver == null) {
202 bool result = driver.DeviceIOControl(IOCTL_OLS_READ_MSR, index,
205 edx = (uint)((buffer >> 32) & 0xFFFFFFFF);
206 eax = (uint)(buffer & 0xFFFFFFFF);
210 public static bool RdmsrTx(uint index, out uint eax, out uint edx,
211 ulong threadAffinityMask)
213 ulong mask = ThreadAffinity.Set(threadAffinityMask);
215 bool result = Rdmsr(index, out eax, out edx);
217 ThreadAffinity.Set(mask);
221 [StructLayout(LayoutKind.Sequential, Pack = 1)]
222 private struct WrmsrInput {
223 public uint Register;
227 public static bool Wrmsr(uint index, uint eax, uint edx) {
231 WrmsrInput input = new WrmsrInput();
232 input.Register = index;
233 input.Value = ((ulong)edx << 32) | eax;
235 return driver.DeviceIOControl(IOCTL_OLS_WRITE_MSR, input);
238 public static byte ReadIoPort(uint port) {
243 driver.DeviceIOControl(IOCTL_OLS_READ_IO_PORT_BYTE, port, ref value);
245 return (byte)(value & 0xFF);
248 [StructLayout(LayoutKind.Sequential, Pack = 1)]
249 private struct WriteIoPortInput {
250 public uint PortNumber;
254 public static void WriteIoPort(uint port, byte value) {
258 WriteIoPortInput input = new WriteIoPortInput();
259 input.PortNumber = port;
262 driver.DeviceIOControl(IOCTL_OLS_WRITE_IO_PORT_BYTE, input);
265 public const uint InvalidPciAddress = 0xFFFFFFFF;
267 public static uint GetPciAddress(byte bus, byte device, byte function) {
269 (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7));
272 [StructLayout(LayoutKind.Sequential, Pack = 1)]
273 private struct ReadPciConfigInput {
274 public uint PciAddress;
275 public uint RegAddress;
278 public static bool ReadPciConfig(uint pciAddress, uint regAddress,
281 if (driver == null || (regAddress & 3) != 0) {
286 ReadPciConfigInput input = new ReadPciConfigInput();
287 input.PciAddress = pciAddress;
288 input.RegAddress = regAddress;
291 return driver.DeviceIOControl(IOCTL_OLS_READ_PCI_CONFIG, input,
295 [StructLayout(LayoutKind.Sequential, Pack = 1)]
296 private struct WritePciConfigInput {
297 public uint PciAddress;
298 public uint RegAddress;
302 public static bool WritePciConfig(uint pciAddress, uint regAddress,
305 if (driver == null || (regAddress & 3) != 0)
308 WritePciConfigInput input = new WritePciConfigInput();
309 input.PciAddress = pciAddress;
310 input.RegAddress = regAddress;
313 return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input);
316 [StructLayout(LayoutKind.Sequential, Pack = 1)]
317 private struct ReadMemoryInput {
318 public ulong address;
319 public uint unitSize;
323 public static bool ReadMemory<T>(ulong address, ref T buffer) {
324 if (driver == null) {
328 ReadMemoryInput input = new ReadMemoryInput();
329 input.address = address;
331 input.count = (uint)Marshal.SizeOf(buffer);
333 return driver.DeviceIOControl(IOCTL_OLS_READ_MEMORY, input,