Fixed a few details for the Linux GUI.
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.
38 using System.Globalization;
41 namespace OpenHardwareMonitor.Hardware.LPC {
42 internal class NCT677X : ISuperIO {
44 private readonly ushort port;
45 private readonly byte revision;
47 private readonly Chip chip;
49 private readonly float?[] voltages = new float?[9];
50 private readonly float?[] temperatures = new float?[3];
51 private readonly float?[] fans = new float?[0];
54 private const uint ADDRESS_REGISTER_OFFSET = 0x05;
55 private const uint DATA_REGISTER_OFFSET = 0x06;
56 private const byte BANK_SELECT_REGISTER = 0x4E;
58 private byte ReadByte(ushort address) {
59 byte bank = (byte)(address >> 8);
60 byte register = (byte)(address & 0xFF);
61 Ring0.WriteIoPort(port + ADDRESS_REGISTER_OFFSET, BANK_SELECT_REGISTER);
62 Ring0.WriteIoPort(port + DATA_REGISTER_OFFSET, bank);
63 Ring0.WriteIoPort(port + ADDRESS_REGISTER_OFFSET, register);
64 return Ring0.ReadIoPort(port + DATA_REGISTER_OFFSET);
68 private const ushort NUVOTON_VENDOR_ID = 0x5CA3;
70 // Hardware Monitor Registers
71 private const ushort VENDOR_ID_HIGH_REGISTER = 0x804F;
72 private const ushort VENDOR_ID_LOW_REGISTER = 0x004F;
73 private const ushort VOLTAGE_VBAT_REG = 0x0551;
75 private readonly ushort[] TEMPERATURE_REG =
76 { 0x150, 0x250, 0x27, 0x62B, 0x62C, 0x62D };
77 private readonly ushort[] TEMPERATURE_HALF_REG =
78 { 0x151, 0x251, 0, 0x62E, 0x62E, 0x62E };
79 private readonly ushort[] TEMPERATURE_SRC_REG =
80 { 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
81 private readonly int[] TEMPERATURE_HALF_BIT = { 7, 7, -1, 0, 1, 2 };
82 private readonly ushort[] VOLTAGE_REG =
83 { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551 };
84 private readonly ushort[] FAN_RPM_REG =
85 { 0x656, 0x658, 0x65A, 0x65C, 0x65E};
87 private readonly int minFanRPM;
89 private enum TemperatureSource : byte {
102 PCH_CHIP_CPU_MAX_TEMP = 13,
112 public NCT677X(Chip chip, byte revision, ushort port) {
114 this.revision = revision;
117 if (!IsNuvotonVendor())
121 case LPC.Chip.NCT6771F:
122 fans = new float?[4];
123 // min value RPM value with 16-bit fan counter
124 minFanRPM = (int)(1.35e6 / 0xFFFF);
126 case LPC.Chip.NCT6776F:
127 fans = new float?[5];
128 // min value RPM value with 13-bit fan counter
129 minFanRPM = (int)(1.35e6 / 0x1FFF);
134 private bool IsNuvotonVendor() {
135 return ((ReadByte(VENDOR_ID_HIGH_REGISTER) << 8) |
136 ReadByte(VENDOR_ID_LOW_REGISTER)) == NUVOTON_VENDOR_ID;
139 public byte? ReadGPIO(int index) {
143 public void WriteGPIO(int index, byte value) { }
145 public Chip Chip { get { return chip; } }
146 public float?[] Voltages { get { return voltages; } }
147 public float?[] Temperatures { get { return temperatures; } }
148 public float?[] Fans { get { return fans; } }
150 public void Update() {
151 if (!Ring0.WaitIsaBusMutex(10))
154 for (int i = 0; i < voltages.Length; i++) {
155 float value = 0.008f * ReadByte(VOLTAGE_REG[i]);
156 bool valid = value > 0;
158 // check if battery voltage monitor is enabled
159 if (valid && VOLTAGE_REG[i] == VOLTAGE_VBAT_REG)
160 valid = (ReadByte(0x005D) & 0x01) > 0;
162 voltages[i] = valid ? value : (float?)null;
165 for (int i = 0; i < TEMPERATURE_REG.Length; i++) {
166 int value = ((sbyte)ReadByte(TEMPERATURE_REG[i])) << 1;
167 if (TEMPERATURE_HALF_BIT[i] > 0) {
168 value |= ((ReadByte(TEMPERATURE_HALF_REG[i]) >>
169 TEMPERATURE_HALF_BIT[i]) & 0x1);
172 TemperatureSource source = (TemperatureSource)
173 ReadByte(TEMPERATURE_SRC_REG[i]);
175 float? temperature = 0.5f * value;
176 if (temperature > 125 || temperature < -55)
180 case TemperatureSource.CPUTIN: temperatures[0] = temperature; break;
181 case TemperatureSource.AUXTIN: temperatures[1] = temperature; break;
182 case TemperatureSource.SYSTIN: temperatures[2] = temperature; break;
186 for (int i = 0; i < fans.Length; i++) {
187 byte high = ReadByte(FAN_RPM_REG[i]);
188 byte low = ReadByte((ushort)(FAN_RPM_REG[i] + 1));
189 int value = (high << 8) | low;
191 fans[i] = value > minFanRPM ? value : 0;
194 Ring0.ReleaseIsaBusMutex();
197 public string GetReport() {
198 StringBuilder r = new StringBuilder();
200 r.AppendLine("LPC " + this.GetType().Name);
202 r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
203 r.Append("Chip revision: 0x");
204 r.AppendLine(revision.ToString("X", CultureInfo.InvariantCulture));
205 r.Append("Base Adress: 0x");
206 r.AppendLine(port.ToString("X4", CultureInfo.InvariantCulture));
209 if (!Ring0.WaitIsaBusMutex(100))
212 ushort[] addresses = new ushort[] {
213 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070,
214 0x100, 0x110, 0x120, 0x130, 0x140, 0x150,
215 0x200, 0x220, 0x230, 0x240, 0x250,
216 0x300, 0x320, 0x330, 0x340,
217 0x400, 0x410, 0x420, 0x440, 0x450, 0x460,
219 0x600, 0x610 ,0x620, 0x630, 0x640, 0x650, 0x660, 0x670,
220 0xA00, 0xA10, 0xA20, 0xA30, 0xA50, 0xA60, 0xA70,
221 0xB00, 0xB10, 0xB20, 0xB30, 0xB50, 0xB60, 0xB70,
222 0xC00, 0xC10, 0xC20, 0xC30, 0xC50, 0xC60, 0xC70,
223 0xD00, 0xD10, 0xD20, 0xD30, 0xD50, 0xD60,
224 0xE00, 0xE10, 0xE20, 0xE30,
225 0xF00, 0xF10, 0xF20, 0xF30};
227 r.AppendLine("Hardware Monitor Registers");
229 r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
231 foreach (ushort address in addresses) {
233 r.Append(address.ToString("X3", CultureInfo.InvariantCulture));
235 for (ushort j = 0; j <= 0xF; j++) {
237 r.Append(ReadByte((ushort)(address | j)).ToString(
238 "X2", CultureInfo.InvariantCulture));
244 Ring0.ReleaseIsaBusMutex();