Fixed Issue 387. The new implementation does not try to start a ring 0 driver that already exists, but could not be opened. It tries to delete the driver and install it new. The driver is now stored temporarily in the application folder. The driver is not correctly removed on system shutdown.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
11 using System.Globalization;
14 namespace OpenHardwareMonitor.Hardware.LPC {
15 internal class IT87XX : ISuperIO {
17 private readonly ushort address;
18 private readonly Chip chip;
19 private readonly byte version;
21 private readonly ushort gpioAddress;
22 private readonly int gpioCount;
24 private readonly ushort addressReg;
25 private readonly ushort dataReg;
27 private readonly float?[] voltages = new float?[0];
28 private readonly float?[] temperatures = new float?[0];
29 private readonly float?[] fans = new float?[0];
30 private readonly float?[] controls = new float?[0];
32 private readonly float voltageGain;
33 private readonly bool has16bitFanCounter;
36 private const byte ITE_VENDOR_ID = 0x90;
38 // Environment Controller
39 private const byte ADDRESS_REGISTER_OFFSET = 0x05;
40 private const byte DATA_REGISTER_OFFSET = 0x06;
42 // Environment Controller Registers
43 private const byte CONFIGURATION_REGISTER = 0x00;
44 private const byte TEMPERATURE_BASE_REG = 0x29;
45 private const byte VENDOR_ID_REGISTER = 0x58;
46 private const byte FAN_TACHOMETER_DIVISOR_REGISTER = 0x0B;
47 private readonly byte[] FAN_TACHOMETER_REG =
48 new byte[] { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
49 private readonly byte[] FAN_TACHOMETER_EXT_REG =
50 new byte[] { 0x18, 0x19, 0x1a, 0x81, 0x83 };
51 private const byte VOLTAGE_BASE_REG = 0x20;
53 private byte ReadByte(byte register, out bool valid) {
54 Ring0.WriteIoPort(addressReg, register);
55 byte value = Ring0.ReadIoPort(dataReg);
56 valid = register == Ring0.ReadIoPort(addressReg);
60 private bool WriteByte(byte register, byte value) {
61 Ring0.WriteIoPort(addressReg, register);
62 Ring0.WriteIoPort(dataReg, value);
63 return register == Ring0.ReadIoPort(addressReg);
66 public byte? ReadGPIO(int index) {
67 if (index >= gpioCount)
70 return Ring0.ReadIoPort((ushort)(gpioAddress + index));
73 public void WriteGPIO(int index, byte value) {
74 if (index >= gpioCount)
77 Ring0.WriteIoPort((ushort)(gpioAddress + index), value);
80 public void SetControl(int index, byte? value) { }
82 public IT87XX(Chip chip, ushort address, ushort gpioAddress, byte version) {
84 this.address = address;
86 this.version = version;
87 this.addressReg = (ushort)(address + ADDRESS_REGISTER_OFFSET);
88 this.dataReg = (ushort)(address + DATA_REGISTER_OFFSET);
89 this.gpioAddress = gpioAddress;
93 byte vendorId = ReadByte(VENDOR_ID_REGISTER, out valid);
94 if (!valid || vendorId != ITE_VENDOR_ID)
97 // Bit 0x10 of the configuration register should always be 1
98 if ((ReadByte(CONFIGURATION_REGISTER, out valid) & 0x10) == 0)
103 voltages = new float?[9];
104 temperatures = new float?[3];
105 fans = new float?[chip == Chip.IT8705F ? 3 : 5];
107 // IT8721F, IT8728F and IT8772E use a 12mV resultion ADC, all others 16mV
108 if (chip == Chip.IT8721F || chip == Chip.IT8728F || chip == Chip.IT8771E
109 || chip == Chip.IT8772E)
111 voltageGain = 0.012f;
113 voltageGain = 0.016f;
116 // older IT8705F and IT8721F revisions do not have 16-bit fan counters
117 if ((chip == Chip.IT8705F && version < 3) ||
118 (chip == Chip.IT8712F && version < 8))
120 has16bitFanCounter = false;
122 has16bitFanCounter = true;
125 // Set the number of GPIO sets
146 public Chip Chip { get { return chip; } }
147 public float?[] Voltages { get { return voltages; } }
148 public float?[] Temperatures { get { return temperatures; } }
149 public float?[] Fans { get { return fans; } }
150 public float?[] Controls { get { return controls; } }
152 public string GetReport() {
153 StringBuilder r = new StringBuilder();
155 r.AppendLine("LPC " + this.GetType().Name);
157 r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
158 r.Append("Chip Version: 0x"); r.AppendLine(
159 version.ToString("X", CultureInfo.InvariantCulture));
160 r.Append("Base Address: 0x"); r.AppendLine(
161 address.ToString("X4", CultureInfo.InvariantCulture));
162 r.Append("GPIO Address: 0x"); r.AppendLine(
163 gpioAddress.ToString("X4", CultureInfo.InvariantCulture));
166 if (!Ring0.WaitIsaBusMutex(100))
169 r.AppendLine("Environment Controller Registers");
171 r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
173 for (int i = 0; i <= 0xA; i++) {
175 r.Append((i << 4).ToString("X2", CultureInfo.InvariantCulture));
177 for (int j = 0; j <= 0xF; j++) {
180 byte value = ReadByte((byte)((i << 4) | j), out valid);
182 valid ? value.ToString("X2", CultureInfo.InvariantCulture) : "??");
188 r.AppendLine("GPIO Registers");
190 for (int i = 0; i < gpioCount; i++) {
192 r.Append(ReadGPIO(i).Value.ToString("X2",
193 CultureInfo.InvariantCulture));
198 Ring0.ReleaseIsaBusMutex();
203 public void Update() {
204 if (!Ring0.WaitIsaBusMutex(10))
207 for (int i = 0; i < voltages.Length; i++) {
211 voltageGain * ReadByte((byte)(VOLTAGE_BASE_REG + i), out valid);
221 for (int i = 0; i < temperatures.Length; i++) {
223 sbyte value = (sbyte)ReadByte(
224 (byte)(TEMPERATURE_BASE_REG + i), out valid);
228 if (value < sbyte.MaxValue && value > 0)
229 temperatures[i] = value;
231 temperatures[i] = null;
234 if (has16bitFanCounter) {
235 for (int i = 0; i < fans.Length; i++) {
237 int value = ReadByte(FAN_TACHOMETER_REG[i], out valid);
240 value |= ReadByte(FAN_TACHOMETER_EXT_REG[i], out valid) << 8;
245 fans[i] = (value < 0xffff) ? 1.35e6f / (value * 2) : 0;
251 for (int i = 0; i < fans.Length; i++) {
253 int value = ReadByte(FAN_TACHOMETER_REG[i], out valid);
259 int divisors = ReadByte(FAN_TACHOMETER_DIVISOR_REGISTER, out valid);
262 divisor = 1 << ((divisors >> (3 * i)) & 0x7);
266 fans[i] = (value < 0xff) ? 1.35e6f / (value * divisor) : 0;
273 Ring0.ReleaseIsaBusMutex();