Release version 0.1.6. Fixed F71882 temperature reading. Added error handling for ATI GPUs (ADL). Fixed sensor events.
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) 2009-2010
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.
39 using System.Collections.Generic;
43 namespace OpenHardwareMonitor.Hardware.LPC {
44 public class W83627DHG : IHardware {
46 private byte revision;
51 private bool available = false;
52 private ushort address;
54 private List<ISensor> active = new List<ISensor>();
56 private Sensor[] temperatures;
57 private Sensor[] fans;
58 private Sensor[] voltages;
60 private float[] voltageGains;
63 private const ushort WINBOND_VENDOR_ID = 0x5CA3;
64 private const byte HIGH_BYTE = 0x80;
67 private const byte ADDRESS_REGISTER_OFFSET = 0x05;
68 private const byte DATA_REGISTER_OFFSET = 0x06;
70 // Hardware Monitor Registers
71 private const byte VOLTAGE_BASE_REG = 0x20;
72 private const byte BANK_SELECT_REGISTER = 0x04E;
73 private const byte VENDOR_ID_REGISTER = 0x4F;
74 private const byte FIRST_BANK_REGISTER = 0x50;
75 private const byte TEMPERATURE_BASE_REG = 0x50;
76 private const byte TEMPERATURE_SYS_REG = 0x27;
78 private byte[] FAN_TACHO_REG = new byte[] { 0x28, 0x29, 0x2A, 0x3F, 0x53 };
79 private byte[] FAN_TACHO_BANK = new byte[] { 0, 0, 0, 0, 5 };
80 private string[] FAN_NAME = new string[]
81 { "System", "CPU #1", "Auxiliary #1", "CPU #2", "Auxiliary #2" };
82 private byte[] FAN_BIT_REG = new byte[] { 0x47, 0x4B, 0x4C, 0x59, 0x5D };
83 private byte[] FAN_DIV_BIT0 = new byte[] { 36, 38, 30, 8, 10 };
84 private byte[] FAN_DIV_BIT1 = new byte[] { 37, 39, 31, 9, 11 };
85 private byte[] FAN_DIV_BIT2 = new byte[] { 5, 6, 7, 23, 15 };
87 private byte ReadByte(byte bank, byte register) {
88 WinRing0.WriteIoPortByte(
89 (ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER);
90 WinRing0.WriteIoPortByte(
91 (ushort)(address + DATA_REGISTER_OFFSET), bank);
92 WinRing0.WriteIoPortByte(
93 (ushort)(address + ADDRESS_REGISTER_OFFSET), register);
94 return WinRing0.ReadIoPortByte(
95 (ushort)(address + DATA_REGISTER_OFFSET));
98 public W83627DHG(byte revision, ushort address) {
99 this.revision = revision;
100 this.address = address;
104 (ushort)((ReadByte(HIGH_BYTE, VENDOR_ID_REGISTER) << 8) |
105 ReadByte(0, VENDOR_ID_REGISTER));
106 if (vendorId != WINBOND_VENDOR_ID)
109 voltageGains = new float[] { 0.008f, 1, 1, 0.016f, 1, 1, 1, 0.016f };
110 voltages = new Sensor[3];
111 voltages[0] = new Sensor("CPU VCore", 0, SensorType.Voltage, this);
112 voltages[1] = new Sensor("+3.3V", 3, SensorType.Voltage, this);
113 voltages[2] = new Sensor("Battery", 7, SensorType.Voltage, this);
115 temperatures = new Sensor[3];
116 temperatures[0] = new Sensor("CPU", 0, SensorType.Temperature, this);
117 temperatures[1] = new Sensor("Auxiliary", 1, SensorType.Temperature, this);
118 temperatures[2] = new Sensor("System", 2, SensorType.Temperature, this);
120 fans = new Sensor[FAN_NAME.Length];
121 for (int i = 0; i < FAN_NAME.Length; i++)
122 fans[i] = new Sensor(FAN_NAME[i], i, SensorType.Fan, this);
124 this.name = "Winbond W83627DHG";
125 this.icon = Utilities.EmbeddedResources.GetImage("chip.png");
129 public bool IsAvailable {
130 get { return available; }
137 public string Identifier {
138 get { return "/lpc/w83627dhg"; }
145 public ISensor[] Sensors {
146 get { return active.ToArray(); }
149 public string GetReport() {
150 StringBuilder r = new StringBuilder();
152 r.AppendLine("LPC W83627DHG");
154 r.Append("Chip revision: 0x"); r.AppendLine(revision.ToString("X"));
155 r.Append("Base Adress: 0x"); r.AppendLine(address.ToString("X4"));
157 r.AppendLine("Hardware Monitor Registers");
159 r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
161 for (int i = 0; i < 0x7; i++) {
162 r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append(" ");
163 for (int j = 0; j <= 0xF; j++) {
165 r.Append(ReadByte(0, (byte)((i << 4) | j)).ToString("X2"));
169 for (int k = 1; k <=5; k++) {
170 r.AppendLine("Bank " + k);
171 for (int i = 0x5; i < 0x6; i++) {
172 r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append(" ");
173 for (int j = 0; j <= 0xF; j++) {
175 r.Append(ReadByte((byte)(k),
176 (byte)((i << 4) | j)).ToString("X2"));
186 public void Update() {
187 foreach (Sensor sensor in voltages) {
188 if (sensor.Index < 7) {
189 int value = ReadByte(0, (byte)(VOLTAGE_BASE_REG + sensor.Index));
190 sensor.Value = voltageGains[sensor.Index] * value;
191 if (sensor.Value > 0)
192 ActivateSensor(sensor);
194 DeactivateSensor(sensor);
197 bool valid = (ReadByte(0, 0x5D) & 0x01) > 0;
199 sensor.Value = voltageGains[sensor.Index] *
201 ActivateSensor(sensor);
203 DeactivateSensor(sensor);
207 foreach (Sensor sensor in temperatures) {
209 if (sensor.Index < 2) {
210 value = ReadByte((byte)(sensor.Index + 1), TEMPERATURE_BASE_REG);
211 value = (value << 1) | ReadByte((byte)(sensor.Index + 1),
212 (byte)(TEMPERATURE_BASE_REG + 1)) >> 7;
214 value = ReadByte(0, TEMPERATURE_SYS_REG) << 1;
216 sensor.Value = value / 2.0f;
218 ActivateSensor(sensor);
220 DeactivateSensor(sensor);
224 for (int i = 0; i < FAN_BIT_REG.Length; i++)
225 bits = (bits << 8) | ReadByte(0, FAN_BIT_REG[i]);
226 foreach (Sensor sensor in fans) {
227 int count = ReadByte(FAN_TACHO_BANK[sensor.Index],
228 FAN_TACHO_REG[sensor.Index]);
229 int divisorBits = (int)(
230 (((bits >> FAN_DIV_BIT2[sensor.Index]) & 1) << 2) |
231 (((bits >> FAN_DIV_BIT1[sensor.Index]) & 1) << 1) |
232 ((bits >> FAN_DIV_BIT0[sensor.Index]) & 1));
233 int divisor = 1 << divisorBits;
234 sensor.Value = (count < 0xff) ? 1.35e6f / (count * divisor) : 0;
235 ActivateSensor(sensor);
239 private void ActivateSensor(Sensor sensor) {
240 if (!active.Contains(sensor)) {
242 if (SensorAdded != null)
247 private void DeactivateSensor(Sensor sensor) {
248 if (active.Contains(sensor)) {
249 active.Remove(sensor);
250 if (SensorRemoved != null)
251 SensorRemoved(sensor);
255 public event SensorEventHandler SensorAdded;
256 public event SensorEventHandler SensorRemoved;