Hardware/LPC/W83627DHG.cs
author moel.mich
Sun, 31 Jan 2010 22:00:31 +0000
changeset 15 0e812fe67bac
parent 14 51c2f209da6d
child 19 890e8fca7f33
permissions -rw-r--r--
Release version 0.1.6. Fixed F71882 temperature reading. Added error handling for ATI GPUs (ADL). Fixed sensor events.
     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 byte revision;
    47 
    48     private string name;
    49     private Image icon;
    50 
    51     private bool available = false;
    52     private ushort address;
    53 
    54     private List<ISensor> active = new List<ISensor>();
    55 
    56     private Sensor[] temperatures;
    57     private Sensor[] fans;
    58     private Sensor[] voltages;
    59 
    60     private float[] voltageGains;
    61 
    62     // Consts 
    63     private const ushort WINBOND_VENDOR_ID = 0x5CA3;
    64     private const byte HIGH_BYTE = 0x80;
    65 
    66     // Hardware Monitor
    67     private const byte ADDRESS_REGISTER_OFFSET = 0x05;
    68     private const byte DATA_REGISTER_OFFSET = 0x06;
    69 
    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;
    77 
    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 };
    86 
    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));
    96     }    
    97 
    98     public W83627DHG(byte revision, ushort address) {      
    99       this.revision = revision;
   100       this.address = address;
   101 
   102       // Check vendor id
   103       ushort vendorId =
   104         (ushort)((ReadByte(HIGH_BYTE, VENDOR_ID_REGISTER) << 8) |
   105            ReadByte(0, VENDOR_ID_REGISTER));
   106       if (vendorId != WINBOND_VENDOR_ID)
   107         return;
   108 
   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);
   114 
   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);
   119 
   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);
   123 
   124       this.name = "Winbond W83627DHG";
   125       this.icon = Utilities.EmbeddedResources.GetImage("chip.png");
   126       available = true;
   127     }
   128 
   129     public bool IsAvailable {
   130       get { return available; }
   131     }
   132 
   133     public string Name {
   134       get { return name; }
   135     }
   136 
   137     public string Identifier {
   138       get { return "/lpc/w83627dhg"; }
   139     }
   140 
   141     public Image Icon {
   142       get { return icon; }
   143     }
   144 
   145     public ISensor[] Sensors {
   146       get { return active.ToArray(); }
   147     }
   148 
   149     public string GetReport() {
   150       StringBuilder r = new StringBuilder();
   151 
   152       r.AppendLine("LPC W83627DHG");
   153       r.AppendLine();
   154       r.Append("Chip revision: 0x"); r.AppendLine(revision.ToString("X"));
   155       r.Append("Base Adress: 0x"); r.AppendLine(address.ToString("X4"));
   156       r.AppendLine();
   157       r.AppendLine("Hardware Monitor Registers");
   158       r.AppendLine();
   159       r.AppendLine("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
   160       r.AppendLine();
   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++) {
   164           r.Append(" ");
   165           r.Append(ReadByte(0, (byte)((i << 4) | j)).ToString("X2"));
   166         }
   167         r.AppendLine();
   168       }      
   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++) {
   174             r.Append(" ");
   175             r.Append(ReadByte((byte)(k), 
   176               (byte)((i << 4) | j)).ToString("X2"));
   177           }
   178           r.AppendLine();
   179         }        
   180       }
   181       r.AppendLine();
   182 
   183       return r.ToString();
   184     }
   185 
   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);
   193           else
   194             DeactivateSensor(sensor);
   195         } else {
   196           // Battery voltage
   197           bool valid = (ReadByte(0, 0x5D) & 0x01) > 0;
   198           if (valid) {
   199             sensor.Value = voltageGains[sensor.Index] * 
   200               ReadByte(5, 0x51);
   201             ActivateSensor(sensor);
   202           } else
   203             DeactivateSensor(sensor);
   204         }
   205       }
   206 
   207       foreach (Sensor sensor in temperatures) {
   208         int value;
   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;
   213         } else {
   214           value = ReadByte(0, TEMPERATURE_SYS_REG) << 1;
   215         }
   216         sensor.Value = value / 2.0f;
   217         if (value < 0x1FE)
   218           ActivateSensor(sensor);
   219         else
   220           DeactivateSensor(sensor);
   221       }
   222 
   223       long bits = 0;
   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);        
   236       }     
   237     }
   238 
   239     private void ActivateSensor(Sensor sensor) {
   240       if (!active.Contains(sensor)) {
   241         active.Add(sensor);
   242         if (SensorAdded != null)
   243           SensorAdded(sensor);
   244       }
   245     }
   246 
   247     private void DeactivateSensor(Sensor sensor) {
   248       if (active.Contains(sensor)) {
   249         active.Remove(sensor);
   250         if (SensorRemoved != null)
   251           SensorRemoved(sensor);
   252       }
   253     }
   254 
   255     public event SensorEventHandler SensorAdded;
   256     public event SensorEventHandler SensorRemoved;
   257   }
   258 }