Hardware/LPC/LPCGroup.cs
author moel.mich
Mon, 01 Mar 2010 22:12:29 +0000
changeset 67 bb5696abab23
parent 60 0e62c377c08c
child 68 d706e16a79c0
permissions -rw-r--r--
Added support for Winbond W83687THF and improved report output for LPC detection.
     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 
    46     private List<IHardware> hardware = new List<IHardware>();
    47     private StringBuilder report = new StringBuilder();
    48 
    49     private Chip chip = Chip.Unknown;
    50 
    51     // I/O Ports
    52     private ushort[] REGISTER_PORTS = new ushort[] { 0x2e, 0x4e };
    53     private ushort[] VALUE_PORTS = new ushort[] { 0x2f, 0x4f };
    54 
    55     private ushort registerPort;
    56     private ushort valuePort;
    57 
    58     // Registers
    59     private const byte CONFIGURATION_CONTROL_REGISTER = 0x02;
    60     private const byte DEVCIE_SELECT_REGISTER = 0x07;
    61     private const byte CHIP_ID_REGISTER = 0x20;
    62     private const byte CHIP_REVISION_REGISTER = 0x21;
    63     private const byte BASE_ADDRESS_REGISTER = 0x60;
    64 
    65     private byte ReadByte(byte register) {
    66       WinRing0.WriteIoPortByte(registerPort, register);
    67       return WinRing0.ReadIoPortByte(valuePort);
    68     } 
    69 
    70     private ushort ReadWord(byte register) {
    71       return (ushort)((ReadByte(register) << 8) | 
    72         ReadByte((byte)(register + 1)));
    73     }
    74 
    75     private void Select(byte logicalDeviceNumber) {
    76       WinRing0.WriteIoPortByte(registerPort, DEVCIE_SELECT_REGISTER);
    77       WinRing0.WriteIoPortByte(valuePort, logicalDeviceNumber);
    78     }
    79 
    80     // ITE
    81     private const byte IT87_ENVIRONMENT_CONTROLLER_LDN = 0x04;    
    82 
    83     private void IT87Enter() {
    84       WinRing0.WriteIoPortByte(registerPort, 0x87);
    85       WinRing0.WriteIoPortByte(registerPort, 0x01);
    86       WinRing0.WriteIoPortByte(registerPort, 0x55);
    87       WinRing0.WriteIoPortByte(registerPort, 0x55);
    88     }
    89 
    90     internal void IT87Exit() {
    91       WinRing0.WriteIoPortByte(registerPort, CONFIGURATION_CONTROL_REGISTER);
    92       WinRing0.WriteIoPortByte(valuePort, 0x02);
    93     }
    94 
    95     // Winbond, Fintek
    96     private const byte FINTEK_VENDOR_ID_REGISTER = 0x23;
    97     private const ushort FINTEK_VENDOR_ID = 0x1934;
    98 
    99     private const byte WINBOND_HARDWARE_MONITOR_LDN = 0x0B;
   100 
   101     private const byte F71858_HARDWARE_MONITOR_LDN = 0x02;
   102     private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04;
   103 
   104     private void WinbondFintekEnter() {
   105       WinRing0.WriteIoPortByte(registerPort, 0x87);
   106       WinRing0.WriteIoPortByte(registerPort, 0x87);
   107     }
   108 
   109     private void WinbondFintekExit() {
   110       WinRing0.WriteIoPortByte(registerPort, 0xAA);      
   111     }
   112 
   113     // SMSC
   114     private void SMSCEnter() {
   115       WinRing0.WriteIoPortByte(registerPort, 0x55);
   116     }
   117 
   118     private void SMSCExit() {
   119       WinRing0.WriteIoPortByte(registerPort, 0xAA);
   120     }
   121 
   122     public LPCGroup() {
   123       if (!WinRing0.IsAvailable)
   124         return;
   125 
   126       for (int i = 0; i < REGISTER_PORTS.Length; i++) {
   127         registerPort = REGISTER_PORTS[i];
   128         valuePort = VALUE_PORTS[i];
   129 
   130         WinbondFintekEnter();
   131 
   132         byte logicalDeviceNumber;
   133         byte id = ReadByte(CHIP_ID_REGISTER);
   134         byte revision = ReadByte(CHIP_REVISION_REGISTER);
   135         chip = Chip.Unknown;
   136         logicalDeviceNumber = 0;
   137         switch (id) {
   138           case 0x05:
   139             switch (revision) {
   140               case 0x41:
   141                 chip = Chip.F71882;
   142                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   143                 break;              
   144             } break;
   145           case 0x06:
   146             switch (revision) {             
   147               case 0x01:
   148                 chip = Chip.F71862;
   149                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   150                 break;              
   151             } break;
   152           case 0x07:
   153             switch (revision) {
   154               case 0x23:
   155                 chip = Chip.F71889;
   156                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   157                 break;              
   158             } break;
   159           case 0x08:
   160             switch (revision) {
   161               case 0x14:
   162                 chip = Chip.F71869;
   163                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   164                 break;              
   165             } break;
   166           case 0x52:
   167             switch (revision) {
   168               case 0x17:
   169               case 0x3A:
   170                 chip = Chip.W83627HF;
   171                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   172                 break;             
   173             } break;
   174           case 0x82:
   175             switch (revision) {
   176               case 0x83:
   177                 chip = Chip.W83627THF;
   178                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   179                 break;
   180             } break;
   181           case 0x85:
   182             switch (revision) {
   183               case 0x41:
   184                 chip = Chip.W83687THF;
   185                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   186                 break;
   187             } break;
   188           case 0x88:
   189             switch (revision & 0xF0) {
   190               case 0x60:
   191                 chip = Chip.W83627EHF;
   192                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   193                 break;
   194             } break;
   195           case 0xA0:
   196             switch (revision & 0xF0) {
   197               case 0x20: 
   198                 chip = Chip.W83627DHG;
   199                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;  
   200                 break;             
   201             } break;
   202           case 0xA5:
   203             switch (revision & 0xF0) {
   204               case 0x10:
   205                 chip = Chip.W83667HG;
   206                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   207                 break;
   208             } break;
   209           case 0xB0:
   210             switch (revision & 0xF0) {
   211               case 0x70:
   212                 chip = Chip.W83627DHGP;
   213                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   214                 break;             
   215             } break;
   216           case 0xB3:
   217             switch (revision & 0xF0) {
   218               case 0x50:
   219                 chip = Chip.W83667HGB;
   220                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   221                 break;
   222             } break; 
   223         }
   224         if (chip == Chip.Unknown) {
   225           if (id != 0 && id != 0xff) {
   226             WinbondFintekExit();
   227 
   228             report.Append("Chip ID: Unknown Winbond / Fintek with ID 0x"); 
   229             report.AppendLine(((id << 8) | revision).ToString("X"));
   230             report.AppendLine();
   231           }
   232         } else {
   233 
   234           Select(logicalDeviceNumber);
   235           ushort address = ReadWord(BASE_ADDRESS_REGISTER);          
   236           Thread.Sleep(1);
   237           ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
   238           
   239           ushort vendorID = 0;
   240           if (chip == Chip.F71862 || chip == Chip.F71882 || chip == Chip.F71889)
   241             vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER);
   242 
   243           WinbondFintekExit();
   244 
   245           if (address != verify) {            
   246             report.Append("Chip ID: 0x"); 
   247             report.AppendLine(chip.ToString("X"));
   248             report.Append("Chip revision: 0x"); 
   249             report.AppendLine(revision.ToString("X"));
   250             report.AppendLine("Error: Address verification failed");
   251             report.AppendLine();
   252             return;
   253           }
   254 
   255           // some Fintek chips have address register offset 0x05 added already
   256           if ((address & 0x07) == 0x05)
   257             address &= 0xFFF8;
   258 
   259           if (address < 0x100 || (address & 0xF007) != 0) {            
   260             report.Append("Chip ID: 0x");
   261             report.AppendLine(chip.ToString("X"));
   262             report.Append("Chip revision: 0x");
   263             report.AppendLine(revision.ToString("X"));
   264             report.Append("Error: Invalid address 0x");
   265             report.AppendLine(address.ToString("X"));
   266             report.AppendLine();
   267             return;
   268           }
   269 
   270           switch (chip) {
   271             case Chip.W83627DHG:
   272             case Chip.W83627DHGP:
   273             case Chip.W83627EHF:
   274             case Chip.W83627HF:
   275             case Chip.W83627THF:
   276             case Chip.W83667HG:
   277             case Chip.W83667HGB:
   278             case Chip.W83687THF:
   279               W836XX w836XX = new W836XX(chip, revision, address);
   280               if (w836XX.IsAvailable)
   281                 hardware.Add(w836XX);
   282               break;
   283             case Chip.F71862:
   284             case Chip.F71882:
   285             case Chip.F71889: 
   286               if (vendorID == FINTEK_VENDOR_ID)
   287                 hardware.Add(new F718XX(chip, address));
   288               break;
   289             case Chip.F71869:
   290               hardware.Add(new F718XX(chip, address));
   291               break;
   292             default: break;
   293           }
   294           
   295           return;
   296         }
   297 
   298         IT87Enter();
   299 
   300         ushort chipID = ReadWord(CHIP_ID_REGISTER);
   301         switch (chipID) {
   302           case 0x8716: chip = Chip.IT8716F; break;
   303           case 0x8718: chip = Chip.IT8718F; break;
   304           case 0x8720: chip = Chip.IT8720F; break;
   305           case 0x8726: chip = Chip.IT8726F; break; 
   306           default: chip = Chip.Unknown; break;
   307         }
   308         if (chip == Chip.Unknown) {
   309           if (chipID != 0 && chipID != 0xffff) {
   310             IT87Exit();
   311 
   312             report.Append("Chip ID: Unknown ITE with ID 0x");
   313             report.AppendLine(chipID.ToString("X"));
   314             report.AppendLine();
   315           }
   316         } else {
   317           Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
   318           ushort address = ReadWord(BASE_ADDRESS_REGISTER);
   319           Thread.Sleep(1);
   320           ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
   321 
   322           IT87Exit();
   323 
   324           if (address != verify || address < 0x100 || (address & 0xF007) != 0) {
   325             report.Append("Chip ID: 0x");
   326             report.AppendLine(chip.ToString("X"));            
   327             report.Append("Error: Invalid address 0x");
   328             report.AppendLine(address.ToString("X"));
   329             report.AppendLine();
   330             return;
   331           }
   332 
   333           IT87XX it87 = new IT87XX(chip, address);
   334           if (it87.IsAvailable)
   335             hardware.Add(it87);
   336 
   337           return;
   338         }
   339 
   340         SMSCEnter();
   341 
   342         chipID = ReadWord(CHIP_ID_REGISTER);
   343         switch (chipID) {
   344           default: chip = Chip.Unknown; break;
   345         }
   346         if (chip == Chip.Unknown) {
   347           if (chipID != 0 && chipID != 0xffff) {
   348             SMSCExit();
   349 
   350             report.Append("Chip ID: Unknown SMSC with ID 0x");
   351             report.AppendLine(chipID.ToString("X"));
   352             report.AppendLine();
   353           }
   354         } else {
   355           SMSCExit();
   356 
   357           return;
   358         }
   359       }   
   360     }
   361 
   362     public IHardware[] Hardware {
   363       get {
   364         return hardware.ToArray();
   365       }
   366     }
   367 
   368     public string GetReport() {
   369       if (report.Length > 0) {
   370         report.Insert(0, "LPCIO" + Environment.NewLine +
   371           Environment.NewLine);        
   372         return report.ToString();
   373       } else
   374         return null;
   375     }
   376 
   377     public void Close() { }
   378   }
   379 }