Hardware/LPC/W83627DHG.cs
author moel.mich
Thu, 04 Feb 2010 21:19:27 +0000
changeset 26 0e01b63e1fdc
parent 19 890e8fca7f33
permissions -rw-r--r--
Release version 0.1.13. Replaced PerformanceCounter based CPU load sensors with an implementation using NtQuerySystemInformation. Fixed a temperature reading problem for W83627DHG chips (sensors with invalid value 127?C).
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     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
     8  
     9   http://www.mozilla.org/MPL/
    10 
    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.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    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.
    21 
    22   Contributor(s):
    23 
    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.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.Drawing;
    41 using System.Text;
    42 
    43 namespace OpenHardwareMonitor.Hardware.LPC {
    44   public class W83627DHG : IHardware {
    45 
    46     private Chip chip;
    47     private byte revision;
    48 
    49     private string name;
    50     private Image icon;
    51 
    52     private bool available = false;
    53     private ushort address;
    54 
    55     private List<ISensor> active = new List<ISensor>();
    56 
    57     private Sensor[] temperatures;
    58     private Sensor[] fans;
    59     private Sensor[] voltages;
    60 
    61     private float[] voltageGains;
    62 
    63     // Consts 
    64     private const ushort WINBOND_VENDOR_ID = 0x5CA3;
    65     private const byte HIGH_BYTE = 0x80;
    66 
    67     // Hardware Monitor
    68     private const byte ADDRESS_REGISTER_OFFSET = 0x05;
    69     private const byte DATA_REGISTER_OFFSET = 0x06;
    70 
    71     // Hardware Monitor Registers
    72     private const byte VOLTAGE_BASE_REG = 0x20;
    73     private const byte BANK_SELECT_REGISTER = 0x04E;
    74     private const byte VENDOR_ID_REGISTER = 0x4F;
    75     private const byte FIRST_BANK_REGISTER = 0x50;
    76     private const byte TEMPERATURE_BASE_REG = 0x50;
    77     private const byte TEMPERATURE_SYS_REG = 0x27;
    78 
    79     private byte[] FAN_TACHO_REG = new byte[] { 0x28, 0x29, 0x2A, 0x3F, 0x53 };
    80     private byte[] FAN_TACHO_BANK = new byte[] { 0, 0, 0, 0, 5 };    
    81     private string[] FAN_NAME = new string[] 
    82       { "System", "CPU #1", "Auxiliary #1", "CPU #2", "Auxiliary #2" };
    83     private byte[] FAN_BIT_REG = new byte[] { 0x47, 0x4B, 0x4C, 0x59, 0x5D };
    84     private byte[] FAN_DIV_BIT0 = new byte[] { 36, 38, 30, 8, 10 };
    85     private byte[] FAN_DIV_BIT1 = new byte[] { 37, 39, 31, 9, 11 };
    86     private byte[] FAN_DIV_BIT2 = new byte[] { 5, 6, 7, 23, 15 };
    87 
    88     private byte ReadByte(byte bank, byte register) {  
    89       WinRing0.WriteIoPortByte(
    90          (ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER);
    91       WinRing0.WriteIoPortByte(
    92          (ushort)(address + DATA_REGISTER_OFFSET), bank);
    93       WinRing0.WriteIoPortByte(
    94          (ushort)(address + ADDRESS_REGISTER_OFFSET), register);
    95       return WinRing0.ReadIoPortByte(
    96         (ushort)(address + DATA_REGISTER_OFFSET));
    97     } 
    98 
    99     public W83627DHG(Chip chip, byte revision, ushort address) {
   100       this.chip = chip;
   101       this.revision = revision;
   102       this.address = address;
   103 
   104       // Check vendor id
   105       ushort vendorId =
   106         (ushort)((ReadByte(HIGH_BYTE, VENDOR_ID_REGISTER) << 8) |
   107            ReadByte(0, VENDOR_ID_REGISTER));
   108       if (vendorId != WINBOND_VENDOR_ID)
   109         return;
   110 
   111       voltageGains = new float[] { 0.008f, 1, 1, 0.016f, 1, 1, 1, 0.016f };
   112       voltages = new Sensor[3];
   113       voltages[0] = new Sensor("CPU VCore", 0, SensorType.Voltage, this);
   114       voltages[1] = new Sensor("+3.3V", 3, SensorType.Voltage, this);
   115       voltages[2] = new Sensor("Battery", 7, SensorType.Voltage, this);
   116 
   117       temperatures = new Sensor[3];
   118       temperatures[0] = new Sensor("CPU", 0, SensorType.Temperature, this);
   119       temperatures[1] = new Sensor("Auxiliary", 1, SensorType.Temperature, this);
   120       temperatures[2] = new Sensor("System", 2, SensorType.Temperature, this);
   121 
   122       fans = new Sensor[FAN_NAME.Length];
   123       for (int i = 0; i < FAN_NAME.Length; i++)
   124         fans[i] = new Sensor(FAN_NAME[i], i, SensorType.Fan, this);
   125 
   126       switch (chip) {
   127         case Chip.W83627DHG: name = "Winbond W83627DHG"; break;
   128         case Chip.W83627DHGP: name = "Winbond W83627DHG-P"; break;
   129         default: return;
   130       }
   131 
   132       this.icon = Utilities.EmbeddedResources.GetImage("chip.png");
   133       available = true;
   134     }
   135 
   136     public bool IsAvailable {
   137       get { return available; }
   138     }
   139 
   140     public string Name {
   141       get { return name; }
   142     }
   143 
   144     public string Identifier {
   145       get { return "/lpc/" + chip.ToString().ToLower(); }
   146     }
   147 
   148     public Image Icon {
   149       get { return icon; }
   150     }
   151 
   152     public ISensor[] Sensors {
   153       get { return active.ToArray(); }
   154     }
   155 
   156     public string GetReport() {
   157       StringBuilder r = new StringBuilder();
   158 
   159       r.AppendLine("LPC W83627DHG");
   160       r.AppendLine();
   161       r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
   162       r.Append("Chip revision: 0x"); r.AppendLine(revision.ToString("X"));
   163       r.Append("Base Adress: 0x"); r.AppendLine(address.ToString("X4"));
   164       r.AppendLine();
   165       r.AppendLine("Hardware Monitor Registers");
   166       r.AppendLine();
   167       r.AppendLine("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
   168       r.AppendLine();
   169       for (int i = 0; i < 0x7; i++) {
   170         r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append("  ");
   171         for (int j = 0; j <= 0xF; j++) {
   172           r.Append(" ");
   173           r.Append(ReadByte(0, (byte)((i << 4) | j)).ToString("X2"));
   174         }
   175         r.AppendLine();
   176       }      
   177       for (int k = 1; k <=5; k++) {
   178         r.AppendLine("Bank " + k);
   179         for (int i = 0x5; i < 0x6; i++) {
   180           r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append("  ");
   181           for (int j = 0; j <= 0xF; j++) {
   182             r.Append(" ");
   183             r.Append(ReadByte((byte)(k), 
   184               (byte)((i << 4) | j)).ToString("X2"));
   185           }
   186           r.AppendLine();
   187         }        
   188       }
   189       r.AppendLine();
   190 
   191       return r.ToString();
   192     }
   193 
   194     public void Update() {
   195       foreach (Sensor sensor in voltages) {
   196         if (sensor.Index < 7) {
   197           int value = ReadByte(0, (byte)(VOLTAGE_BASE_REG + sensor.Index));
   198           sensor.Value = voltageGains[sensor.Index] * value;
   199           if (sensor.Value > 0)
   200             ActivateSensor(sensor);
   201           else
   202             DeactivateSensor(sensor);
   203         } else {
   204           // Battery voltage
   205           bool valid = (ReadByte(0, 0x5D) & 0x01) > 0;
   206           if (valid) {
   207             sensor.Value = voltageGains[sensor.Index] * 
   208               ReadByte(5, 0x51);
   209             ActivateSensor(sensor);
   210           } else
   211             DeactivateSensor(sensor);
   212         }
   213       }
   214 
   215       foreach (Sensor sensor in temperatures) {
   216         int value;
   217         if (sensor.Index < 2) {
   218           value = (sbyte)ReadByte((byte)(sensor.Index + 1), TEMPERATURE_BASE_REG);
   219           value = (value << 1) | ReadByte((byte)(sensor.Index + 1),
   220             (byte)(TEMPERATURE_BASE_REG + 1)) >> 7;
   221         } else {
   222           value = (sbyte)ReadByte(0, TEMPERATURE_SYS_REG) << 1;
   223         }
   224         sensor.Value = value / 2.0f;
   225         if (value < 0xFE)
   226           ActivateSensor(sensor);
   227         else
   228           DeactivateSensor(sensor);
   229       }
   230 
   231       long bits = 0;
   232       for (int i = 0; i < FAN_BIT_REG.Length; i++)
   233         bits = (bits << 8) | ReadByte(0, FAN_BIT_REG[i]);
   234       foreach (Sensor sensor in fans) {
   235         int count = ReadByte(FAN_TACHO_BANK[sensor.Index], 
   236           FAN_TACHO_REG[sensor.Index]);
   237         int divisorBits = (int)(
   238           (((bits >> FAN_DIV_BIT2[sensor.Index]) & 1) << 2) |
   239           (((bits >> FAN_DIV_BIT1[sensor.Index]) & 1) << 1) |
   240            ((bits >> FAN_DIV_BIT0[sensor.Index]) & 1));
   241         int divisor = 1 << divisorBits;
   242         sensor.Value = (count < 0xff) ? 1.35e6f / (count * divisor) : 0;
   243         ActivateSensor(sensor);        
   244       }     
   245     }
   246 
   247     private void ActivateSensor(Sensor sensor) {
   248       if (!active.Contains(sensor)) {
   249         active.Add(sensor);
   250         if (SensorAdded != null)
   251           SensorAdded(sensor);
   252       }
   253     }
   254 
   255     private void DeactivateSensor(Sensor sensor) {
   256       if (active.Contains(sensor)) {
   257         active.Remove(sensor);
   258         if (SensorRemoved != null)
   259           SensorRemoved(sensor);
   260       }
   261     }
   262 
   263     public event SensorEventHandler SensorAdded;
   264     public event SensorEventHandler SensorRemoved;
   265   }
   266 }