Added experimental support for ITE IT8771E super I/O chips.
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.Security.AccessControl;
43 using System.Threading;
46 namespace OpenHardwareMonitor.Hardware {
47 internal static class Ring0 {
49 private static KernelDriver driver;
50 private static string fileName;
51 private static Mutex isaBusMutex;
52 private static readonly StringBuilder report = new StringBuilder();
54 private const uint OLS_TYPE = 40000;
55 private static IOControlCode
56 IOCTL_OLS_GET_REFCOUNT = new IOControlCode(OLS_TYPE, 0x801,
57 IOControlCode.Access.Any),
58 IOCTL_OLS_GET_DRIVER_VERSION = new IOControlCode(OLS_TYPE, 0x800,
59 IOControlCode.Access.Any),
60 IOCTL_OLS_READ_MSR = new IOControlCode(OLS_TYPE, 0x821,
61 IOControlCode.Access.Any),
62 IOCTL_OLS_WRITE_MSR = new IOControlCode(OLS_TYPE, 0x822,
63 IOControlCode.Access.Any),
64 IOCTL_OLS_READ_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x833,
65 IOControlCode.Access.Read),
66 IOCTL_OLS_WRITE_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x836,
67 IOControlCode.Access.Write),
68 IOCTL_OLS_READ_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x851,
69 IOControlCode.Access.Read),
70 IOCTL_OLS_WRITE_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x852,
71 IOControlCode.Access.Write),
72 IOCTL_OLS_READ_MEMORY = new IOControlCode(OLS_TYPE, 0x841,
73 IOControlCode.Access.Read);
75 private static string GetTempFileName() {
77 // try to get a file in the temporary folder
79 return Path.GetTempFileName();
80 } catch (IOException) {
83 catch (UnauthorizedAccessException) {
84 // we do not have the right to create a file in the temp folder
86 catch (NotSupportedException) {
87 // invalid path format of the TMP system environment variable
90 // if this failed, we try to create one in the application folder
91 string fileName = Path.ChangeExtension(
92 Assembly.GetExecutingAssembly().Location, ".sys");
94 using (FileStream stream = File.Create(fileName)) {
97 } catch (IOException) { }
98 catch (UnauthorizedAccessException) { }
103 private static bool ExtractDriver(string fileName) {
104 string resourceName = "OpenHardwareMonitor.Hardware." +
105 (IntPtr.Size == 4 ? "WinRing0.sys" : "WinRing0x64.sys");
108 Assembly.GetExecutingAssembly().GetManifestResourceNames();
109 byte[] buffer = null;
110 for (int i = 0; i < names.Length; i++) {
111 if (names[i].Replace('\\', '.') == resourceName) {
112 using (Stream stream = Assembly.GetExecutingAssembly().
113 GetManifestResourceStream(names[i]))
115 buffer = new byte[stream.Length];
116 stream.Read(buffer, 0, buffer.Length);
125 using (FileStream target = new FileStream(fileName, FileMode.Create)) {
126 target.Write(buffer, 0, buffer.Length);
128 } catch (IOException) {
129 // for example there is not enough space on the disk
136 public static void Open() {
137 // no implementation for unix systems
138 int p = (int)Environment.OSVersion.Platform;
139 if ((p == 4) || (p == 128))
145 // clear the current report
148 driver = new KernelDriver("WinRing0_1_2_0");
151 if (!driver.IsOpen) {
152 // driver is not loaded, try to reinstall and open
155 fileName = GetTempFileName();
156 if (fileName != null && ExtractDriver(fileName)) {
157 if (driver.Install(fileName)) {
160 if (!driver.IsOpen) {
162 report.AppendLine("Status: Opening driver failed");
165 report.AppendLine("Status: Installing driver \"" +
166 fileName + "\" failed" +
167 (File.Exists(fileName) ? " and file exists" : ""));
169 report.Append("Exception: " + Marshal.GetExceptionForHR(
170 Marshal.GetHRForLastWin32Error()).Message);
173 report.AppendLine("Status: Extracting driver failed");
177 // try to delte the driver file
178 if (File.Exists(fileName))
179 File.Delete(fileName);
181 } catch (IOException) { }
182 catch (UnauthorizedAccessException) { }
188 string mutexName = "Global\\Access_ISABUS.HTP.Method";
190 isaBusMutex = new Mutex(false, mutexName);
191 } catch (UnauthorizedAccessException) {
193 isaBusMutex = Mutex.OpenExisting(mutexName, MutexRights.Synchronize);
198 public static bool IsOpen {
199 get { return driver != null; }
202 public static void Close() {
207 driver.DeviceIOControl(IOCTL_OLS_GET_REFCOUNT, null, ref refCount);
216 if (isaBusMutex != null) {
221 // try to delete temporary driver file again if failed during open
222 if (fileName != null && File.Exists(fileName)) {
224 File.Delete(fileName);
226 } catch (IOException) { }
227 catch (UnauthorizedAccessException) { }
231 public static string GetReport() {
232 if (report.Length > 0) {
233 StringBuilder r = new StringBuilder();
234 r.AppendLine("Ring0");
243 public static bool WaitIsaBusMutex(int millisecondsTimeout) {
244 if (isaBusMutex == null)
247 return isaBusMutex.WaitOne(millisecondsTimeout, false);
248 } catch (AbandonedMutexException) { return false; }
249 catch (InvalidOperationException) { return false; }
252 public static void ReleaseIsaBusMutex() {
253 if (isaBusMutex == null)
255 isaBusMutex.ReleaseMutex();
258 public static bool Rdmsr(uint index, out uint eax, out uint edx) {
259 if (driver == null) {
266 bool result = driver.DeviceIOControl(IOCTL_OLS_READ_MSR, index,
269 edx = (uint)((buffer >> 32) & 0xFFFFFFFF);
270 eax = (uint)(buffer & 0xFFFFFFFF);
274 public static bool RdmsrTx(uint index, out uint eax, out uint edx,
275 ulong threadAffinityMask)
277 ulong mask = ThreadAffinity.Set(threadAffinityMask);
279 bool result = Rdmsr(index, out eax, out edx);
281 ThreadAffinity.Set(mask);
285 [StructLayout(LayoutKind.Sequential, Pack = 1)]
286 private struct WrmsrInput {
287 public uint Register;
291 public static bool Wrmsr(uint index, uint eax, uint edx) {
295 WrmsrInput input = new WrmsrInput();
296 input.Register = index;
297 input.Value = ((ulong)edx << 32) | eax;
299 return driver.DeviceIOControl(IOCTL_OLS_WRITE_MSR, input);
302 public static byte ReadIoPort(uint port) {
307 driver.DeviceIOControl(IOCTL_OLS_READ_IO_PORT_BYTE, port, ref value);
309 return (byte)(value & 0xFF);
312 [StructLayout(LayoutKind.Sequential, Pack = 1)]
313 private struct WriteIoPortInput {
314 public uint PortNumber;
318 public static void WriteIoPort(uint port, byte value) {
322 WriteIoPortInput input = new WriteIoPortInput();
323 input.PortNumber = port;
326 driver.DeviceIOControl(IOCTL_OLS_WRITE_IO_PORT_BYTE, input);
329 public const uint InvalidPciAddress = 0xFFFFFFFF;
331 public static uint GetPciAddress(byte bus, byte device, byte function) {
333 (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7));
336 [StructLayout(LayoutKind.Sequential, Pack = 1)]
337 private struct ReadPciConfigInput {
338 public uint PciAddress;
339 public uint RegAddress;
342 public static bool ReadPciConfig(uint pciAddress, uint regAddress,
345 if (driver == null || (regAddress & 3) != 0) {
350 ReadPciConfigInput input = new ReadPciConfigInput();
351 input.PciAddress = pciAddress;
352 input.RegAddress = regAddress;
355 return driver.DeviceIOControl(IOCTL_OLS_READ_PCI_CONFIG, input,
359 [StructLayout(LayoutKind.Sequential, Pack = 1)]
360 private struct WritePciConfigInput {
361 public uint PciAddress;
362 public uint RegAddress;
366 public static bool WritePciConfig(uint pciAddress, uint regAddress,
369 if (driver == null || (regAddress & 3) != 0)
372 WritePciConfigInput input = new WritePciConfigInput();
373 input.PciAddress = pciAddress;
374 input.RegAddress = regAddress;
377 return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input);
380 [StructLayout(LayoutKind.Sequential, Pack = 1)]
381 private struct ReadMemoryInput {
382 public ulong address;
383 public uint unitSize;
387 public static bool ReadMemory<T>(ulong address, ref T buffer) {
388 if (driver == null) {
392 ReadMemoryInput input = new ReadMemoryInput();
393 input.address = address;
395 input.count = (uint)Marshal.SizeOf(buffer);
397 return driver.DeviceIOControl(IOCTL_OLS_READ_MEMORY, input,