Hardware/LPC/LPCGroup.cs
author moel.mich
Tue, 09 Feb 2010 18:52:52 +0000
changeset 36 32adc68f54f8
parent 31 c4d1fb76a9e1
child 54 f940fe2a7c2b
permissions -rw-r--r--
Added upper bound for valid fan RPM on IT87.
     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.Text;
    41 using System.Threading;
    42 
    43 namespace OpenHardwareMonitor.Hardware.LPC {
    44   public class LPCGroup : IGroup {
    45     private List<IHardware> hardware = new List<IHardware>();
    46 
    47     private Chip chip = Chip.Unknown;
    48 
    49     // I/O Ports
    50     private ushort[] REGISTER_PORTS = new ushort[] { 0x2e, 0x4e };
    51     private ushort[] VALUE_PORTS = new ushort[] { 0x2f, 0x4f };
    52 
    53     private ushort registerPort;
    54     private ushort valuePort;
    55 
    56     // Registers
    57     private const byte CONFIGURATION_CONTROL_REGISTER = 0x02;
    58     private const byte DEVCIE_SELECT_REGISTER = 0x07;
    59     private const byte CHIP_ID_REGISTER = 0x20;
    60     private const byte CHIP_REVISION_REGISTER = 0x21;
    61     private const byte BASE_ADDRESS_REGISTER = 0x60;
    62 
    63     private byte ReadByte(byte register) {
    64       WinRing0.WriteIoPortByte(registerPort, register);
    65       return WinRing0.ReadIoPortByte(valuePort);
    66     } 
    67 
    68     private ushort ReadWord(byte register) {
    69       return (ushort)((ReadByte(register) << 8) | 
    70         ReadByte((byte)(register + 1)));
    71     }
    72 
    73     private void Select(byte logicalDeviceNumber) {
    74       WinRing0.WriteIoPortByte(registerPort, DEVCIE_SELECT_REGISTER);
    75       WinRing0.WriteIoPortByte(valuePort, logicalDeviceNumber);
    76     }
    77 
    78     // ITE
    79     private const byte IT87_ENVIRONMENT_CONTROLLER_LDN = 0x04;    
    80 
    81     private void IT87Enter() {
    82       WinRing0.WriteIoPortByte(registerPort, 0x87);
    83       WinRing0.WriteIoPortByte(registerPort, 0x01);
    84       WinRing0.WriteIoPortByte(registerPort, 0x55);
    85       WinRing0.WriteIoPortByte(registerPort, 0x55);
    86     }
    87 
    88     internal void IT87Exit() {
    89       WinRing0.WriteIoPortByte(registerPort, CONFIGURATION_CONTROL_REGISTER);
    90       WinRing0.WriteIoPortByte(valuePort, 0x02);
    91     }
    92 
    93     // Winbond, Fintek
    94     private const byte FINTEK_VENDOR_ID_REGISTER = 0x23;
    95     private const ushort FINTEK_VENDOR_ID = 0x1934;
    96 
    97     private const byte WINBOND_HARDWARE_MONITOR_LDN = 0x0B;
    98 
    99     private const byte F71858_HARDWARE_MONITOR_LDN = 0x02;
   100     private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04;
   101 
   102     private void WinbondFintekEnter() {
   103       WinRing0.WriteIoPortByte(registerPort, 0x87);
   104       WinRing0.WriteIoPortByte(registerPort, 0x87);
   105     }
   106 
   107     private void WinbondFintekExit() {
   108       WinRing0.WriteIoPortByte(registerPort, 0xAA);      
   109     }
   110 
   111     public LPCGroup() {
   112       if (!WinRing0.IsAvailable)
   113         return;
   114 
   115       for (int i = 0; i < REGISTER_PORTS.Length; i++) {
   116         registerPort = REGISTER_PORTS[i];
   117         valuePort = VALUE_PORTS[i];
   118 
   119         WinbondFintekEnter();
   120 
   121         byte logicalDeviceNumber;
   122         byte id = ReadByte(CHIP_ID_REGISTER);
   123         byte revision = ReadByte(CHIP_REVISION_REGISTER);
   124         chip = Chip.Unknown;
   125         logicalDeviceNumber = 0;
   126         switch (id) {
   127           case 0x05:
   128             switch (revision) {
   129               case 0x41:
   130                 chip = Chip.F71882;
   131                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   132                 break;              
   133             } break;
   134           case 0x06:
   135             switch (revision) {             
   136               case 0x01:
   137                 chip = Chip.F71862;
   138                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   139                 break;              
   140             } break;
   141           case 0x07:
   142             switch (revision) {
   143               case 0x23:
   144                 chip = Chip.F71889;
   145                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   146                 break;              
   147             } break;
   148           case 0x08:
   149             switch (revision) {
   150               case 0x14:
   151                 chip = Chip.F71869;
   152                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   153                 break;              
   154             } break;
   155           case 0x52:
   156             switch (revision) {
   157               case 0x17:
   158               case 0x3A:
   159                 chip = Chip.W83627HF;
   160                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   161                 break;             
   162             } break;
   163           case 0x88:
   164             switch (revision & 0xF0) {
   165               case 0x60:
   166                 chip = Chip.W83627EHF;
   167                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   168                 break;
   169             } break;
   170           case 0xA0:
   171             switch (revision & 0xF0) {
   172               case 0x20: 
   173                 chip = Chip.W83627DHG;
   174                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;  
   175                 break;             
   176             } break;
   177           case 0xA5:
   178             switch (revision & 0xF0) {
   179               case 0x10:
   180                 chip = Chip.W83667HG;
   181                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   182                 break;
   183             } break;
   184           case 0xB0:
   185             switch (revision & 0xF0) {
   186               case 0x70:
   187                 chip = Chip.W83627DHGP;
   188                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   189                 break;             
   190             } break;
   191           case 0xB3:
   192             switch (revision & 0xF0) {
   193               case 0x50:
   194                 chip = Chip.W83667HGB;
   195                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   196                 break;
   197             } break; 
   198         }
   199         if (chip != Chip.Unknown) {
   200 
   201           Select(logicalDeviceNumber);
   202           ushort address = ReadWord(BASE_ADDRESS_REGISTER);
   203           Thread.Sleep(1);
   204           ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
   205 
   206           ushort vendorID = 0;
   207           if (chip == Chip.F71862 || chip == Chip.F71882 || chip == Chip.F71889)
   208             vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER);
   209 
   210           WinbondFintekExit();
   211 
   212           if (address != verify || address < 0x100 || (address & 0xF007) != 0)
   213             return;
   214           
   215           switch (chip) {
   216             case Chip.W83627DHG:
   217             case Chip.W83627DHGP:
   218             case Chip.W83627EHF:
   219             case Chip.W83627HF:
   220             case Chip.W83667HG:
   221             case Chip.W83667HGB:
   222               W836XX w836XX = new W836XX(chip, revision, address);
   223               if (w836XX.IsAvailable)
   224                 hardware.Add(w836XX);
   225               break;
   226             case Chip.F71862:
   227             case Chip.F71882:
   228             case Chip.F71889: 
   229               if (vendorID == FINTEK_VENDOR_ID)
   230                 hardware.Add(new F718XX(chip, address));
   231               break;
   232             case Chip.F71869:
   233               hardware.Add(new F718XX(chip, address));
   234               break;
   235             default: break;
   236           }
   237           
   238           return;
   239         }
   240 
   241         IT87Enter();
   242 
   243         switch (ReadWord(CHIP_ID_REGISTER)) {
   244           case 0x8716: chip = Chip.IT8716F; break;
   245           case 0x8718: chip = Chip.IT8718F; break;
   246           case 0x8720: chip = Chip.IT8720F; break;
   247           case 0x8726: chip = Chip.IT8726F; break;
   248           default: chip = Chip.Unknown; break;
   249         }
   250 
   251         if (chip != Chip.Unknown) {
   252           Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
   253           ushort address = ReadWord(BASE_ADDRESS_REGISTER);
   254           Thread.Sleep(1);
   255           ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
   256 
   257           IT87Exit();
   258 
   259           if (address != verify || address < 0x100 || (address & 0xF007) != 0)
   260             return;
   261 
   262           IT87XX it87 = new IT87XX(chip, address);
   263           if (it87.IsAvailable)
   264             hardware.Add(it87);
   265 
   266           return;
   267         }
   268       }   
   269     }
   270 
   271     public IHardware[] Hardware {
   272       get {
   273         return hardware.ToArray();
   274       }
   275     }
   276 
   277     public string GetReport() {
   278       return null;
   279     }
   280 
   281     public void Close() { }
   282   }
   283 }