Hardware/LPC/LPCGroup.cs
author moel.mich
Sat, 20 Feb 2010 19:51:10 +0000
changeset 56 5cb7eb5bf628
parent 34 dc276daadb2c
child 60 0e62c377c08c
permissions -rw-r--r--
Improved Winbond temperature reading. Temperatures create by adding PECI Agent values (delta to TCC Activation Temperature) to a (possibly uncalibrated) TBase are not read. Direct reading temperatures from sensor report register if available. Added lower bound for temperatures on Winbond chips. Nvidia GPUs are now displayed even if they do not have any sensors.
moel@1
     1
/*
moel@1
     2
  
moel@1
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1
     4
moel@1
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@1
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@1
     7
  the License. You may obtain a copy of the License at
moel@1
     8
 
moel@1
     9
  http://www.mozilla.org/MPL/
moel@1
    10
moel@1
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@1
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1
    13
  for the specific language governing rights and limitations under the License.
moel@1
    14
moel@1
    15
  The Original Code is the Open Hardware Monitor code.
moel@1
    16
moel@1
    17
  The Initial Developer of the Original Code is 
moel@1
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@1
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
moel@1
    22
  Contributor(s):
moel@1
    23
moel@1
    24
  Alternatively, the contents of this file may be used under the terms of
moel@1
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    28
  of those above. If you wish to allow use of your version of this file only
moel@1
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    30
  use your version of this file under the terms of the MPL, indicate your
moel@1
    31
  decision by deleting the provisions above and replace them with the notice
moel@1
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    33
  the provisions above, a recipient may use your version of this file under
moel@1
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    35
 
moel@1
    36
*/
moel@1
    37
moel@1
    38
using System;
moel@1
    39
using System.Collections.Generic;
moel@1
    40
using System.Text;
moel@1
    41
using System.Threading;
moel@1
    42
moel@1
    43
