| 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@1 |     50 |     private const ushort REGISTER_PORT = 0x2e;
 | 
| moel@1 |     51 |     private const ushort VALUE_PORT = 0x2f;
 | 
| moel@1 |     52 | 
 | 
| moel@1 |     53 |     // Registers
 | 
| moel@1 |     54 |     private const byte CONFIGURATION_CONTROL_REGISTER = 0x02;
 | 
| moel@1 |     55 |     private const byte DEVCIE_SELECT_REGISTER = 0x07;
 | 
| moel@1 |     56 |     private const byte CHIP_ID_REGISTER = 0x20;
 | 
| moel@1 |     57 |     private const byte CHIP_REVISION_REGISTER = 0x21;
 | 
| moel@1 |     58 | 
 | 
| moel@1 |     59 |     private static byte ReadByte(byte register) {
 | 
| moel@1 |     60 |       WinRing0.WriteIoPortByte(REGISTER_PORT, register);
 | 
| moel@1 |     61 |       return WinRing0.ReadIoPortByte(VALUE_PORT);
 | 
| moel@1 |     62 |     }
 | 
| moel@1 |     63 | 
 | 
| moel@1 |     64 |     private static ushort ReadWord(byte register) {
 | 
| moel@1 |     65 |       ushort value;
 | 
| moel@1 |     66 |       WinRing0.WriteIoPortByte(REGISTER_PORT, register);
 | 
| moel@1 |     67 |       value = (ushort)(((ushort)WinRing0.ReadIoPortByte(VALUE_PORT)) << 8);
 | 
| moel@1 |     68 |       WinRing0.WriteIoPortByte(REGISTER_PORT, (byte)(register + 1));
 | 
| moel@1 |     69 |       value |= (ushort)WinRing0.ReadIoPortByte(VALUE_PORT);
 | 
| moel@1 |     70 |       return value;
 | 
| moel@1 |     71 |     }
 | 
| moel@1 |     72 | 
 | 
| moel@1 |     73 |     private static void Select(byte logicalDeviceNumber) {
 | 
| moel@1 |     74 |       WinRing0.WriteIoPortByte(REGISTER_PORT, DEVCIE_SELECT_REGISTER);
 | 
| moel@1 |     75 |       WinRing0.WriteIoPortByte(VALUE_PORT, logicalDeviceNumber);
 | 
| moel@1 |     76 |     }
 | 
| moel@1 |     77 | 
 | 
| moel@1 |     78 |     // IT87
 | 
| moel@1 |     79 |     private const ushort IT8716F_CHIP_ID = 0x8716;
 | 
| moel@1 |     80 |     private const ushort IT8718F_CHIP_ID = 0x8718;
 | 
| moel@1 |     81 |     private const ushort IT8720F_CHIP_ID = 0x8720;
 | 
| moel@1 |     82 |     private const ushort IT8726F_CHIP_ID = 0x8726;
 | 
| moel@1 |     83 | 
 | 
| moel@1 |     84 |     private const byte IT87_ENVIRONMENT_CONTROLLER_LDN = 0x04;
 | 
| moel@1 |     85 |     private const byte IT87_ENVIRONMENT_CONTROLLER_BASE_ADDR_REG = 0x60;
 | 
| moel@1 |     86 | 
 | 
| moel@1 |     87 |     private static void IT87Enter() {
 | 
| moel@1 |     88 |       WinRing0.WriteIoPortByte(REGISTER_PORT, 0x87);
 | 
| moel@1 |     89 |       WinRing0.WriteIoPortByte(REGISTER_PORT, 0x01);
 | 
| moel@1 |     90 |       WinRing0.WriteIoPortByte(REGISTER_PORT, 0x55);
 | 
| moel@1 |     91 |       WinRing0.WriteIoPortByte(REGISTER_PORT, 0x55);
 | 
| moel@1 |     92 |     }
 | 
| moel@1 |     93 | 
 | 
| moel@1 |     94 |     internal static void IT87Exit() {
 | 
| moel@1 |     95 |       WinRing0.WriteIoPortByte(REGISTER_PORT, CONFIGURATION_CONTROL_REGISTER);
 | 
| moel@1 |     96 |       WinRing0.WriteIoPortByte(VALUE_PORT, 0x02);
 | 
| moel@1 |     97 |     }
 | 
| moel@1 |     98 | 
 | 
| moel@1 |     99 |     // Winbond
 | 
| moel@1 |    100 |     private static void WinbondEnter() {
 | 
| moel@1 |    101 |       WinRing0.WriteIoPortByte(REGISTER_PORT, 0x87);
 | 
| moel@1 |    102 |       WinRing0.WriteIoPortByte(REGISTER_PORT, 0x87);
 | 
| moel@1 |    103 |     }
 | 
| moel@1 |    104 | 
 | 
