Hardware/LPC/F718XX.cs
author moel.mich
Sat, 31 Dec 2011 17:31:04 +0000
changeset 324 c6ee430d6995
parent 236 763675f19ff4
child 344 3145aadca3d2
permissions -rw-r--r--
Modified and extended version of the patch v4 by Roland Reinl (see Issue 256). Main differences to the original patch: DeviceIoControl refactorings removed, SmartAttribute is now descriptive only and does not hold any state, report is written as one 80 columns table, sensors are created only for meaningful values and without duplicates (remaining life, temperatures, host writes and reads). Also the current implementation should really preserve all the functionality of the old system. Additionally there is now a simple SMART devices emulation class (DebugSmart) that can be used in place of WindowsSmart for testing with reported data.
moel@16
     1
/*
moel@16
     2
  
moel@16
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@16
     4
moel@16
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@16
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@16
     7
  the License. You may obtain a copy of the License at
moel@16
     8
 
moel@16
     9
  http://www.mozilla.org/MPL/
moel@16
    10
moel@16
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@16
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@16
    13
  for the specific language governing rights and limitations under the License.
moel@16
    14
moel@16
    15
  The Original Code is the Open Hardware Monitor code.
moel@16
    16
moel@16
    17
  The Initial Developer of the Original Code is 
moel@16
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@323
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2011
moel@16
    20
  the Initial Developer. All Rights Reserved.
moel@16
    21
moel@16
    22
  Contributor(s):
moel@16
    23
moel@16
    24
  Alternatively, the contents of this file may be used under the terms of
moel@16
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@16
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@16
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@16
    28
  of those above. If you wish to allow use of your version of this file only
moel@16
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@16
    30
  use your version of this file under the terms of the MPL, indicate your
moel@16
    31
  decision by deleting the provisions above and replace them with the notice
moel@16
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@16
    33
  the provisions above, a recipient may use your version of this file under
moel@16
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@16
    35
 
moel@16
    36
*/
moel@16
    37
moel@166
    38
using System.Globalization;
moel@16
    39
using System.Text;
moel@16
    40
moel@16
    41
