Hardware/LPC/LPCIO.cs
author moel.mich
Mon, 24 May 2010 15:27:46 +0000
changeset 126 2354fdb91ac4
parent 110 411b72b73d8f
child 130 80065ab20b84
permissions -rw-r--r--
Extended the ITE super I/O voltage reading by adding hidden voltage sensors for unknown channels. Added a few known DFI and Gigabyte mainboard voltage configurations.
     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 LPCIO {
    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 LPCIO(Mainboard.Manufacturer mainboardManufacturer, 
   123       Mainboard.Model mainboardModel) 
   124     {
   125       if (!WinRing0.IsAvailable)
   126         return;
   127 
   128       for (int i = 0; i < REGISTER_PORTS.Length; i++) {
   129         registerPort = REGISTER_PORTS[i];
   130         valuePort = VALUE_PORTS[i];
   131 
   132         WinbondFintekEnter();
   133 
   134         byte logicalDeviceNumber;
   135         byte id = ReadByte(CHIP_ID_REGISTER);
   136         byte revision = ReadByte(CHIP_REVISION_REGISTER);
   137         chip = Chip.Unknown;
   138         logicalDeviceNumber = 0;
   139         switch (id) {
   140           case 0x05:
   141             switch (revision) {
   142               case 0x07:
   143                 chip = Chip.F71858;
   144                 logicalDeviceNumber = F71858_HARDWARE_MONITOR_LDN;
   145                 break;
   146               case 0x41:
   147                 chip = Chip.F71882;
   148                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   149                 break;              
   150             } break;
   151           case 0x06:
   152             switch (revision) {             
   153               case 0x01:
   154                 chip = Chip.F71862;
   155                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   156                 break;              
   157             } break;
   158           case 0x07:
   159             switch (revision) {
   160               case 0x23:
   161                 chip = Chip.F71889F;
   162                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   163                 break;              
   164             } break;
   165           case 0x08:
   166             switch (revision) {
   167               case 0x14:
   168                 chip = Chip.F71869;
   169                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   170                 break;              
   171             } break;
   172           case 0x09:
   173             switch (revision) {
   174               case 0x09:
   175                 chip = Chip.F71889ED;
   176                 logicalDeviceNumber = FINTEK_HARDWARE_MONITOR_LDN;
   177                 break;              
   178             } break;
   179           case 0x52:
   180             switch (revision) {
   181               case 0x17:
   182               case 0x3A:
   183               case 0x41:
   184                 chip = Chip.W83627HF;
   185                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   186                 break;             
   187             } break;
   188           case 0x82:
   189             switch (revision) {
   190               case 0x83:
   191                 chip = Chip.W83627THF;
   192                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   193                 break;
   194             } break;
   195           case 0x85:
   196             switch (revision) {
   197               case 0x41:
   198                 chip = Chip.W83687THF;
   199                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   200                 break;
   201             } break;
   202           case 0x88:
   203             switch (revision & 0xF0) {
   204               case 0x50:
   205               case 0x60:
   206                 chip = Chip.W83627EHF;
   207                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   208                 break;
   209             } break;
   210           case 0xA0:
   211             switch (revision & 0xF0) {
   212               case 0x20: 
   213                 chip = Chip.W83627DHG;
   214                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;  
   215                 break;             
   216             } break;
   217           case 0xA5:
   218             switch (revision & 0xF0) {
   219               case 0x10:
   220                 chip = Chip.W83667HG;
   221                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   222                 break;
   223             } break;
   224           case 0xB0:
   225             switch (revision & 0xF0) {
   226               case 0x70:
   227                 chip = Chip.W83627DHGP;
   228                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   229                 break;             
   230             } break;
   231           case 0xB3:
   232             switch (revision & 0xF0) {
   233               case 0x50:
   234                 chip = Chip.W83667HGB;
   235                 logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
   236                 break;
   237             } break; 
   238         }
   239         if (chip == Chip.Unknown) {
   240           if (id != 0 && id != 0xff) {
   241             WinbondFintekExit();
   242 
   243             report.Append("Chip ID: Unknown Winbond / Fintek with ID 0x"); 
   244             report.AppendLine(((id << 8) | revision).ToString("X"));
   245             report.AppendLine();
   246           }
   247         } else {
   248 
   249           Select(logicalDeviceNumber);
   250           ushort address = ReadWord(BASE_ADDRESS_REGISTER);          
   251           Thread.Sleep(1);
   252           ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
   253 
   254           ushort vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER);
   255 
   256           WinbondFintekExit();
   257 
   258           if (address != verify) {            
   259             report.Append("Chip ID: 0x"); 
   260             report.AppendLine(chip.ToString("X"));
   261             report.Append("Chip revision: 0x"); 
   262             report.AppendLine(revision.ToString("X"));
   263             report.AppendLine("Error: Address verification failed");
   264             report.AppendLine();
   265             return;
   266           }
   267 
   268           // some Fintek chips have address register offset 0x05 added already
   269           if ((address & 0x07) == 0x05)
   270             address &= 0xFFF8;
   271 
   272           if (address < 0x100 || (address & 0xF007) != 0) {            
   273             report.Append("Chip ID: 0x");
   274             report.AppendLine(chip.ToString("X"));
   275             report.Append("Chip revision: 0x");
   276             report.AppendLine(revision.ToString("X"));
   277             report.Append("Error: Invalid address 0x");
   278             report.AppendLine(address.ToString("X"));
   279             report.AppendLine();
   280             return;
   281           }
   282 
   283           switch (chip) {
   284             case Chip.W83627DHG:
   285             case Chip.W83627DHGP:
   286             case Chip.W83627EHF:
   287             case Chip.W83627HF:
   288             case Chip.W83627THF:
   289             case Chip.W83667HG:
   290             case Chip.W83667HGB:
   291             case Chip.W83687THF:
   292               W836XX w836XX = new W836XX(chip, revision, address);
   293               if (w836XX.IsAvailable)
   294                 hardware.Add(w836XX);
   295               break;
   296             case Chip.F71858:
   297             case Chip.F71862:
   298             case Chip.F71869:
   299             case Chip.F71882:
   300             case Chip.F71889ED:
   301             case Chip.F71889F:
   302               if (vendorID != FINTEK_VENDOR_ID) {
   303                 report.Append("Chip ID: 0x");
   304                 report.AppendLine(chip.ToString("X"));
   305                 report.Append("Chip revision: 0x");
   306                 report.AppendLine(revision.ToString("X"));
   307                 report.Append("Error: Invalid vendor ID 0x");
   308                 report.AppendLine(vendorID.ToString("X"));
   309                 report.AppendLine();
   310                 return;
   311               }
   312               hardware.Add(new F718XX(chip, address));
   313               break;
   314             default: break;
   315           }
   316           
   317           return;
   318         }
   319 
   320         IT87Enter();
   321 
   322         ushort chipID = ReadWord(CHIP_ID_REGISTER);
   323         switch (chipID) {
   324           case 0x8712: chip = Chip.IT8712F; break;
   325           case 0x8716: chip = Chip.IT8716F; break;
   326           case 0x8718: chip = Chip.IT8718F; break;
   327           case 0x8720: chip = Chip.IT8720F; break;
   328           case 0x8726: chip = Chip.IT8726F; break; 
   329           default: chip = Chip.Unknown; break;
   330         }
   331         if (chip == Chip.Unknown) {
   332           if (chipID != 0 && chipID != 0xffff) {
   333             IT87Exit();
   334 
   335             report.Append("Chip ID: Unknown ITE with ID 0x");
   336             report.AppendLine(chipID.ToString("X"));
   337             report.AppendLine();
   338           }
   339         } else {
   340           Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
   341           ushort address = ReadWord(BASE_ADDRESS_REGISTER);
   342           Thread.Sleep(1);
   343           ushort verify = ReadWord(BASE_ADDRESS_REGISTER);
   344 
   345           IT87Exit();
   346 
   347           if (address != verify || address < 0x100 || (address & 0xF007) != 0) {
   348             report.Append("Chip ID: 0x");
   349             report.AppendLine(chip.ToString("X"));            
   350             report.Append("Error: Invalid address 0x");
   351             report.AppendLine(address.ToString("X"));
   352             report.AppendLine();
   353             return;
   354           }
   355 
   356           IT87XX it87 = new IT87XX(chip, address, mainboardManufacturer, 
   357             mainboardModel);
   358           if (it87.IsAvailable)
   359             hardware.Add(it87);
   360 
   361           return;
   362         }
   363 
   364         SMSCEnter();
   365 
   366         chipID = ReadWord(CHIP_ID_REGISTER);
   367         switch (chipID) {
   368           default: chip = Chip.Unknown; break;
   369         }
   370         if (chip == Chip.Unknown) {
   371           if (chipID != 0 && chipID != 0xffff) {
   372             SMSCExit();
   373 
   374             report.Append("Chip ID: Unknown SMSC with ID 0x");
   375             report.AppendLine(chipID.ToString("X"));
   376             report.AppendLine();
   377           }
   378         } else {
   379           SMSCExit();
   380 
   381           return;
   382         }
   383       }   
   384     }
   385 
   386     public IHardware[] Hardware {
   387       get {
   388         return hardware.ToArray();
   389       }
   390     }
   391 
   392     public string GetReport() {
   393       if (report.Length > 0) {
   394         report.Insert(0, "LPCIO" + Environment.NewLine +
   395           Environment.NewLine);        
   396         return report.ToString();
   397       } else
   398         return null;
   399     }
   400   }
   401 }