| moel@1 |    105 |     private static void WinbondExit() {
 | 
| moel@1 |    106 |       WinRing0.WriteIoPortByte(REGISTER_PORT, 0xAA);      
 | 
| moel@1 |    107 |     }
 | 
| moel@1 |    108 | 
 | 
| moel@1 |    109 |     public LPCGroup() {
 | 
| moel@1 |    110 |       if (!WinRing0.IsAvailable)
 | 
| moel@1 |    111 |         return;
 | 
| moel@1 |    112 | 
 | 
| moel@1 |    113 |       WinbondEnter();
 | 
| moel@1 |    114 | 
 | 
| moel@1 |    115 |       byte id = ReadByte(CHIP_ID_REGISTER);
 | 
| moel@1 |    116 |       byte revision = ReadByte(CHIP_REVISION_REGISTER);
 | 
| moel@1 |    117 |       switch (id) {
 | 
| moel@1 |    118 |         case 0xA0:
 | 
| moel@1 |    119 |           switch (revision & 0xF0) {
 | 
| moel@1 |    120 |             case 0x20: chip = Chip.W83627DHG; break;
 | 
| moel@1 |    121 |             default: chip = Chip.Unknown; break;
 | 
| moel@1 |    122 |           } break;
 | 
| moel@1 |    123 |         default: chip = Chip.Unknown; break;
 | 
| moel@1 |    124 |       }
 | 
| moel@1 |    125 |       if (chip != Chip.Unknown) {
 | 
| moel@1 |    126 | 
 | 
| moel@1 |    127 |         WinbondExit();
 | 
| moel@1 |    128 | 
 | 
| moel@1 |    129 |         W83627DHG w83627dhg = new W83627DHG(revision);
 | 
| moel@1 |    130 |         if (w83627dhg.IsAvailable)
 | 
| moel@1 |    131 |           hardware.Add(w83627dhg);
 | 
| moel@1 |    132 |         return;
 | 
| moel@1 |    133 |       }
 | 
| moel@1 |    134 | 
 | 
| moel@1 |    135 |       IT87Enter();
 | 
| moel@1 |    136 | 
 | 
| moel@1 |    137 |       switch (ReadWord(CHIP_ID_REGISTER)) {
 | 
| moel@1 |    138 |         case 0x8716: chip = Chip.IT8716F; break;
 | 
| moel@1 |    139 |         case 0x8718: chip = Chip.IT8718F; break;
 | 
| moel@1 |    140 |         case 0x8720: chip = Chip.IT8720F; break;
 | 
| moel@1 |    141 |         case 0x8726: chip = Chip.IT8726F; break;
 | 
| moel@1 |    142 |         default: chip = Chip.Unknown; break;
 | 
| moel@1 |    143 |       }
 | 
| moel@1 |    144 | 
 | 
| moel@1 |    145 |       if (chip != Chip.Unknown) {        
 | 
| moel@1 |    146 |         Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
 | 
| moel@1 |    147 |         ushort address = ReadWord(IT87_ENVIRONMENT_CONTROLLER_BASE_ADDR_REG);
 | 
| moel@1 |    148 |         Thread.Sleep(1);
 | 
| moel@1 |    149 |         ushort verify = ReadWord(IT87_ENVIRONMENT_CONTROLLER_BASE_ADDR_REG);
 | 
| moel@1 |    150 | 
 | 
| moel@1 |    151 |         IT87Exit();
 | 
| moel@1 |    152 | 
 | 
| moel@1 |    153 |         if (address != verify || address == 0 || (address & 0xF007) != 0)
 | 
| moel@1 |    154 |           return;
 | 
| moel@1 |    155 | 
 | 
| moel@1 |    156 |         IT87 it87 = new IT87(chip, address);
 | 
| moel@1 |    157 |         if (it87.IsAvailable)
 | 
| moel@1 |    158 |           hardware.Add(it87);
 | 
| moel@1 |    159 |         
 | 
| moel@1 |    160 |         return;
 | 
| moel@1 |    161 |       }                
 | 
| moel@1 |    162 |     }
 | 
| moel@1 |    163 | 
 | 
| moel@1 |    164 |     public IHardware[] Hardware {
 | 
| moel@1 |    165 |       get {
 | 
| moel@1 |    166 |         return hardware.ToArray();
 | 
| moel@1 |    167 |       }
 | 
| moel@1 |    168 |     }
 | 
| moel@1 |    169 | 
 | 
| moel@1 |    170 |     public string GetReport() {
 | 
| moel@1 |    171 |       return null;
 | 
| moel@1 |    172 |     }
 | 
| moel@1 |    173 | 
 | 
| moel@1 |    174 |     public void Close() { }
 | 
| moel@1 |    175 |   }
 | 
| moel@1 |    176 | }
 |