namespace OpenHardwareMonitor.Hardware.LPC {
moel@165
    42
  internal class F718XX : ISuperIO {
moel@16
    43
moel@195
    44
    private readonly ushort address;
moel@195
    45
    private readonly Chip chip;
moel@16
    46
moel@195
    47
    private readonly float?[] voltages;
moel@195
    48
    private readonly float?[] temperatures;
moel@195
    49
    private readonly float?[] fans;
moel@323
    50
    private readonly float?[] controls;
moel@16
    51
moel@16
    52
    // Hardware Monitor
moel@16
    53
    private const byte ADDRESS_REGISTER_OFFSET = 0x05;
moel@16
    54
    private const byte DATA_REGISTER_OFFSET = 0x06;
moel@16
    55
moel@16
    56
    // Hardware Monitor Registers
moel@16
    57
    private const byte VOLTAGE_BASE_REG = 0x20;
moel@68
    58
    private const byte TEMPERATURE_CONFIG_REG = 0x69;
moel@68
    59
    private const byte TEMPERATURE_BASE_REG = 0x70;
moel@195
    60
    private readonly byte[] FAN_TACHOMETER_REG = 
moel@195
    61
      new byte[] { 0xA0, 0xB0, 0xC0, 0xD0 };
moel@16
    62
    
moel@16
    63
    private byte ReadByte(byte register) {
moel@236
    64
      Ring0.WriteIoPort(
moel@16
    65
        (ushort)(address + ADDRESS_REGISTER_OFFSET), register);
moel@236
    66
      return Ring0.ReadIoPort((ushort)(address + DATA_REGISTER_OFFSET));
moel@132
    67
    }
moel@16
    68
moel@228
    69
    public byte? ReadGPIO(int index) {
moel@228
    70
      return null;
moel@228
    71
    }
moel@228
    72
moel@228
    73
    public void WriteGPIO(int index, byte value) { }
moel@228
    74
moel@323
    75
    public void SetControl(int index, byte? value) { }   
moel@323
    76
moel@130
    77
    public F718XX(Chip chip, ushort address) {
moel@16
    78
      this.address = address;
moel@130
    79
      this.chip = chip;
moel@16
    80
moel@130
    81
      voltages = new float?[chip == Chip.F71858 ? 3 : 9];
moel@130
    82
      temperatures = new float?[3];
moel@130
    83
      fans = new float?[chip == Chip.F71882 || chip == Chip.F71858? 4 : 3];
moel@323
    84
      controls = new float?[0];
moel@16
    85
    }
moel@16
    86
moel@130
    87
    public Chip Chip { get { return chip; } }
moel@130
    88
    public float?[] Voltages { get { return voltages; } }
moel@130
    89
    public float?[] Temperatures { get { return temperatures; } }
moel@130
    90
    public float?[] Fans { get { return fans; } }
moel@323
    91
    public float?[] Controls { get { return controls; } }
moel@130
    92
moel@130
    93
    public string GetReport() {
moel@16
    94
      StringBuilder r = new StringBuilder();
moel@16
    95
moel@31
    96
      r.AppendLine("LPC " + this.GetType().Name);
moel@16
    97
      r.AppendLine();
moel@166
    98
      r.Append("Base Adress: 0x"); 
moel@166
    99
      r.AppendLine(address.ToString("X4", CultureInfo.InvariantCulture));
moel@16
   100
      r.AppendLine();
moel@162
   101
moel@236
   102
      if (!Ring0.WaitIsaBusMutex(100))
moel@162
   103
        return r.ToString();
moel@162
   104
moel@16
   105
      r.AppendLine("Hardware Monitor Registers");
moel@16
   106
      r.AppendLine();
moel@16
   107
      r.AppendLine("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
moel@16
   108
      r.AppendLine();
moel@16
   109
      for (int i = 0; i <= 0xF; i++) {
moel@166
   110
        r.Append(" "); 
moel@166
   111
        r.Append((i << 4).ToString("X2", CultureInfo.InvariantCulture)); 
moel@166
   112
        r.Append("  ");
moel@16
   113
        for (int j = 0; j <= 0xF; j++) {
moel@16
   114
          r.Append(" ");
moel@166
   115
          r.Append(ReadByte((byte)((i << 4) | j)).ToString("X2", 
moel@166
   116
            CultureInfo.InvariantCulture));
moel@16
   117
        }
moel@16
   118
        r.AppendLine();
moel@16
   119
      }
moel@16
   120
      r.AppendLine();
moel@162
   121
moel@236
   122
      Ring0.ReleaseIsaBusMutex();
moel@162
   123
moel@16
   124
      return r.ToString();
moel@16
   125
    }
moel@16
   126
moel@130
   127
    public void Update() {
moel@236
   128
      if (!Ring0.WaitIsaBusMutex(10))
moel@162
   129
        return;
moel@16
   130
moel@130
   131
      for (int i = 0; i < voltages.Length; i++) {
moel@130
   132
        int value = ReadByte((byte)(VOLTAGE_BASE_REG + i));
moel@132
   133
        voltages[i] = 0.008f * value;
moel@16
   134
      }
moel@68
   135
     
moel@130
   136
      for (int i = 0; i < temperatures.Length; i++) {
moel@68
   137
        switch (chip) {
moel@68
   138
          case Chip.F71858: {
moel@195
   139
              int tableMode = 0x3 & ReadByte(TEMPERATURE_CONFIG_REG);
moel@68
   140
              int high = 
moel@130
   141
                ReadByte((byte)(TEMPERATURE_BASE_REG + 2 * i));
moel@68
   142
              int low =
moel@130
   143
                ReadByte((byte)(TEMPERATURE_BASE_REG + 2 * i + 1));              
moel@68
   144
              if (high != 0xbb && high != 0xcc) {
moel@68
   145
                int bits = 0;
moel@68
   146
                switch (tableMode) {
moel@68
   147
                  case 0: bits = 0; break;
moel@68
   148
                  case 1: bits = 0; break;
moel@68
   149
                  case 2: bits = (high & 0x80) << 8; break;
moel@68
   150
                  case 3: bits = (low & 0x01) << 15; break;
moel@68
   151
                }
moel@68
   152
                bits |= high << 7;
moel@68
   153
                bits |= (low & 0xe0) >> 1;
moel@68
   154
                short value = (short)(bits & 0xfff0);
moel@130
   155
                temperatures[i] = value / 128.0f;
moel@68
   156
              } else {
moel@130
   157
                temperatures[i] = null;
moel@68
   158
              }
moel@68
   159
          } break;
moel@68
   160
          default: {
moel@68
   161
            sbyte value = (sbyte)ReadByte((byte)(
moel@130
   162
              TEMPERATURE_BASE_REG + 2 * (i + 1)));            
moel@68
   163
            if (value < sbyte.MaxValue && value > 0)
moel@130
   164
              temperatures[i] = value;
moel@130
   165
            else
moel@130
   166
              temperatures[i] = null;
moel@68
   167
          } break;
moel@68
   168
        }
moel@16
   169
      }
moel@16
   170
moel@130
   171
      for (int i = 0; i < fans.Length; i++) {
moel@130
   172
        int value = ReadByte(FAN_TACHOMETER_REG[i]) << 8;
moel@130
   173
        value |= ReadByte((byte)(FAN_TACHOMETER_REG[i] + 1));
moel@16
   174
moel@130
   175
        if (value > 0) 
moel@130
   176
          fans[i] = (value < 0x0fff) ? 1.5e6f / value : 0;
moel@130
   177
        else 
moel@130
   178
          fans[i] = null;        
moel@162
   179
      }
moel@162
   180
moel@236
   181
      Ring0.ReleaseIsaBusMutex();
moel@16
   182
    }
moel@16
   183
  }
moel@16
   184
}