Hardware/LPC/IT87XX.cs
author moel.mich
Tue, 24 Aug 2010 20:14:54 +0000
changeset 174 51d62ed28ff5
parent 166 fa9dfbfc4145
child 182 4801e9eaf979
permissions -rw-r--r--
Fixed Issue 105 and Issue 106.
     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.Globalization;
    41 using System.Text;
    42 
    43 namespace OpenHardwareMonitor.Hardware.LPC {
    44   internal class IT87XX : ISuperIO {
    45        
    46     private ushort address;
    47     private Chip chip;
    48     private byte version;
    49 
    50     private readonly ushort addressReg;
    51     private readonly ushort dataReg;
    52 
    53     private float?[] voltages = new float?[0];
    54     private float?[] temperatures = new float?[0];
    55     private float?[] fans = new float?[0];
    56 
    57     private readonly float voltageGain;
    58    
    59     // Consts
    60     private const byte ITE_VENDOR_ID = 0x90;
    61        
    62     // Environment Controller
    63     private const byte ADDRESS_REGISTER_OFFSET = 0x05;
    64     private const byte DATA_REGISTER_OFFSET = 0x06;
    65 
    66     // Environment Controller Registers    
    67     private const byte CONFIGURATION_REGISTER = 0x00;
    68     private const byte TEMPERATURE_BASE_REG = 0x29;
    69     private const byte VENDOR_ID_REGISTER = 0x58;
    70     private const byte FAN_TACHOMETER_16_BIT_ENABLE_REGISTER = 0x0c;
    71     private byte[] FAN_TACHOMETER_REG = 
    72       new byte[] { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
    73     private byte[] FAN_TACHOMETER_EXT_REG =
    74       new byte[] { 0x18, 0x19, 0x1a, 0x81, 0x83 };
    75     private const byte VOLTAGE_BASE_REG = 0x20;
    76 
    77     private byte ReadByte(byte register, out bool valid) {
    78       WinRing0.WriteIoPortByte(addressReg, register);
    79       byte value = WinRing0.ReadIoPortByte(dataReg);
    80       valid = register == WinRing0.ReadIoPortByte(addressReg);
    81       return value;
    82     } 
    83 
    84     public IT87XX(Chip chip, ushort address, byte version) {
    85       
    86       this.address = address;
    87       this.chip = chip;
    88       this.version = version;
    89       this.addressReg = (ushort)(address + ADDRESS_REGISTER_OFFSET);
    90       this.dataReg = (ushort)(address + DATA_REGISTER_OFFSET);
    91       
    92       // Check vendor id
    93       bool valid;
    94       byte vendorId = ReadByte(VENDOR_ID_REGISTER, out valid);       
    95       if (!valid || vendorId != ITE_VENDOR_ID)
    96         return;
    97 
    98       // Bit 0x10 of the configuration register should always be 1
    99       if ((ReadByte(CONFIGURATION_REGISTER, out valid) & 0x10) == 0)
   100         return;
   101       if (!valid)
   102         return;
   103 
   104       voltages = new float?[9];
   105       temperatures = new float?[3];
   106       fans = new float?[5];
   107 
   108       // The IT8721F uses a 12mV resultion ADC, all others 16mV
   109       if (chip == Chip.IT8721F) {
   110         voltageGain = 0.012f;
   111       } else {
   112         voltageGain = 0.016f;
   113       }
   114     }
   115 
   116     public Chip Chip { get { return chip; } }
   117     public float?[] Voltages { get { return voltages; } }
   118     public float?[] Temperatures { get { return temperatures; } }
   119     public float?[] Fans { get { return fans; } }
   120 
   121     public string GetReport() {
   122       StringBuilder r = new StringBuilder();
   123 
   124       r.AppendLine("LPC " + this.GetType().Name);
   125       r.AppendLine();
   126       r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
   127       r.Append("Chip Version: 0x"); r.AppendLine(
   128         version.ToString("X", CultureInfo.InvariantCulture));
   129       r.Append("Base Address: 0x"); r.AppendLine(
   130         address.ToString("X4", CultureInfo.InvariantCulture));
   131       r.AppendLine();
   132 
   133       if (!WinRing0.WaitIsaBusMutex(100))
   134         return r.ToString();
   135 
   136       r.AppendLine("Environment Controller Registers");
   137       r.AppendLine();
   138       r.AppendLine("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
   139       r.AppendLine();
   140       for (int i = 0; i <= 0xA; i++) {
   141         r.Append(" "); 
   142         r.Append((i << 4).ToString("X2", CultureInfo.InvariantCulture)); 
   143         r.Append("  ");
   144         for (int j = 0; j <= 0xF; j++) {
   145           r.Append(" ");
   146           bool valid;
   147           byte value = ReadByte((byte)((i << 4) | j), out valid);
   148           if (valid)
   149             r.Append(value.ToString("X2", CultureInfo.InvariantCulture));
   150           else
   151             r.Append("??");
   152         }
   153         r.AppendLine();
   154       }
   155       r.AppendLine();
   156 
   157       WinRing0.ReleaseIsaBusMutex();
   158 
   159       return r.ToString();
   160     }
   161 
   162     public void Update() {
   163       if (!WinRing0.WaitIsaBusMutex(10))
   164         return;
   165 
   166       for (int i = 0; i < voltages.Length; i++) {
   167         bool valid;
   168         
   169         float value = 
   170           voltageGain * ReadByte((byte)(VOLTAGE_BASE_REG + i), out valid);   
   171 
   172         if (!valid)
   173           continue;
   174         if (value > 0)
   175           voltages[i] = value;  
   176         else
   177           voltages[i] = null;
   178       }
   179 
   180       for (int i = 0; i < temperatures.Length; i++) {
   181         bool valid;
   182         sbyte value = (sbyte)ReadByte(
   183           (byte)(TEMPERATURE_BASE_REG + i), out valid);
   184         if (!valid)
   185           continue;
   186 
   187         if (value < sbyte.MaxValue && value > 0)
   188           temperatures[i] = value;
   189         else
   190           temperatures[i] = null;       
   191       }
   192 
   193       for (int i = 0; i < fans.Length; i++) {
   194         bool valid;
   195         int value = ReadByte(FAN_TACHOMETER_REG[i], out valid);
   196         if (!valid) 
   197           continue;
   198         value |= ReadByte(FAN_TACHOMETER_EXT_REG[i], out valid) << 8;
   199         if (!valid)
   200           continue;
   201 
   202         if (value > 0x3f) {
   203           fans[i] = (value < 0xffff) ? 1.35e6f / ((value) * 2) : 0;
   204         } else {
   205           fans[i] = null;
   206         }
   207       }
   208 
   209       WinRing0.ReleaseIsaBusMutex();
   210     }
   211   } 
   212 }