namespace OpenHardwareMonitor.Hardware.LPC {
moel@1
    44
  public class LPCGroup : IGroup {
moel@1
    45
    private List<IHardware> hardware = new List<IHardware>();
moel@1
    46
moel@1
    47
    private Chip chip = Chip.Unknown;
moel@1
    48
moel@1
    49
    // I/O Ports
moel@7
    50
    private ushort[] REGISTER_PORTS = new ushort[] { 0x2e, 0x4e };
moel@7
    51
    private ushort[] VALUE_PORTS = new ushort[] { 0x2f, 0x4f };
moel@7
    52
moel@7
    53
    private ushort registerPort;
moel@7
    54
    private ushort valuePort;
moel@1
    55
moel@1
    56
    // Registers
moel@1
    57
    private const byte CONFIGURATION_CONTROL_REGISTER = 0x02;
moel@1
    58
    private const byte DEVCIE_SELECT_REGISTER = 0x07;
moel@1
    59
    private const byte CHIP_ID_REGISTER = 0x20;
moel@1
    60
    private const byte CHIP_REVISION_REGISTER = 0x21;
moel@7
    61
    private const byte BASE_ADDRESS_REGISTER = 0x60;
moel@1
    62
moel@7
    63
    private byte ReadByte(byte register) {
moel@7
    64
      WinRing0.WriteIoPortByte(registerPort, register);
moel@7
    65
      return WinRing0.ReadIoPortByte(valuePort);
moel@13
    66
    } 
moel@1
    67
moel@7
    68
    private ushort ReadWord(byte register) {
moel@7
    69
      return (ushort)((ReadByte(register) << 8) | 
moel@7
    70
        ReadByte((byte)(register + 1)));
moel@1
    71
    }
moel@1
    72
moel@7
    73
    private void Select(byte logicalDeviceNumber) {
moel@7
    74
      WinRing0.WriteIoPortByte(registerPort, DEVCIE_SELECT_REGISTER);
moel@7
    75
      WinRing0.WriteIoPortByte(valuePort, logicalDeviceNumber);
moel@1
    76
    }
moel@1
    77
moel@34
    78
    // ITE
moel@7
    79
    private const byte IT87_ENVIRONMENT_CONTROLLER_LDN = 0x04;    
moel@1
    80
moel@7
    81
    private void IT87Enter() {
moel@7
    82
      WinRing0.WriteIoPortByte(registerPort, 0x87);
moel@7
    83
      WinRing0.WriteIoPortByte(registerPort, 0x01);
moel@7
    84
      WinRing0.WriteIoPortByte(registerPort, 0x55);
moel@7
    85
      WinRing0.WriteIoPortByte(registerPort, 0x55);
moel@1
    86
    }
moel@1
    87
moel@7
    88
    internal void IT87Exit() {
moel@7
    89
      WinRing0.WriteIoPortByte(registerPort, CONFIGURATION_CONTROL_REGISTER);
moel@7
    90
      WinRing0.WriteIoPortByte(valuePort, 0x02);
moel@1
    91
    }
moel@1
    92
moel@7
    93
    // Winbond, Fintek
moel@7
    94
    private const byte FINTEK_VENDOR_ID_REGISTER = 0x23;
moel@7
    95
    private const ushort FINTEK_VENDOR_ID = 0x1934;
moel@7
    96
moel@34
    97
    private const byte WINBOND_HARDWARE_MONITOR_LDN = 0x0B;
moel@16
    98
moel@16
    99
    private const byte F71858_HARDWARE_MONITOR_LDN = 0x02;
moel@16
   100
    private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04;
moel@7
   101
moel@7
   102
    private void WinbondFintekEnter() {
moel@7
   103
      WinRing0.WriteIoPortByte(registerPort, 0x87);
moel@7
   104
      WinRing0.WriteIoPortByte(registerPort, 0x87);
moel@1
   105
    }
moel@1
   106
moel@7
   107
    private void WinbondFintekExit() {
moel@7
   108
      WinRing0.WriteIoPortByte(registerPort, 0xAA);      
moel@1
   109
    }
moel@1
   110
moel@1
   111
    public LPCGroup() {
moel@1
   112
      if (!WinRing0.IsAvailable)
moel@1
   113
        return;
moel@1
   114
moel@7
   115
      for (int i = 0; i < REGISTER_PORTS.Length; i++) {
moel@7
   116
        registerPort = REGISTER_PORTS[i];
moel@7
   117
        valuePort = VALUE_PORTS[i];
moel@1
   118
moel@7
   119
        WinbondFintekEnter();
moel@1
   120
moel@16
   121
        byte logicalDeviceNumber;
moel@7
   122
        byte id = ReadByte(CHIP_ID_REGISTER);
moel@7
   123
        byte revision = ReadByte(CHIP_REVISION_REGISTER);
moel@34
   124
        chip = Chip.Unknown;
moel@34
   125
        logicalDeviceNumber = 0;
moel@7
   126
        switch (id) {
moel@16
   127
          case 0x05:
moel@16
   128
            switch (revision) {
moel@16
   129
              case 0x41:
moel@16
   130
                chip = Chip.F71882;
moel@16
   131
                logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@34
   132
                break;              
moel@16
   133
            } break;
moel@16
   134
          case 0x06:
moel@16
   135
            switch (revision) {             
moel@16
   136
              case 0x01:
moel@16
   137
                chip = Chip.F71862;
moel@16
   138
                logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@34
   139
                break;              
moel@16
   140
            } break;
moel@16
   141
          case 0x07:
moel@16
   142
            switch (revision) {
moel@16
   143
              case 0x23:
moel@16
   144
                chip = Chip.F71889;
moel@16
   145
                logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@34
   146
                break;              
moel@16
   147
            } break;
moel@16
   148
          case 0x08:
moel@16
   149
            switch (revision) {
moel@16
   150
              case 0x14:
moel@16
   151
                chip = Chip.F71869;
moel@16
   152
                logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
moel@34
   153
                break;              
moel@16
   154
            } break;
moel@31
   155
          case 0x52:
moel@31
   156
            switch (revision) {
moel@31
   157
              case 0x17:
moel@31
   158
              case 0x3A:
moel@31
   159
                chip = Chip.W83627HF;
moel@34
   160
                logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
moel@34
   161
                break;             
moel@34
   162
            } break;
moel@54
   163
          case 0x82:
moel@54
   164
            switch (revision) {
moel@54
   165
              case 0x83:
moel@54
   166
                chip = Chip.W83627THF;
moel@54
   167
                logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
moel@54
   168
                break;
moel@54
   169
            } break;
moel@34
   170
          case 0x88:
moel@34
   171
            switch (revision & 0xF0) {
moel@34
   172
              case 0x60:
moel@34
   173
                chip = Chip.W83627EHF;
moel@34
   174
                logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
moel@31
   175
                break;
moel@31
   176
            } break;
moel@7
   177
          case 0xA0:
moel@7
   178
            switch (revision & 0xF0) {
moel@7
   179
              case 0x20: 
moel@7
   180
                chip = Chip.W83627DHG;
moel@34
   181
                logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;  
moel@34
   182
                break;             
moel@34
   183
            } break;
moel@34
   184
          case 0xA5:
moel@34
   185
            switch (revision & 0xF0) {
moel@34
   186
              case 0x10:
moel@34
   187
                chip = Chip.W83667HG;
moel@34
   188
                logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
moel@7
   189
                break;
moel@19
   190
            } break;
moel@19
   191
          case 0xB0:
moel@19
   192
            switch (revision & 0xF0) {
moel@19
   193
              case 0x70:
moel@19
   194
                chip = Chip.W83627DHGP;
moel@34
   195
                logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
moel@34
   196
                break;             
moel@34
   197
            } break;
moel@34
   198
          case 0xB3:
moel@34
   199
            switch (revision & 0xF0) {
moel@34
   200
              case 0x50:
moel@34
   201
                chip = Chip.W83667HGB;
moel@34
   202
                logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
moel@19
   203
                break;
moel@34
   204
            } break; 
moel@7
   205
        }
moel@7
   206
        if (chip != Chip.Unknown) {
moel@1
   207
moel@16
   208
          Select(logicalDeviceNumber);
moel@7
   209
          ushort address = ReadWord(BASE_ADDRESS_REGISTER);
moel@7
   210
          Thread.Sleep(1);
moel@7
   211
          ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
moel@1
   212
moel@7
   213
          ushort vendorID = 0;
moel@16
   214
          if (chip == Chip.F71862 || chip == Chip.F71882 || chip == Chip.F71889)
moel@7
   215
            vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER);
moel@1
   216
moel@7
   217
          WinbondFintekExit();
moel@1
   218
moel@34
   219
          if (address != verify || address < 0x100 || (address & 0xF007) != 0)
moel@7
   220
            return;
moel@7
   221
          
moel@7
   222
          switch (chip) {
moel@7
   223
            case Chip.W83627DHG:
moel@19
   224
            case Chip.W83627DHGP:
moel@34
   225
            case Chip.W83627EHF:
moel@31
   226
            case Chip.W83627HF:
moel@54
   227
            case Chip.W83627THF:
moel@34
   228
            case Chip.W83667HG:
moel@34
   229
            case Chip.W83667HGB:
moel@34
   230
              W836XX w836XX = new W836XX(chip, revision, address);
moel@34
   231
              if (w836XX.IsAvailable)
moel@34
   232
                hardware.Add(w836XX);
moel@7
   233
              break;
moel@16
   234
            case Chip.F71862:
moel@16
   235
            case Chip.F71882:
moel@16
   236
            case Chip.F71889: 
moel@7
   237
              if (vendorID == FINTEK_VENDOR_ID)
moel@16
   238
                hardware.Add(new F718XX(chip, address));
moel@16
   239
              break;
moel@16
   240
            case Chip.F71869:
moel@16
   241
              hardware.Add(new F718XX(chip, address));
moel@7
   242
              break;
moel@7
   243
            default: break;
moel@7
   244
          }
moel@7
   245
          
moel@7
   246
          return;
moel@7
   247
        }
moel@1
   248
moel@7
   249
        IT87Enter();
moel@1
   250
moel@7
   251
        switch (ReadWord(CHIP_ID_REGISTER)) {
moel@21
   252
          case 0x8716: chip = Chip.IT8716F; break;
moel@21
   253
          case 0x8718: chip = Chip.IT8718F; break;
moel@21
   254
          case 0x8720: chip = Chip.IT8720F; break;
moel@21
   255
          case 0x8726: chip = Chip.IT8726F; break;
moel@7
   256
          default: chip = Chip.Unknown; break;
moel@7
   257
        }
moel@7
   258
moel@7
   259
        if (chip != Chip.Unknown) {
moel@7
   260
          Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
moel@7
   261
          ushort address = ReadWord(BASE_ADDRESS_REGISTER);
moel@7
   262
          Thread.Sleep(1);
moel@7
   263
          ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
moel@7
   264
moel@7
   265
          IT87Exit();
moel@7
   266
moel@34
   267
          if (address != verify || address < 0x100 || (address & 0xF007) != 0)
moel@7
   268
            return;
moel@7
   269
moel@16
   270
          IT87XX it87 = new IT87XX(chip, address);
moel@7
   271
          if (it87.IsAvailable)
moel@7
   272
            hardware.Add(it87);
moel@7
   273
moel@1
   274
          return;
moel@7
   275
        }
moel@7
   276
      }   
moel@1
   277
    }
moel@1
   278
moel@1
   279
    public IHardware[] Hardware {
moel@1
   280
      get {
moel@1
   281
        return hardware.ToArray();
moel@1
   282
      }
moel@1
   283
    }
moel@1
   284
moel@1
   285
    public string GetReport() {
moel@1
   286
      return null;
moel@1
   287
    }
moel@1
   288
moel@1
   289
    public void Close() { }
moel@1
   290
  }
moel@1
   291
}