Hardware/LPC/LPCGroup.cs
author moel.mich
Fri, 19 Feb 2010 18:33:08 +0000
changeset 54 f940fe2a7c2b
parent 34 dc276daadb2c
child 60 0e62c377c08c
permissions -rw-r--r--
Added support for Winbond W83627THF super I/O chip.
     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 0x82:
   164             switch (revision) {
   165               case 0x83:
   166                 chip = Chip.W83627THF;
   167                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   168                 break;
   169             } break;
   170           case 0x88:
   171             switch (revision & 0xF0) {
   172               case 0x60:
   173                 chip = Chip.W83627EHF;
   174                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   175                 break;
   176             } break;
   177           case 0xA0:
   178             switch (revision & 0xF0) {
   179               case 0x20: 
   180                 chip = Chip.W83627DHG;
   181                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;  
   182                 break;             
   183             } break;
   184           case 0xA5:
   185             switch (revision & 0xF0) {
   186               case 0x10:
   187                 chip = Chip.W83667HG;
   188                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   189                 break;
   190             } break;
   191           case 0xB0:
   192             switch (revision & 0xF0) {
   193               case 0x70:
   194                 chip = Chip.W83627DHGP;
   195                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   196                 break;             
   197             } break;
   198           case 0xB3:
   199             switch (revision & 0xF0) {
   200               case 0x50:
   201                 chip = Chip.W83667HGB;
   202                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   203                 break;
   204             } break; 
   205         }
   206         if (chip != Chip.Unknown) {
   207 
   208           Select(logicalDeviceNumber);
   209           ushort address = ReadWord(BASE_ADDRESS_REGISTER);
   210           Thread.Sleep(1);
   211           ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
   212 
   213           ushort vendorID = 0;
   214           if (chip == Chip.F71862 || chip == Chip.F71882 || chip == Chip.F71889)
   215             vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER);
   216 
   217           WinbondFintekExit();
   218 
   219           if (address != verify || address < 0x100 || (address & 0xF007) != 0)
   220             return;
   221           
   222           switch (chip) {
   223             case Chip.W83627DHG:
   224             case Chip.W83627DHGP:
   225             case Chip.W83627EHF:
   226             case Chip.W83627HF:
   227             case Chip.W83627THF:
   228             case Chip.W83667HG:
   229             case Chip.W83667HGB:
   230               W836XX w836XX = new W836XX(chip, revision, address);
   231               if (w836XX.IsAvailable)
   232                 hardware.Add(w836XX);
   233               break;
   234             case Chip.F71862:
   235             case Chip.F71882:
   236             case Chip.F71889: 
   237               if (vendorID == FINTEK_VENDOR_ID)
   238                 hardware.Add(new F718XX(chip, address));
   239               break;
   240             case Chip.F71869:
   241               hardware.Add(new F718XX(chip, address));
   242               break;
   243             default: break;
   244           }
   245           
   246           return;
   247         }
   248 
   249         IT87Enter();
   250 
   251         switch (ReadWord(CHIP_ID_REGISTER)) {
   252           case 0x8716: chip = Chip.IT8716F; break;
   253           case 0x8718: chip = Chip.IT8718F; break;
   254           case 0x8720: chip = Chip.IT8720F; break;
   255           case 0x8726: chip = Chip.IT8726F; break;
   256           default: chip = Chip.Unknown; break;
   257         }
   258 
   259         if (chip != Chip.Unknown) {
   260           Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
   261           ushort address = ReadWord(BASE_ADDRESS_REGISTER);
   262           Thread.Sleep(1);
   263           ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
   264 
   265           IT87Exit();
   266 
   267           if (address != verify || address < 0x100 || (address & 0xF007) != 0)
   268             return;
   269 
   270           IT87XX it87 = new IT87XX(chip, address);
   271           if (it87.IsAvailable)
   272             hardware.Add(it87);
   273 
   274           return;
   275         }
   276       }   
   277     }
   278 
   279     public IHardware[] Hardware {
   280       get {
   281         return hardware.ToArray();
   282       }
   283     }
   284 
   285     public string GetReport() {
   286       return null;
   287     }
   288 
   289     public void Close() { }
   290   }
   291 }