1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/Hardware/LPC/W836XX.cs Mon Feb 08 20:18:25 2010 +0000
1.3 @@ -0,0 +1,239 @@
1.4 +/*
1.5 +
1.6 + Version: MPL 1.1/GPL 2.0/LGPL 2.1
1.7 +
1.8 + The contents of this file are subject to the Mozilla Public License Version
1.9 + 1.1 (the "License"); you may not use this file except in compliance with
1.10 + the License. You may obtain a copy of the License at
1.11 +
1.12 + http://www.mozilla.org/MPL/
1.13 +
1.14 + Software distributed under the License is distributed on an "AS IS" basis,
1.15 + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1.16 + for the specific language governing rights and limitations under the License.
1.17 +
1.18 + The Original Code is the Open Hardware Monitor code.
1.19 +
1.20 + The Initial Developer of the Original Code is
1.21 + Michael Möller <m.moeller@gmx.ch>.
1.22 + Portions created by the Initial Developer are Copyright (C) 2009-2010
1.23 + the Initial Developer. All Rights Reserved.
1.24 +
1.25 + Contributor(s):
1.26 +
1.27 + Alternatively, the contents of this file may be used under the terms of
1.28 + either the GNU General Public License Version 2 or later (the "GPL"), or
1.29 + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1.30 + in which case the provisions of the GPL or the LGPL are applicable instead
1.31 + of those above. If you wish to allow use of your version of this file only
1.32 + under the terms of either the GPL or the LGPL, and not to allow others to
1.33 + use your version of this file under the terms of the MPL, indicate your
1.34 + decision by deleting the provisions above and replace them with the notice
1.35 + and other provisions required by the GPL or the LGPL. If you do not delete
1.36 + the provisions above, a recipient may use your version of this file under
1.37 + the terms of any one of the MPL, the GPL or the LGPL.
1.38 +
1.39 +*/
1.40 +
1.41 +using System;
1.42 +using System.Collections.Generic;
1.43 +using System.Drawing;
1.44 +using System.Text;
1.45 +
1.46 +namespace OpenHardwareMonitor.Hardware.LPC {
1.47 + public class W836XX : LPCHardware, IHardware {
1.48 +
1.49 + private ushort address;
1.50 + private byte revision;
1.51 +
1.52 + private bool available;
1.53 +
1.54 + private Sensor[] temperatures;
1.55 + private Sensor[] fans;
1.56 + private Sensor[] voltages;
1.57 +
1.58 + private float[] voltageGains;
1.59 + private string[] fanNames;
1.60 +
1.61 + // Consts
1.62 + private const ushort WINBOND_VENDOR_ID = 0x5CA3;
1.63 + private const byte HIGH_BYTE = 0x80;
1.64 +
1.65 + // Hardware Monitor
1.66 + private const byte ADDRESS_REGISTER_OFFSET = 0x05;
1.67 + private const byte DATA_REGISTER_OFFSET = 0x06;
1.68 +
1.69 + // Hardware Monitor Registers
1.70 + private const byte VOLTAGE_BASE_REG = 0x20;
1.71 + private const byte BANK_SELECT_REGISTER = 0x04E;
1.72 + private const byte VENDOR_ID_REGISTER = 0x4F;
1.73 + private const byte TEMPERATURE_BASE_REG = 0x50;
1.74 + private const byte TEMPERATURE_SYS_REG = 0x27;
1.75 +
1.76 + private byte[] FAN_TACHO_REG = new byte[] { 0x28, 0x29, 0x2A, 0x3F, 0x53 };
1.77 + private byte[] FAN_TACHO_BANK = new byte[] { 0, 0, 0, 0, 5 };
1.78 + private byte[] FAN_BIT_REG = new byte[] { 0x47, 0x4B, 0x4C, 0x59, 0x5D };
1.79 + private byte[] FAN_DIV_BIT0 = new byte[] { 36, 38, 30, 8, 10 };
1.80 + private byte[] FAN_DIV_BIT1 = new byte[] { 37, 39, 31, 9, 11 };
1.81 + private byte[] FAN_DIV_BIT2 = new byte[] { 5, 6, 7, 23, 15 };
1.82 +
1.83 + private byte ReadByte(byte bank, byte register) {
1.84 + WinRing0.WriteIoPortByte(
1.85 + (ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER);
1.86 + WinRing0.WriteIoPortByte(
1.87 + (ushort)(address + DATA_REGISTER_OFFSET), bank);
1.88 + WinRing0.WriteIoPortByte(
1.89 + (ushort)(address + ADDRESS_REGISTER_OFFSET), register);
1.90 + return WinRing0.ReadIoPortByte(
1.91 + (ushort)(address + DATA_REGISTER_OFFSET));
1.92 + }
1.93 +
1.94 + public W836XX(Chip chip, byte revision, ushort address)
1.95 + : base(chip)
1.96 + {
1.97 + this.address = address;
1.98 + this.revision = revision;
1.99 +
1.100 + available = IsWinbondVendor();
1.101 +
1.102 + temperatures = new Sensor[3];
1.103 + temperatures[0] = new Sensor("CPU", 0, SensorType.Temperature, this);
1.104 + temperatures[1] = new Sensor("Auxiliary", 1, SensorType.Temperature, this);
1.105 + temperatures[2] = new Sensor("System", 2, SensorType.Temperature, this);
1.106 +
1.107 + switch (chip) {
1.108 + case Chip.W83627DHG:
1.109 + case Chip.W83627DHGP:
1.110 + case Chip.W83627EHF:
1.111 + case Chip.W83667HG:
1.112 + case Chip.W83667HGB:
1.113 + fanNames = new string[] { "System", "CPU", "Auxiliary",
1.114 + "CPU #2", "Auxiliary #2" };
1.115 + voltageGains = new float[] { 1, 1, 1, 2, 1, 1, 1, 2 };
1.116 + voltages = new Sensor[3];
1.117 + voltages[0] = new Sensor("CPU VCore", 0, SensorType.Voltage, this);
1.118 + voltages[1] = new Sensor("+3.3V", 3, SensorType.Voltage, this);
1.119 + voltages[2] = new Sensor("Battery", 7, SensorType.Voltage, this);
1.120 + break;
1.121 + case Chip.W83627HF:
1.122 + fanNames = new string[] { "Fan #1", "Fan #2", "Fan #3" };
1.123 + voltageGains = new float[] { 2, 1, 2, 1, 1, 1, 1, 2 };
1.124 + voltages = new Sensor[3];
1.125 + voltages[0] = new Sensor("CPU VCore", 0, SensorType.Voltage, this);
1.126 + voltages[1] = new Sensor("+3.3V", 2, SensorType.Voltage, this);
1.127 + voltages[2] = new Sensor("Battery", 7, SensorType.Voltage, this);
1.128 + break;
1.129 + default: fanNames = new string[0];
1.130 + break;
1.131 + }
1.132 +
1.133 + fans = new Sensor[fanNames.Length];
1.134 + for (int i = 0; i < fanNames.Length; i++)
1.135 + fans[i] = new Sensor(fanNames[i], i, SensorType.Fan, this);
1.136 + }
1.137 +
1.138 + public bool IsAvailable {
1.139 + get { return available; }
1.140 + }
1.141 +
1.142 + private bool IsWinbondVendor() {
1.143 + ushort vendorId =
1.144 + (ushort)((ReadByte(HIGH_BYTE, VENDOR_ID_REGISTER) << 8) |
1.145 + ReadByte(0, VENDOR_ID_REGISTER));
1.146 + return vendorId == WINBOND_VENDOR_ID;
1.147 + }
1.148 +
1.149 + public void Update() {
1.150 + foreach (Sensor sensor in voltages) {
1.151 + if (sensor.Index < 7) {
1.152 + int value = ReadByte(0, (byte)(VOLTAGE_BASE_REG + sensor.Index));
1.153 + sensor.Value = 0.008f * voltageGains[sensor.Index] * value;
1.154 + if (sensor.Value > 0)
1.155 + ActivateSensor(sensor);
1.156 + else
1.157 + DeactivateSensor(sensor);
1.158 + } else {
1.159 + // Battery voltage
1.160 + bool valid = (ReadByte(0, 0x5D) & 0x01) > 0;
1.161 + if (valid) {
1.162 + sensor.Value =
1.163 + 0.008f * voltageGains[sensor.Index] * ReadByte(5, 0x51);
1.164 + ActivateSensor(sensor);
1.165 + } else
1.166 + DeactivateSensor(sensor);
1.167 + }
1.168 + }
1.169 +
1.170 + foreach (Sensor sensor in temperatures) {
1.171 + int value;
1.172 + if (sensor.Index < 2) {
1.173 + value = (sbyte)ReadByte((byte)(sensor.Index + 1), TEMPERATURE_BASE_REG);
1.174 + value = (value << 1) | ReadByte((byte)(sensor.Index + 1),
1.175 + (byte)(TEMPERATURE_BASE_REG + 1)) >> 7;
1.176 + } else {
1.177 + value = (sbyte)ReadByte(0, TEMPERATURE_SYS_REG) << 1;
1.178 + }
1.179 + sensor.Value = value / 2.0f;
1.180 + if (value < 0xFE)
1.181 + ActivateSensor(sensor);
1.182 + else
1.183 + DeactivateSensor(sensor);
1.184 + }
1.185 +
1.186 + long bits = 0;
1.187 + for (int i = 0; i < FAN_BIT_REG.Length; i++)
1.188 + bits = (bits << 8) | ReadByte(0, FAN_BIT_REG[i]);
1.189 + foreach (Sensor sensor in fans) {
1.190 + int count = ReadByte(FAN_TACHO_BANK[sensor.Index],
1.191 + FAN_TACHO_REG[sensor.Index]);
1.192 + int divisorBits = (int)(
1.193 + (((bits >> FAN_DIV_BIT2[sensor.Index]) & 1) << 2) |
1.194 + (((bits >> FAN_DIV_BIT1[sensor.Index]) & 1) << 1) |
1.195 + ((bits >> FAN_DIV_BIT0[sensor.Index]) & 1));
1.196 + int divisor = 1 << divisorBits;
1.197 + float value = (count < 0xff) ? 1.35e6f / (count * divisor) : 0;
1.198 + sensor.Value = value;
1.199 + if (value > 0)
1.200 + ActivateSensor(sensor);
1.201 + }
1.202 + }
1.203 +
1.204 + public string GetReport() {
1.205 + StringBuilder r = new StringBuilder();
1.206 +
1.207 + r.AppendLine("LPC " + this.GetType().Name);
1.208 + r.AppendLine();
1.209 + r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
1.210 + r.Append("Chip revision: 0x"); r.AppendLine(revision.ToString("X"));
1.211 + r.Append("Base Adress: 0x"); r.AppendLine(address.ToString("X4"));
1.212 + r.AppendLine();
1.213 + r.AppendLine("Hardware Monitor Registers");
1.214 + r.AppendLine();
1.215 + r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
1.216 + r.AppendLine();
1.217 + for (int i = 0; i < 0x7; i++) {
1.218 + r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append(" ");
1.219 + for (int j = 0; j <= 0xF; j++) {
1.220 + r.Append(" ");
1.221 + r.Append(ReadByte(0, (byte)((i << 4) | j)).ToString("X2"));
1.222 + }
1.223 + r.AppendLine();
1.224 + }
1.225 + for (int k = 1; k <= 5; k++) {
1.226 + r.AppendLine("Bank " + k);
1.227 + for (int i = 0x5; i < 0x6; i++) {
1.228 + r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append(" ");
1.229 + for (int j = 0; j <= 0xF; j++) {
1.230 + r.Append(" ");
1.231 + r.Append(ReadByte((byte)(k),
1.232 + (byte)((i << 4) | j)).ToString("X2"));
1.233 + }
1.234 + r.AppendLine();
1.235 + }
1.236 + }
1.237 + r.AppendLine();
1.238 +
1.239 + return r.ToString();
1.240 + }
1.241 + }
1.242 +}