Hardware/Mainboard/SuperIOHardware.cs
author moel.mich
Mon, 07 Jun 2010 20:03:48 +0000
changeset 136 fa2957aa0699
parent 134 8b3b9b2e28e5
child 138 1301992d8ae5
permissions -rw-r--r--
Added (partial) SMBIOS support for Linux by reading from sysfs.
     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 OpenHardwareMonitor.Hardware.LPC;
    42 
    43 namespace OpenHardwareMonitor.Hardware.Mainboard {
    44   public class SuperIOHardware : Hardware {
    45 
    46     private ISuperIO superIO;
    47     private Image icon;
    48     protected readonly string name;
    49 
    50     private List<Sensor> voltages = new List<Sensor>();
    51     private List<Sensor> temperatures = new List<Sensor>();
    52     private List<Sensor> fans = new List<Sensor>();  
    53 
    54     public SuperIOHardware(ISuperIO superIO, Manufacturer manufacturer, 
    55       Model model) 
    56     {
    57       this.superIO = superIO;
    58       this.icon = Utilities.EmbeddedResources.GetImage("chip.png");
    59 
    60       switch (superIO.Chip) {
    61         case Chip.F71858: name = "Fintek F71858"; break;
    62         case Chip.F71862: name = "Fintek F71862"; break;
    63         case Chip.F71869: name = "Fintek F71869"; break;
    64         case Chip.F71882: name = "Fintek F71882"; break;
    65         case Chip.F71889ED: name = "Fintek F71889ED"; break;
    66         case Chip.F71889F: name = "Fintek F71889F"; break;
    67         case Chip.IT8712F: this.name = "ITE IT8712F"; break;
    68         case Chip.IT8716F: this.name = "ITE IT8716F"; break;
    69         case Chip.IT8718F: this.name = "ITE IT8718F"; break;
    70         case Chip.IT8720F: this.name = "ITE IT8720F"; break;
    71         case Chip.IT8726F: this.name = "ITE IT8726F"; break;
    72         case Chip.W83627DHG: this.name = "Winbond W83627DHG"; break;
    73         case Chip.W83627DHGP: this.name = "Winbond W83627DHG-P"; break;
    74         case Chip.W83627EHF: this.name = "Winbond W83627EHF"; break;
    75         case Chip.W83627HF: this.name = "Winbond W83627HF"; break;
    76         case Chip.W83627THF: this.name = "Winbond W83627THF"; break;
    77         case Chip.W83667HG: this.name = "Winbond W83667HG"; break;
    78         case Chip.W83667HGB: this.name = "Winbond W83667HG-B"; break;
    79         case Chip.W83687THF: this.name = "Winbond W83687THF"; break;
    80         case Chip.Unknown: this.name = "Unkown"; break;
    81       }
    82 
    83       List<Voltage> v = new List<Voltage>();
    84       List<Temperature> t = new List<Temperature>();
    85       List<Fan> f = new List<Fan>();
    86 
    87       switch (superIO.Chip) {
    88         case Chip.IT8712F:
    89         case Chip.IT8716F:
    90         case Chip.IT8718F:
    91         case Chip.IT8720F:
    92         case Chip.IT8726F:
    93           switch (manufacturer) {
    94             case Manufacturer.ASUS:
    95               switch (model) {
    96                 case Model.Crosshair_III_Formula:
    97                   v.Add(new Voltage("VBat", 8));
    98                   t.Add(new Temperature("CPU", 0));
    99                   for (int i = 0; i < superIO.Fans.Length; i++)
   100                     f.Add(new Fan("Fan #" + (i + 1), i));
   101                   break;
   102                 case Model.M2N_SLI_DELUXE:
   103                   v.Add(new Voltage("CPU VCore", 0));
   104                   v.Add(new Voltage("+3.3V", 1));
   105                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   106                   v.Add(new Voltage("+12V", 4, 30, 10, 0));
   107                   v.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0));
   108                   v.Add(new Voltage("VBat", 8));
   109                   t.Add(new Temperature("CPU", 0));
   110                   t.Add(new Temperature("Motherboard", 1));
   111                   f.Add(new Fan("CPU Fan", 0));
   112                   f.Add(new Fan("Chassis Fan #1", 1));
   113                   f.Add(new Fan("Power Fan", 2));
   114                   break;
   115                 default:
   116                   v.Add(new Voltage("CPU VCore", 0));
   117                   v.Add(new Voltage("Voltage #2", 1, true));
   118                   v.Add(new Voltage("Voltage #3", 2, true));
   119                   v.Add(new Voltage("Voltage #4", 3, true));
   120                   v.Add(new Voltage("Voltage #5", 4, true));
   121                   v.Add(new Voltage("Voltage #6", 5, true));
   122                   v.Add(new Voltage("Voltage #7", 6, true));
   123                   v.Add(new Voltage("Voltage #8", 7, true));
   124                   v.Add(new Voltage("VBat", 8));
   125                   for (int i = 0; i < superIO.Temperatures.Length; i++)
   126                     t.Add(new Temperature("Temperature #" + (i + 1), i));
   127                   for (int i = 0; i < superIO.Fans.Length; i++)
   128                     f.Add(new Fan("Fan #" + (i + 1), i));
   129                   break;
   130               }
   131               break;
   132             case Manufacturer.DFI:
   133               switch (model) {
   134                 case Model.LP_BI_P45_T2RS_Elite:
   135                   v.Add(new Voltage("CPU VCore", 0));
   136                   v.Add(new Voltage("FSB VTT", 1));
   137                   v.Add(new Voltage("+3.3V", 2));
   138                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   139                   v.Add(new Voltage("+12V", 4, 30, 10, 0));
   140                   v.Add(new Voltage("NB Core", 5));
   141                   v.Add(new Voltage("VDIMM", 6));
   142                   v.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0));
   143                   v.Add(new Voltage("VBat", 8));
   144                   t.Add(new Temperature("CPU", 0));
   145                   t.Add(new Temperature("System", 1));
   146                   t.Add(new Temperature("Chipset", 2));
   147                   f.Add(new Fan("Fan #1", 0));
   148                   f.Add(new Fan("Fan #2", 1));
   149                   f.Add(new Fan("Fan #3", 2));
   150                   break;
   151                 case Model.LP_DK_P55_T3eH9:
   152                   v.Add(new Voltage("CPU VCore", 0));
   153                   v.Add(new Voltage("VTT", 1));
   154                   v.Add(new Voltage("+3.3V", 2));
   155                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   156                   v.Add(new Voltage("+12V", 4, 30, 10, 0));
   157                   v.Add(new Voltage("CPU PLL", 5));
   158                   v.Add(new Voltage("DRAM", 6));
   159                   v.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0));
   160                   v.Add(new Voltage("VBat", 8));
   161                   t.Add(new Temperature("Chipset", 0));
   162                   t.Add(new Temperature("CPU PWM", 1));
   163                   t.Add(new Temperature("CPU", 2));
   164                   f.Add(new Fan("Fan #1", 0));
   165                   f.Add(new Fan("Fan #2", 1));
   166                   f.Add(new Fan("Fan #3", 2));
   167                   break;
   168                 default:
   169                   v.Add(new Voltage("CPU VCore", 0));
   170                   v.Add(new Voltage("VTT", 1, true));
   171                   v.Add(new Voltage("+3.3V", 2, true));
   172                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0, true));
   173                   v.Add(new Voltage("+12V", 4, 30, 10, 0, true));
   174                   v.Add(new Voltage("Voltage #6", 5, true));
   175                   v.Add(new Voltage("DRAM", 6, true));
   176                   v.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0, true));
   177                   v.Add(new Voltage("VBat", 8));
   178                   for (int i = 0; i < superIO.Temperatures.Length; i++)
   179                     t.Add(new Temperature("Temperature #" + (i + 1), i));
   180                   for (int i = 0; i < superIO.Fans.Length; i++)
   181                     f.Add(new Fan("Fan #" + (i + 1), i));
   182                   break;
   183               }
   184               break;
   185 
   186             case Manufacturer.Gigabyte:
   187               switch (model) {
   188                 case Model._965P_S3:
   189                   v.Add(new Voltage("CPU VCore", 0));
   190                   v.Add(new Voltage("DRAM", 1));
   191                   v.Add(new Voltage("+3.3V", 2));
   192                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   193                   v.Add(new Voltage("+12V", 7, 27, 9.1f, 0));
   194                   v.Add(new Voltage("VBat", 8));
   195                   t.Add(new Temperature("System", 0));
   196                   t.Add(new Temperature("CPU", 1));
   197                   f.Add(new Fan("CPU Fan", 0));
   198                   f.Add(new Fan("System Fan", 1));
   199                   break;
   200                 case Model.EP45_DS3R:
   201                 case Model.EP45_UD3R: 
   202                 case Model.X38_DS5:                
   203                   v.Add(new Voltage("CPU VCore", 0));
   204                   v.Add(new Voltage("DRAM", 1));
   205                   v.Add(new Voltage("+3.3V", 2));
   206                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   207                   v.Add(new Voltage("+12V", 7, 27, 9.1f, 0));
   208                   v.Add(new Voltage("VBat", 8));
   209                   t.Add(new Temperature("System", 0));
   210                   t.Add(new Temperature("CPU", 1));
   211                   f.Add(new Fan("CPU Fan", 0));
   212                   f.Add(new Fan("System Fan #2", 1));
   213                   f.Add(new Fan("Power Fan", 2));
   214                   f.Add(new Fan("System Fan #1", 3));
   215                   break;
   216                 case Model.EX58_EXTREME:
   217                   v.Add(new Voltage("CPU VCore", 0));
   218                   v.Add(new Voltage("DRAM", 1));
   219                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   220                   v.Add(new Voltage("VBat", 8));
   221                   t.Add(new Temperature("System", 0));
   222                   t.Add(new Temperature("CPU", 1));
   223                   t.Add(new Temperature("MCH", 2));
   224                   f.Add(new Fan("CPU Fan", 0));
   225                   f.Add(new Fan("System Fan #2", 1));
   226                   f.Add(new Fan("Power Fan", 2));
   227                   f.Add(new Fan("System Fan #1", 3));
   228                   break;
   229                 case Model.P35_DS3:
   230                 case Model.P35_DS3L:
   231                   v.Add(new Voltage("CPU VCore", 0));
   232                   v.Add(new Voltage("DRAM", 1));
   233                   v.Add(new Voltage("+3.3V", 2));
   234                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   235                   v.Add(new Voltage("+12V", 7, 27, 9.1f, 0));
   236                   v.Add(new Voltage("VBat", 8));
   237                   t.Add(new Temperature("System", 0));
   238                   t.Add(new Temperature("CPU", 1));
   239                   f.Add(new Fan("CPU Fan", 0));
   240                   f.Add(new Fan("System Fan #1", 1));
   241                   f.Add(new Fan("System Fan #2", 2));
   242                   f.Add(new Fan("Power Fan", 3));
   243                   break;
   244                 case Model.GA_MA785GMT_UD2H:
   245                   v.Add(new Voltage("CPU VCore", 0));
   246                   v.Add(new Voltage("DRAM", 1));
   247                   v.Add(new Voltage("+3.3V", 2));
   248                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0));
   249                   v.Add(new Voltage("+12V", 4, 27, 9.1f, 0));
   250                   v.Add(new Voltage("VBat", 8));
   251                   t.Add(new Temperature("System", 0));
   252                   t.Add(new Temperature("CPU", 1));
   253                   f.Add(new Fan("CPU Fan", 0));
   254                   f.Add(new Fan("System Fan", 1));
   255                   f.Add(new Fan("NB Fan", 2));
   256                   break;
   257                 default:
   258                   v.Add(new Voltage("CPU VCore", 0));
   259                   v.Add(new Voltage("DRAM", 1, true));
   260                   v.Add(new Voltage("+3.3V", 2, true));
   261                   v.Add(new Voltage("+5V", 3, 6.8f, 10, 0, true));
   262                   v.Add(new Voltage("Voltage #5", 4, true));
   263                   v.Add(new Voltage("Voltage #6", 5, true));
   264                   v.Add(new Voltage("Voltage #7", 6, true));
   265                   v.Add(new Voltage("+12V", 7, 27, 9.1f, 0, true));
   266                   v.Add(new Voltage("VBat", 8));
   267                   for (int i = 0; i < superIO.Temperatures.Length; i++)
   268                     t.Add(new Temperature("Temperature #" + (i + 1), i));
   269                   for (int i = 0; i < superIO.Fans.Length; i++)
   270                     f.Add(new Fan("Fan #" + (i + 1), i));
   271                   break;
   272               }
   273               break;
   274 
   275             default:
   276               v.Add(new Voltage("CPU VCore", 0));
   277               v.Add(new Voltage("Voltage #2", 1, true));
   278               v.Add(new Voltage("Voltage #3", 2, true));
   279               v.Add(new Voltage("Voltage #4", 3, true));
   280               v.Add(new Voltage("Voltage #5", 4, true));
   281               v.Add(new Voltage("Voltage #6", 5, true));
   282               v.Add(new Voltage("Voltage #7", 6, true));
   283               v.Add(new Voltage("Voltage #8", 7, true));
   284               v.Add(new Voltage("VBat", 8));
   285               for (int i = 0; i < superIO.Temperatures.Length; i++)
   286                 t.Add(new Temperature("Temperature #" + (i + 1), i));
   287               for (int i = 0; i < superIO.Fans.Length; i++)
   288                 f.Add(new Fan("Fan #" + (i + 1), i));
   289               break;
   290           }
   291           break;
   292           
   293         case Chip.F71858:
   294           v.Add(new Voltage("VCC3V", 0, 150, 150, 0));
   295           v.Add(new Voltage("VSB3V", 1, 150, 150, 0));
   296           v.Add(new Voltage("Battery", 2, 150, 150, 0));
   297           for (int i = 0; i < superIO.Temperatures.Length; i++)
   298             t.Add(new Temperature("Temperature #" + (i + 1), i));
   299           for (int i = 0; i < superIO.Fans.Length; i++)
   300             f.Add(new Fan("Fan #" + (i + 1), i));
   301           break;
   302         case Chip.F71862: 
   303         case Chip.F71869: 
   304         case Chip.F71882:
   305         case Chip.F71889ED: 
   306         case Chip.F71889F:
   307           switch (manufacturer) {
   308             case Manufacturer.EVGA:
   309               switch (model) {
   310                 case Model.X58_SLI_Classified:
   311                   v.Add(new Voltage("VCC3V", 0, 150, 150, 0));
   312                   v.Add(new Voltage("CPU VCore", 1, 47, 100, 0));
   313                   v.Add(new Voltage("DIMM", 2, 47, 100, 0));
   314                   v.Add(new Voltage("CPU VTT", 3, 24, 100, 0));
   315                   v.Add(new Voltage("IOH Vcore", 4, 24, 100, 0));
   316                   v.Add(new Voltage("+5V", 5, 51, 12, 0));
   317                   v.Add(new Voltage("+12V", 6, 56, 6.8f, 0));
   318                   v.Add(new Voltage("3VSB", 7, 150, 150, 0));
   319                   v.Add(new Voltage("VBat", 8, 150, 150, 0));
   320                   t.Add(new Temperature("CPU", 0));
   321                   t.Add(new Temperature("VREG", 1));
   322                   t.Add(new Temperature("System", 2));
   323                   f.Add(new Fan("CPU Fan", 0));
   324                   f.Add(new Fan("Power Fan", 1));
   325                   f.Add(new Fan("Chassis Fan", 2));
   326                   break;
   327                 default:
   328                   v.Add(new Voltage("VCC3V", 0, 150, 150, 0));
   329                   v.Add(new Voltage("CPU VCore", 1));
   330                   v.Add(new Voltage("Voltage #3", 2, true));
   331                   v.Add(new Voltage("Voltage #4", 3, true));
   332                   v.Add(new Voltage("Voltage #5", 4, true));
   333                   v.Add(new Voltage("Voltage #6", 5, true));
   334                   v.Add(new Voltage("Voltage #7", 6, true));
   335                   v.Add(new Voltage("VSB3V", 7, 150, 150, 0));
   336                   v.Add(new Voltage("VBat", 8, 150, 150, 0));
   337                   for (int i = 0; i < superIO.Temperatures.Length; i++)
   338                     t.Add(new Temperature("Temperature #" + (i + 1), i));
   339                   for (int i = 0; i < superIO.Fans.Length; i++)
   340                     f.Add(new Fan("Fan #" + (i + 1), i));
   341                   break;
   342               }
   343               break;
   344             default:
   345               v.Add(new Voltage("VCC3V", 0, 150, 150, 0));
   346               v.Add(new Voltage("CPU VCore", 1));
   347               v.Add(new Voltage("Voltage #3", 2, true));
   348               v.Add(new Voltage("Voltage #4", 3, true));
   349               v.Add(new Voltage("Voltage #5", 4, true));
   350               v.Add(new Voltage("Voltage #6", 5, true));
   351               v.Add(new Voltage("Voltage #7", 6, true));
   352               v.Add(new Voltage("VSB3V", 7, 150, 150, 0));
   353               v.Add(new Voltage("VBat", 8, 150, 150, 0));
   354               for (int i = 0; i < superIO.Temperatures.Length; i++)
   355                 t.Add(new Temperature("Temperature #" + (i + 1), i));
   356               for (int i = 0; i < superIO.Fans.Length; i++)
   357                 f.Add(new Fan("Fan #" + (i + 1), i));
   358               break;
   359           }
   360           break;
   361 
   362         case Chip.W83627EHF:          
   363           v.Add(new Voltage("CPU VCore", 0));
   364           v.Add(new Voltage("Voltage #2", 1, true));
   365           v.Add(new Voltage("AVCC", 2, 34, 34, 0));
   366           v.Add(new Voltage("3VCC", 3, 34, 34, 0));
   367           v.Add(new Voltage("Voltage #5", 4, true));
   368           v.Add(new Voltage("Voltage #6", 5, true));
   369           v.Add(new Voltage("Voltage #7", 6, true));
   370           v.Add(new Voltage("3VSB", 7, 34, 34, 0));
   371           v.Add(new Voltage("VBAT", 8, 34, 34, 0));
   372           v.Add(new Voltage("Voltage #10", 9, true));
   373           t.Add(new Temperature("CPU", 0));
   374           t.Add(new Temperature("Auxiliary", 1));
   375           t.Add(new Temperature("System", 2));
   376           f.Add(new Fan("System", 0));
   377           f.Add(new Fan("CPU", 1));
   378           f.Add(new Fan("Auxiliary", 2));
   379           f.Add(new Fan("CPU #2", 3));
   380           f.Add(new Fan("Auxiliary #2", 4));
   381           break;
   382         case Chip.W83627DHG: 
   383         case Chip.W83627DHGP:                      
   384         case Chip.W83667HG:
   385         case Chip.W83667HGB:
   386           v.Add(new Voltage("CPU VCore", 0));
   387           v.Add(new Voltage("Voltage #2", 1, true));
   388           v.Add(new Voltage("AVCC", 2, 34, 34, 0));
   389           v.Add(new Voltage("3VCC", 3, 34, 34, 0));
   390           v.Add(new Voltage("Voltage #5", 4, true));
   391           v.Add(new Voltage("Voltage #6", 5, true));
   392           v.Add(new Voltage("Voltage #7", 6, true));
   393           v.Add(new Voltage("3VSB", 7, 34, 34, 0));
   394           v.Add(new Voltage("VBAT", 8, 34, 34, 0));
   395           t.Add(new Temperature("CPU", 0));
   396           t.Add(new Temperature("Auxiliary", 1));
   397           t.Add(new Temperature("System", 2));
   398           f.Add(new Fan("System", 0));
   399           f.Add(new Fan("CPU", 1));
   400           f.Add(new Fan("Auxiliary", 2));
   401           f.Add(new Fan("CPU #2", 3));
   402           f.Add(new Fan("Auxiliary #2", 4));            
   403           break;
   404         case Chip.W83627HF: 
   405         case Chip.W83627THF: 
   406         case Chip.W83687THF:
   407           v.Add(new Voltage("CPU VCore", 0));
   408           v.Add(new Voltage("Voltage #2", 1, true));
   409           v.Add(new Voltage("Voltage #3", 2, true));
   410           v.Add(new Voltage("AVCC", 3, 34, 51, 0));
   411           v.Add(new Voltage("Voltage #5", 4, true));
   412           v.Add(new Voltage("5VSB", 5, 34, 51, 0));
   413           v.Add(new Voltage("VBAT", 6));
   414           t.Add(new Temperature("CPU", 0));
   415           t.Add(new Temperature("Auxiliary", 1));
   416           t.Add(new Temperature("System", 2));
   417           f.Add(new Fan("System", 0));
   418           f.Add(new Fan("CPU", 1));
   419           f.Add(new Fan("Auxiliary", 2));
   420           break;
   421         default:
   422           for (int i = 0; i < superIO.Voltages.Length; i++)
   423             v.Add(new Voltage("Voltage #" + (i + 1), i, true));
   424           for (int i = 0; i < superIO.Temperatures.Length; i++)
   425             t.Add(new Temperature("Temperature #" + (i + 1), i));
   426           for (int i = 0; i < superIO.Fans.Length; i++)
   427             f.Add(new Fan("Fan #" + (i + 1), i));
   428           break;
   429       }
   430 
   431       string formula = "Voltage = value + (value - Vf) * Ri / Rf.";
   432       foreach (Voltage voltage in v) 
   433         if (voltage.Index < superIO.Voltages.Length) {
   434           Sensor sensor = new Sensor(voltage.Name, voltage.Index, 
   435             voltage.Hidden, SensorType.Voltage, this, 
   436             new ParameterDescription[] {
   437             new ParameterDescription("Ri [kΩ]", "Input resistance.\n" + 
   438               formula, voltage.Ri),
   439             new ParameterDescription("Rf [kΩ]", "Reference resistance.\n" + 
   440               formula, voltage.Rf),
   441             new ParameterDescription("Vf [V]", "Reference voltage.\n" + 
   442               formula, voltage.Vf)
   443             });
   444           voltages.Add(sensor);
   445       }
   446 
   447       foreach (Temperature temperature in t) 
   448         if (temperature.Index < superIO.Temperatures.Length) {
   449         Sensor sensor = new Sensor(temperature.Name, temperature.Index,
   450           SensorType.Temperature, this, new ParameterDescription[] {
   451           new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
   452         });
   453         temperatures.Add(sensor);
   454       }
   455 
   456       foreach (Fan fan in f)
   457         if (fan.Index < superIO.Fans.Length) {
   458           Sensor sensor = new Sensor(fan.Name, fan.Index, SensorType.Fan,
   459             this, null);
   460           fans.Add(sensor);
   461         }
   462     }
   463 
   464     public override Identifier Identifier {
   465       get { return new Identifier("lpc", superIO.Chip.ToString().ToLower()); }
   466     }
   467 
   468     public override Image Icon {
   469       get { return icon; }
   470     }
   471 
   472     public override string Name {
   473       get { return name; }
   474     }
   475 
   476     public override string GetReport() {
   477       return superIO.GetReport();
   478     }
   479 
   480     public override void Update() {
   481       superIO.Update();
   482 
   483       foreach (Sensor sensor in voltages) {
   484         float? value = superIO.Voltages[sensor.Index];
   485         if (value.HasValue) {
   486           sensor.Value = value + (value - sensor.Parameters[2].Value) *
   487             sensor.Parameters[0].Value / sensor.Parameters[1].Value;
   488           ActivateSensor(sensor);
   489         }
   490       }
   491 
   492       foreach (Sensor sensor in temperatures) {
   493         float? value = superIO.Temperatures[sensor.Index];
   494         if (value.HasValue) {
   495           sensor.Value = value + sensor.Parameters[0].Value;
   496           ActivateSensor(sensor);
   497         }
   498       }
   499 
   500       foreach (Sensor sensor in fans) {
   501         float? value = superIO.Fans[sensor.Index];
   502         if (value.HasValue) {
   503           sensor.Value = value;
   504           if (value.Value > 0)
   505             ActivateSensor(sensor);
   506         }
   507       }
   508     }
   509 
   510     private class Voltage {
   511       public readonly string Name;
   512       public readonly int Index;
   513       public readonly float Ri;
   514       public readonly float Rf;
   515       public readonly float Vf;
   516       public readonly bool Hidden;
   517 
   518       public Voltage(string name, int index) :
   519         this(name, index, 0, 1, 0, false) { }
   520 
   521       public Voltage(string name, int index, bool hidden) :
   522         this(name, index, 0, 1, 0, hidden) { }
   523 
   524       public Voltage(string name, int index, float ri, float rf, float vf) :
   525         this(name, index, ri, rf, vf, false) { }
   526 
   527       public Voltage(string name, int index, float ri, float rf, float vf,
   528         bool hidden) {
   529         this.Name = name;
   530         this.Index = index;
   531         this.Ri = ri;
   532         this.Rf = rf;
   533         this.Vf = vf;
   534         this.Hidden = hidden;
   535       }
   536     }
   537 
   538     private class Temperature {
   539       public readonly string Name;
   540       public readonly int Index;
   541 
   542       public Temperature(string name, int index) {
   543         this.Name = name;
   544         this.Index = index;
   545       }
   546     }
   547 
   548     private class Fan {
   549       public readonly string Name;
   550       public readonly int Index;
   551 
   552       public Fan(string name, int index) {
   553         this.Name = name;
   554         this.Index = index;
   555       }
   556     }
   557   }
   558 }