From 53d5b66e18e68ef392960a259eb7c1e24c670f84 Mon Sep 17 00:00:00 2001 From: Packit Date: Sep 04 2020 13:02:21 +0000 Subject: lm_sensors-3.4.0 base --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d7c1e0b --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# .gitignore for lm-sensors git tree +# +# NB: Please use the 'git ls-files -i --exclude-standard' +# command after changing this file, to see if there are +# any tracked files which get ignored after the change. + +# Generated executables +prog/dump/isadump +prog/dump/isaset +prog/sensord/sensord +prog/sensors/sensors +lib/test/test-scanner + +# Generated shared objects +*.a +*.so* + +# Intermediate objects +*.r[do] +*.a[do] +*.l[do] + +# Generated source code +lib/conf-lex.c +lib/conf-parse.c +lib/conf-parse.h + +# Patching artifacts +*.orig diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..6efba0f --- /dev/null +++ b/CHANGES @@ -0,0 +1,533 @@ +lm-sensors CHANGES file +----------------------- + +SVN HEAD + sensors.1: Add reference to sensors-detect + Document -j option (json output) + sensors: Add support for json output + sensors-detect: Fix systemd paths + Add detection of Fintek F81768 + Only probe I/O ports on x86 + Add detection of Nuvoton NCT6793D + Add detection of Microchip MCP9808 + Mark F71868A as supported by the f71882fg driver + Mark F81768D as supported by the f71882fg driver + Mark F81866D as supported by the f71882fg driver + Add detection of various ITE chips + Add detection of Nuvoton NCT6795D + Add detection of DDR4 SPD + Add detection of ITE IT8987D + Add detection of AMD Family 17h temperature sensors + Add detection of AMD KERNCZ SMBus controller + Add detection of various Intel SMBus controllers + Add detection of Giantec GT30TS00 + Add detection of ONS CAT34TS02C and CAT34TS04 + Add detection of AMD Family 15h Model 60+ temperature sensors + Add detection of Nuvoton NCT6796D + Add detection of AMD Family 15h Model 70+ temperature sensors + configs: Add sample configuration files. + sensors.conf.default: Add hardwired inputs of NCT6795D + vt1211_pwm: replaced deprecated sub shell syntax + pwmconfig: replaced deprecated sub shell syntax + fancontrol: replaced deprecated sub shell syntax + fancontrol.8: replaced deprecated sub shell syntax + +3.4.0 (2015-06-25) + documentation: Update the note about libsensors license + sensors.conf.5: Enhance the hysteresis documentation + sensors.conf.default: Add support for NCT6779 and NCT6791 + libsensors: Get rid of arbitrary limit on per-type sensor count + Add support for temperature min and critical min hysteresis + Fix sparse warnings + sensors: Add support for temperature min and critical min hysteresis + fancontrol: Deal with moving hwmon attributes + Fix shell error when FCFANS is not set + Reduce memory consumption (#2391) + healthd: Avoid using external commands + sensors-detect: Add detection of ADC128D818 + Add detection of AMD family 16h Kabini and Mullins + Add detection of ITE IT8620E and IT8623E + Add detection of TMP441, TMP442, LM95233, LM95234, + and LM95235 + Add detection of NCT7802Y + Print kernel version and processor information + Add detection of NCT6792D + Add reference to nct6683 driver + Show that NCT6102D/6104D/6106D are supported by nct6775 driver + Show NCT5573D as compatible to NCT6776F with same chip ID + Document support for EMC1402, EMC1404, and EMC1424 + Detect new revisions of EMC14xx + Add detection of EMC1422 + Document driver support for TMP431 and TMP432 + Add detection of TMP400 and TMP435 + Add detection of IT8786E + Add detection of IT8780F + Add detection of IT8731F and IT8732F + Add detection of Intel 5500/5520/X58 + Loosen detection rules for TS3000/TSE2002 + Add detection of TSE2004 and TS3001 + Document driver support for NCT7802Y + Add detection of NCT7904D + Add detection of IT8790E + Fix graphics cards detection (#2386, #2392) + Skip more addresses on graphics card I2C bus (#2392) + +3.3.5 "Happy Birthday Beddy" (2014-01-22) + libsensors: Improve documentation of two functions + Increase MAX_SENSORS_PER_TYPE to 33 + init: Fix EnvironmentFile in service files + Drop syslog.target dependency from service files + sensors-conf-convert: Add a manual page + sensors-detect: Report built-in drivers as such + Use modules.builtin instead of /sys/module + Handle built-in modules properly + Add detection of NCT6791D + Add detection of NCT6681D, NCT6682D, and NCT6683D + Add detection of F71868A + Add detection of IT8603E + Add two PCI IDs for new family 15h AMD processors + Introduce automatic mode (--auto) + Detect incorrect non-interactive runs + Rework option handling + Fix use of uninitialized value 'vendor_id' on ppc64 + Add detection of TMP451 + Add detection of SMSC EMC2104 + +3.3.4 (2013-05-27) + sensors.conf.5: Mention "sensors -u" to get the raw feature names + sensors: Clarify what option -u is good for + fancontrol: Fix handling of absolute paths in config + pwmconfig: Print the initial PWM values + Raise the detection threshold to 3/4 + Properly deal with multiple fan control + sensors-detect: Add detection of AMD family 16h power sensors + Map IT8771E, IT8772E, IT8782F and IT8783F to it87 + Use /sys/module instead of /proc/modules where available + Drop legacy sysconfig configuration file syntax + Stay alive when /dev/port is missing + Add detection of IT8752F + Add detection of MCP98244 + Add detection of LM95234 + Add detection of TMP431/TMP432 + Update Nuvoton chip information and NCT6106D chip detection + Drop unreliable DS1621/DS1631 detection + +3.3.3 "Happy Birthday Sophie" (2012-11-06) + documentation: Update fan-divisors, fan divisors are optional + libsensors: Fix warning about library path not in /etc/ld.so.conf + sensors: Fix libiconv linkage need detection in rare corner case + Add support for humidity output + Add long switches to manual page + sensors-detect: Don't choke on systems without PCI + Avoid probing EDID addresses on graphics cards (#2386) + Add detection of NCT6779D and NCT6102D/NCT6106D + Add detection of SMSC LPC47N217 and SIO10N268 + Do not scan I2C adapters on graphics cards by default + Fix parent class discovery when multiplexer is present + +3.3.2 (2012-03-14) + libsensors: Added support for new sysfs attributes + Change sysfs detection to survive upcoming kernel changes + sensord: Fix memory leaks revealed by valgrind + Minor performance improvements + sensors: Added support for new sysfs attributes + Display both instantaneous and average power if available. + Report thermal sensor type 1 as CPU diode + Align power values better + Fix power interval output + fancontrol: Support setup where one PWM output controls several fans + Output error messages to stderr + sensors-detect: Stop calling for PIIX5 SMBus testers + Improve filtering of fake DMI data + Print DMI system/product version if available + Fix loading of the cpuid module + Make LM73 detection less problematic + Add detection of National Semiconductor LM96163 + Add detection of GMT G781 + Properly handle Super-I/O chips without logical device + Add detection of National Semiconductor LM96080 + Add detection of ITE IT8771E + Add detection of ITE IT8781F, IT8782F and IT8783F + Add detection of ITE IT8510E/TE/G, IT8511E/TE/G, + IT8513E/F/G, and IT8518E + Add detection of ST Microelectronics STTS2002 and STTS3000 + Add detection of IDT TSE2002GB2, TS3000GB2, Microchip MCP9804, + and Atmel AT30TS00 + +3.3.1 (2011-07-21) + isadump: Add support for word (16-bit) and long (32-bit) reads + isaset: Add support for word (16-bit) and long (32-bit) writes + sensors.conf.default: Add a section for the EMC6W201 + sensors-detect: Add AMD family 15h CPU detection + Add detection of ADT7461A / NCT1008 + Add detection of ITE IT8516E/F/G + Integrate with systemd + Drop unreliable smart battery detection + Add detection of SMSC EMC6W201 + Drop unreliable detection of Maxim MAX6650 + Add detection of SMSC EMC2300 + Add detection of MAX6642 + Add detection of ITE IT8772E + Don't advertise the ipmisensors driver + Add detection of SA56004 + Add detection of LM95245 + +3.3.0 (2011-03-28) + Makefile: Check for bison and flex + libsensors: Add support for intrusion detection (#2370) + Compute MAX_SUBFEATURES at run-time (#2378) + Compute MAX_*_SENSOR_TYPES at build time (#2378) + Add support for new sysfs attributes (#2379) + Add support for humidity sensors + Limit symbol visibility + sensors.conf.default: Add a section for the W83627THF + Add a section for the SCH5127 + Add a section for the W83627UHG + Add a section for the W83795G/ADG + Add a section for the F81865F + sensors: Display 3 decimal places in raw output + Add support for intrusion detection (#2370) + Fix automatic unit selection of 0 value + Added support for additional sensor attributes (#2379) + sensors-detect: Improve LM90 and W83L771 detection + Fix error seen if I2C bus numbers are not sequential + Add detection of SMSC EMC1423 + Add detection of the Analog Devices ADT7410 + Add detection of the National Semiconductor LM94 + Add detection of the ITE IT8728F + Implement universal detection for coretemp (#2381) + Add detection of Maxim MAX6639 + Add detection of SMSC EMC1023, EMC1043, EMC1053, and EMC1063 + Add detection of Nuvoton NCT5571D, NCT5577D and NCT6776F + Add detection of SMSC EMC1002, EMC1033, EMC1046, EMC1047, + EMC1072, EMC1073, EMC1074, EMC1402, and EMC1424 + Fixed address ranges checked for SMSC EMC1403 and EMC1404. + Fix detection of SPD EEPROM on DDR3 memory modules + Add detection of AMD family 12h and 14h thermal sensors + Add detection of EMC6D103S + Add detection of National Semiconductor LM75A + Count DMI chassis type 8 as a laptop + Add detection of SMSC SCH5627 + Add detection of many Fintek Super-I/O devices + +3.2.0 (2010-10-10) + libsensors: Increase MAX_SENSORS_PER_TYPE to 24 + Map individual beep features + Change license to LGPL + pwmconfig: Sample all fan speeds before returning to full speed (#2380) + Wait for fans to return to full speed only once per PWM + Drop legacy invocations of cut + sensors.conf.default: W83667HG config is similar to W83627EHF/DHG + sensord: Fix support of multiple chips (#2377) + sensors: Properly handle sensor input read errors + sensors-detect: Give udev time to settle before accessing i2c nodes + Add support for Intel PCH (SMBus) + Add support for SMSC EMC1403 and EMC1404 + Fix detection of RB-C3 AMD Family 10h CPU + Add support for SMSC EMC2103 + Add support for Fintek F71889ED + Add support for ITE IT8721F + Fix Maxim MAX6690 support + Fix handling of duplicate detections + Add support for STMicroelectronics STTS424 + Add support for NXP SE97 / SE97B + Add reference to NCT6771F/NCT6772F/NCT6775F + Add support for several JC42.4 compliant temperature sensors + Add support for ITE IT8512E/F and IT8758E + +3.1.2 (2010-02-02) + libsensors: Support upcoming sysfs path to i2c adapters + Add support for HID devices + fancontrol: Check that all referenced sysfs files exist + Check that all devices match the configuration file + pwmconfig: Exit immediately if not root + Save device paths and names in configuration file + sensors.conf.default: Encourage user to not modify this file + Add a section for adt7473 and adt7475 + Add a section for adt7476 and adt7490 + sensord: Don't name our variables "alarm" + Major refactoring including + - Cleanup of huge functions + - Remove needless casts + - Fix coding style + - Break long lines + - Make functions more robust + - Remove unused return value + - Make CGI script more XHTML compatible + sensors: Fix iconv-related build warning in set_degstr + sensors-detect: Refer to tmp401 driver if TMP411 is detected + Clean up the discovery of i2c adapters + Report unsupported Access Bus adapters + Add detection for TI's TMP421, TMP422 and TMP423 chips + The SMSC LPC47M233 isn't currently supported + Support upcoming sysfs path to i2c adapters + Rename the modprobe configuration file to lm_sensors.conf + Only report AMD Family 10h CPU with working sensors + Add detection for AMD Family 11h thermal sensors + Add detection for Intel Atom thermal sensors + Add detection for National Semiconductor LM73 + Add SMBus detection for AMD Hudson-2 + Add detection for Nuvoton W83667HG-B and W83677HG-I + Add detection for Analog Devices ADT7490 + Refer to f71882fg driver if F71889FG is detected + Add detecton for Fintek F71869FG + Detect ADT7473 at 0x2c and 0x2d + More known revisions for the ADT7476 + Add detection for Nuvoton W83L771AWG/ASG + Add detection for VIA Nano + Add detection for Texas Instruments AMC6821 + Add detection for Analog Devices ADT7411 + sysconfig-lm_sensors-convert: Fix exit code + +3.1.1 (2009-06-21) + isadump: Use geteuid instead of getuid so that setuid bit works + isaset: Use geteuid instead of getuid so that setuid bit works + libsensors: Don't rely on dirent->dt_type being set + New method to free the memory allocated for chip names + Makefile: Include generated source files in dependency checking + Make it possible to skip building of the static library + fancontrol: Add support for absolute path to hwmon devices + sensord: Remove the hidden commandline interface + Introduce struct sensord_arguments + Using sigaction for signal handlers + Convert to linux coding style + Cleanup and refactoring of the source code + Don't use the system log when generating a CGI script + Disable unit scaling for fan speeds + Use daemon logging facility instead of local4 by default + Fix a memory leak when a chip name is provided + sensors: Fix a memory leak when a chip name is provided + sensors-detect: Add nNidia nForce MCP78S SMBus detection + Display Super-I/O address even if LD is disabled + Differentiate between PC8374L and WPCD377I + Use dmidecode to find IPMI interfaces if available + Add Nuvoton W83795G/ADG detection + Add National Semiconductor LM95241 detection + Add Winbond/Nuvoton W83627DHG-P and W83627UHG detection + +3.1.0 "Happy Birthday Lina" (2009-02-28) + libsensors: Add support for instantaneous power sensors + Add support for current sensors + Fix error propagation during expression evaluation + Detect excessive recursion depth during expression eval (#2365) + Return a string rather than NULL for unknown errors + Skip non-file sysfs entries for speed + Fix memory leak in scanner when using flex 2.5.9 or later + Report configuration file read errors + Exit the configuration file parser sooner + Free bus statements from the configuration file sooner + Read extra configuration files from /etc/sensors.d (#2174) + Report the configuration file name on parse errors + Add support for ACPI devices + libsensors.3: Reformat for clarity + Document function sensors_snprintf_chip_name + Document error-related functions + lm_sensors.init: Support new format of /etc/sysconfig/lm_sensors (#2246) + Drop support for kernels 2.4 and earlier + lm_sensors.init.suse: Delete (actual SuSE script is much different) + Makefile: Install sensors.conf.default instead of sensors.conf.eg (#2333) + pwmconfig: Drop support for kernels 2.4 and earlier + fancontrol: Don't round temperature values + Drop support for kernels 2.4 and earlier + Exit if configuration file can't be read + Create pid file only after successful initialization + maxilife scripts: Delete (driver never ported to Linux 2.6) + sensord: Accept negative temperatures in RRD database + Don't bail out on transient errors (#2330) + sensors: Add support for instantaneous power sensors + Add support for current sensors + Fix exit code in error case + sensors.conf.5: Lots of additions and reworks + sensors.conf.default: New, minimum version of sensors.conf.eg (#2333) + Add sections for the SMSC SCH311x and SCH5027 + sensors.conf.eg: The LM99 offset is now handled in the lm90 driver + Move help section to sensors.conf.5 + Add a section for the Asus/Fintek F8000 + sensors-detect: Fix detection of ADT7463 and LM96000 + Add VIA VX800/VX820 SMBus support + Fix detection of Intel 5000 series FB-DIMM AMB + Fix detection of ADT7462 + Fix detection of SMSC LPC47M292 + Add SMSC LPC47M233 support + Drop support for Linux 2.4 (#2325) + Handle special case chips more efficiently + Fix SMBus detection of W83627EHF and W83627DHG + Get I2C adapter driver names from sysfs (#2328) + Drop old SiS I2C adapter entries + Drop separate LM78-J entry + Merge all Mozart-2 entries + Merge both GL518SM entries into one + Complete GL520SM detection + Improve GL525SM detection a bit + Let kernel 2.6.28 and later handle chips aliases + Unload kernel drivers when we are done with them (#2329) + Fix handling of bus driver names with an underscore + Simplify loading of bus drivers + Fix bus number prediction logic (#2327) + Suggest the sbs driver for smart batteries + Drop alias detection for Super-I/O chips + Move alias detection after all chip detections + Probe chip types from safest to more risky (#2322) + Add an option to skip ISA probes except IPMI + Skip ISA detection by default if a Super I/O was found (#2322) + Do not scan I2C adapters on multimedia cards by default + Skip SMBus probing by default if a Super I/O was found (#2322) + Display I2C address statistics with --stat + Document the new detection order and rules + Gather DMI data and print it at start-up + Always probe the SMBus on Asus, Tyan and Supermicro boards + Move IPMI interface detection to its own section + Skip IPMI probing on laptops + Add Winbond/Nuvoton W83667HG support + Add Intel Core I7 support + Generate new format for /etc/sysconfig/lm_sensors (#2246) + Print warnings about missing modules on screen + Fix detection of older DS1621 + Add nNidia nForce MCP67, MCP73, MCP79 SMBus support + Exclude auto-loaded PCI and USB drivers from list (#2368) + Special case probing i2c address 0x73 (to not crash FSC ICs) + Add detection of FSC Hades and Syleus IC's + Add detection of Winbond WPCD377I (no sensors) + sensors-detect-stat.pl: Delete (functionality merged into sensors-detect) + sysconfig-lm_sensors-convert: Sample config file conversion script (#2246) + +3.0.3 (2008-09-28) + libsensors: Avoid namespace pollution + fancontrol: Don't use named pipes when we don't need them (#2319) + pwmconfig: Tell the user about gnuplot if it isn't installed + Fix MINSTOP and MINSTART test functions (#2340) + Test MINSTOP before MINSTART + Use better step values for MINSTOP test + Print the revision and date at start-up + Detect and report obviously incorrect fan speeds + Determine MINSTOP automatically + Skip MINSTOP and MINSTART tests if fan can't stop + Change default for MINTEMP from 0 to 20 degrees C + Add support for attributes in the hwmon class device (#2260) + Update manual page + sensors.conf.eg: Drop "label temp#_crit" statements + sensors-detect: Add Intel SCH (bus) support + Add SMSC EMC6D103 support + Improve MAX6657, MAX6658, MAX6659 detection + Cache the byte data reads (#2326) + Add Maxim MAX6654/MAX6690 support + Add National Semiconductor LM95231 support + Add Analog Devices ADT7481 support + Refactor alias detection functions + Fix Andigilog aSC7621 support + Add Texas Instruments THMC51 support + Fix Analog Devices ADT7461 support + Add VIA C7 support + Fix Winbond W83L786NR/NG/R/G support (#2336) + Add Maxim MAX6646/MAX6647/MAX6649 support + Add VIA VT1212 support + Add SMSC EMC2700LPC support + Add ITE IT8720F support + Add Texas Instruments TMP411 support + Prevent misdetection of W83627DHG on I2C as LM78 + W83627DHG has no subclients + Add Maxim MAX1618 support + +3.0.2 (2008-05-18) + documentation: Delete the FAQ, now maintained on the wiki + libsensors: Use __func__ instead of __FUNCTION__ + Parse the configuration file in C locale + Late compute statements override early ones + Support virtual hwmon devices (#2309) + Support power and energy sensors + Support DOS-style configuration files again (#2284) + pwmconfig: Don't create the configuration file before it's needed + Don't preserve configuration file customizations + Fix permissions of the configuration file + Don't start if fancontrol is running (#2299) + fancontrol: Don't start if already running (#2299) + Delete fancontrol.pid at exit time (#2299) + sensord: Fix support of multiple chip names on the command line (#2321) + sensors: Print energy and power sensors with automatically scaled units + sensors-detect: Add SMSC SCH5027D detection + Do not access I/O ports on PPC + Move south bridge sensor detection to the right section + Run chip_special_cases() earlier + New device ID for the SMSC SCH5317 + Add SMSC SCH5127 detection + Add National Semiconductor LM64 detection + Add Asus F8000 detection + Add Intel ICH10 (bus) detection + Don't probe I2C addresses 0x40-0x47 + Fix the parsing of I2C addresses not to scan + Detect and skip 1-register-only I2C devices + Avoid SMBus word transactions where possible + Add Dallas DS1631 detection + +3.0.1 (2008-01-28) + documentation: Update the application writing guidelines + libsensors: No longer depend on libsysfs (#2262) + Don't guess the bus type from the device ID format (#2240) + Add support for attributes in the hwmon class device (#2260) + Makefile: No warnings about ld configuration for staged installations + Document the variable overriding mechanism (#2296) + pwmconfig: Really hide errors on sysfs writes + Deal gracefully with read-only pwm_enable files + Warn about outputs found in automatic mode + Repeat available configuration options before prompt (#2289) + Fix duplicate warning message when config file is broken + fancontrol: Detect improperly formatted FCTEMPS value (#2293) + sensord: Fix rrd support (#2276) + Use the same colors for daily and weekly charts + Drop workaround needed by old versions of rrdtool + sensors: Fix error path on library initialization error + sensors.conf.eg: Fix voltage value references (g520sm, lm80, pc87366) + sensors-detect: Drop PCA9540 detection + Improve sysconfig and modprobe.d integration + Add SMSC SCH5514D-NS detection (no sensors) + Lower the confidence of MAX6650/MAX6651 + Add Fintek F71858DG detection + Add Fintek F81216D detection (no sensors) + unhide_ICH_SMBus: Add support for the 82801AA (ICH) + +3.0.0 (2007-11-24) + Makefile: Fix MODULE_DIR usage in etc + Fix build on PPC + pwmconfig: Better diagnostics in pwmdisable + Give the fans some time to spin up + sensors-detect: Add Texas Instruments TMP401 detection + Mention the f75375s driver + Add SMSC LPC47B367-NC detection (no sensors) + Reduce w83781d/lm78 I2C address probing range + Add Intel Celeron 4xx and Penryn (CPU on 45nm) detection + +3.0.0-rc3 (2007-10-28) + libsensors: Add a default configuration file + Fix memory leaks on initialization error + Make the configuration file optional + Change the default configuration file to /etc/sensors3.conf + sensord: Reload config on SIGHUP rather than automatically + No default configuration file name + sensors: Fix file handle leak on library initialization error + Handle the case where voltage measurements aren't available + No default configuration file name + Install as sensors again + sensors.conf.eg: Install as sensors3.conf + sensors-detect: Fix SMSC LPC47B357/M967 detection + Select the right driver for FSC chips + sensors-detect-stat.pl: Handle alternative chip lists + +3.0.0-rc2 (2007-10-10) + useful_addresses.html: Moved to the wiki + Makefile: Add sensors-conf-convert to make install + libsensors: Notify the caller when writing a value fails + Differentiate between different read error types + Report I/O errors as such + sensord: Log the error code on failure + Drop the configuration file search path mechanism (#2259) + Manual page update + sensors: Fix spurious critical temperature alarm + Print error messages to stderr + Make error messages more helpful and consistent + Better handling of the fault flags + sensors-conf-convert: Add a short help text + sensors-detect: Fix SMSC SCH311x detection + Add AMD K10 CPU sensor detection + +3.0.0-rc1 (2007-09-25) + Initial release diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..a44354b --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,17 @@ +Here is a list of the main contributors to lm-sensors version 3. + +* Frodo Looijaard + Original author of libsensors, sensors-detect, sensors and isadump. +* Merlin Hughes + Original author of sensord. +* Bob Schlaermann + Dynamic chip feature detection (a.k.a. generic chip support) in + libsensors and sensors. +* Mark M. Hoffman + Many improvements to the libsensors configuration file scanner. +* Jean Delvare + New libsensors API, and migration of sensors and sensord thereto. + Many optimizations in libsensors and sensors. + Configuration file converter. + Rewrite of sensors-detect. + Support for multiple configuration files in libsensors. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/COPYING.LGPL b/COPYING.LGPL new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/COPYING.LGPL @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..f4dc82f --- /dev/null +++ b/INSTALL @@ -0,0 +1,83 @@ +INSTALLATION INSTRUCTIONS +========================= + +The lm-sensors package, version 3, provides user-space support for the +hardware monitoring drivers in Linux 2.6.5 and later. For older kernel +versions, you have to use lm-sensors version 2. + + +Dependencies +============ + +Build-time dependencies: +* GNU make +* gcc +* bison +* flex +* rrd header files (optional, for sensord) + +Run-time dependencies: +* perl (for sensors-detect) +* rrdtool >= 1.2.1 (optional, for sensord) +* proper kernel configuration (see below) + + +Compilation +=========== + +At the top of the Makefile are a couple of configuration variables that +you may want to change. There's a description of what each variable does +in the Makefile itself. + +Compilation is done by `make all'. You will get a lot of warnings about +files which are not found, all ending in `.*d'. You can safely ignore +this; they contain dependency information, which is regenerated on the +spot. + +`make install' installs the package (to /usr/local by default). + + +Kernel configuration +==================== + +This package assumes that you have a properly configured kernel. If +you run a distribution kernel, that should be the case. If you're +building your own kernel, here are some recommendations: +* Enable "I2C support" (CONFIG_I2C=y or m). On many motherboards, the + sensor chip is connected to the SMBus, which is supported by I2C + in the Linux kernel. +* Enable "I2C device interface" (CONFIG_I2C_CHARDEV=m). sensors-detect + needs this to probe for SMBus hardware monitoring chips. +* In I2C Hardware Bus support, enable all drivers you might need, + preferably as modules. If you're not sure, select them all. +* Enable "Hardware Monitoring support" (CONFIG_HWMON=y or m). +* Enable all hardware monitoring drivers you might need, preferably + as modules. If you're not sure, select them all. + + +Using the sensors package +========================= + +There is a scanning program installed called sensors-detect. It +will scan all available I2C and SMBus adapters for all known sensor +devices, and will also look for ISA, PCI and Super-I/O chips with +sensors, and give you a list of what kernel drivers you need to load +(using modprobe). + +After loading the suggested drivers, you can use the installed sensors +program to get a report of all detected sensor devices. Check the manual +page for available options. + +The initial output of `sensors' will not be perfect. You have to adjust +the configuration file (/etc/sensors3.conf) to match your motherboard. +This includes (re)labelling inputs, ignoring unused inputs, changing +voltage compute lines and setting limits. Write down all the sensor +information your BIOS displays as a hint to what you are supposed to +obtain in the end. Make sure you modify the right chip section. + +Once you are done with editing the configuration file, calling +`sensors -s' will set the new limits. Then the output of `sensors' +should look much better. + +There are many auxiliary programs not installed. You can find them under +the prog subdirectory. A list can be found in doc/progs. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d6f2192 --- /dev/null +++ b/Makefile @@ -0,0 +1,287 @@ +# Makefile - Makefile for a Linux module for reading sensor data. +# Copyright (c) 1998, 1999 Frodo Looijaard +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. + +# Everything you may want to change is in the top of this file. Usually, you +# can just use the defaults, fortunately. + +# You need a full complement of GNU utilities to run this Makefile +# successfully; most notably, you need GNU make, flex (>= 2.5.1) +# and bison. + +# Uncomment the second line if you are a developer. This will enable many +# additional warnings at compile-time +#WARN := 0 +WARN := 1 + +# Uncomment the second line if you want to get (loads of) debug information +# at run-time. +# Not recommended, unless you are actually debugging the code +DEBUG := 0 +#DEBUG := 1 + +# Note that all the installation paths below can also be set on the make +# command line (e.g. "make PREFIX=/usr"). + +# If you want to install at some other place then at from which you will run +# everything, set DESTDIR to the extra prefix. +DESTDIR := + +# This is the prefix that will be used for almost all directories below. +PREFIX := /usr/local + +# Your C compiler +CC := gcc + +# This is the directory where sensors3.conf will be installed, if no other +# configuration file is found +ETCDIR := /etc + +# You should not need to change this. It is the directory into which the +# library files (both static and shared) will be installed. +LIBDIR := $(PREFIX)/lib + +EXLDFLAGS := -Wl,-rpath,$(LIBDIR) + +# You should not need to change this. It is the directory into which the +# executable program files will be installed. BINDIR for programs that are +# also useful for normal users, SBINDIR for programs that can only be run +# by the superuser. +# Note that not all programs in this package are really installed; +# some are just examples. You can always install them by hand, of +# course. +BINDIR := $(PREFIX)/bin +SBINDIR := $(PREFIX)/sbin + +# You should not need to change this. It is the basic directory into which +# include files will be installed. The actual directory will be +# $(INCLUDEDIR)/sensors for library include files. +INCLUDEDIR := $(PREFIX)/include +LIBINCLUDEDIR := $(INCLUDEDIR)/sensors + +# You should not need to change this. It is the base directory under which the +# manual pages will be installed. +MANDIR := $(PREFIX)/man + +MACHINE := $(shell uname -m) + +# Extra non-default programs to build; e.g., sensord +#PROG_EXTRA := sensord + +# Build and install static library +BUILD_STATIC_LIB := 1 + +# Set these to add preprocessor or compiler flags, or use +# environment variables +# CFLAGS := +# CPPFLAGS := + +################################################## +# Below this, nothing should need to be changed. # +################################################## + +# Note that this is a monolithic Makefile; it calls no sub-Makefiles, +# but instead, it compiles everything right from here. Yes, there are +# some distinct advantages to this; see the following paper for more info: +# http://www.tip.net.au/~millerp/rmch/recu-make-cons-harm.html +# Note that is still uses Makefile fragments in sub-directories; these +# are called 'Module.mk'. + +# Within each Module.mk, rules and dependencies can be added to targets +# all, install and clean. Use double colons instead of single ones +# to do this. + +# The subdirectories we need to build things in +SRCDIRS := lib prog/detect prog/pwm \ + prog/sensors ${PROG_EXTRA:%=prog/%} etc +# Only build isadump and isaset on x86 machines. +ifneq (,$(findstring $(MACHINE), i386 i486 i586 i686 x86_64)) +SRCDIRS += prog/dump +endif +SRCDIRS += lib/test + +# Some often-used commands with default options +MKDIR := mkdir -p +RMDIR := rmdir +RM := rm -f +MV := mv -f +BISON := bison +FLEX := flex +AR := ar +INSTALL := install +LN := ln -sf +GREP := grep +AWK := awk +SED := sed + +# Determine the default compiler flags +# Set CFLAGS or CPPFLAGS above to add your own flags to all. +# ALLCPPFLAGS/ALLCFLAGS are common flags, plus any user-specified overrides from the environment or make command line. +# PROGCPPFLAGS/PROGCFLAGS is to create regular object files (which are linked into executables). +# ARCPPFLAGS/ARCFLAGS are used to create archive object files (static libraries). +# LIBCPPFLAGS/LIBCFLAGS are for shared library objects. +ALL_CPPFLAGS := -I. +ALL_CFLAGS := -Wall + +ifeq ($(DEBUG),1) +ALL_CPPFLAGS += -DDEBUG +ALL_CFLAGS += -O -g +else +ALL_CFLAGS += -O2 +endif + +ifeq ($(WARN),1) +ALL_CFLAGS += -Wstrict-prototypes -Wshadow -Wpointer-arith -Wcast-qual \ + -Wcast-align -Wwrite-strings -Wnested-externs -Winline -W \ + -Wmissing-prototypes -Wundef +endif + +ALL_CPPFLAGS += $(CPPFLAGS) +ALL_CFLAGS += $(CFLAGS) + +PROGCPPFLAGS := -DETCDIR="\"$(ETCDIR)\"" $(ALL_CPPFLAGS) +PROGCFLAGS := $(ALL_CFLAGS) +ARCPPFLAGS := -DETCDIR="\"$(ETCDIR)\"" $(ALL_CPPFLAGS) +ARCFLAGS := $(ALL_CFLAGS) +LIBCPPFLAGS := -DETCDIR="\"$(ETCDIR)\"" $(ALL_CPPFLAGS) +LIBCFLAGS := -fpic -D_REENTRANT $(ALL_CFLAGS) + +.PHONY: all user clean install user_install uninstall user_uninstall + +# Make all the default rule +all:: + +# Include all makefiles for sub-modules +INCLUDEFILES := +include $(patsubst %,%/Module.mk,$(SRCDIRS)) +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(MAKECMDGOALS),uninstall) +ifneq ($(MAKECMDGOALS),user_uninstall) +ifneq ($(MAKECMDGOALS),help) +include $(INCLUDEFILES) +endif +endif +endif +endif + +# Man pages +MANPAGES := $(LIBMAN3FILES) $(LIBMAN5FILES) $(PROGDETECTMAN8FILES) $(PROGDUMPMAN8FILES) \ + $(PROGSENSORSMAN1FILES) $(PROGPWMMAN8FILES) prog/sensord/sensord.8 + +user :: +user_install:: + @echo "*** Important notes:" + @echo "*** * The libsensors configuration file ($(ETCDIR)/sensors3.conf) is never" + @echo "*** overwritten by our installation process, so that you won't lose" + @echo "*** your personal settings in that file. You still can get our latest" + @echo "*** default config file in etc/sensors.conf.default and manually copy" + @echo "*** it to $(ETCDIR)/sensors3.conf if you want. You will then want to" + @echo "*** edit it to fit your needs again." + @echo "*** * The format of $(ETCDIR)/sensors3.conf changed with lm-sensors 3.0.0." + @echo "*** If you have a custom configuration file using the old format, you" + @echo "*** can convert it using the sensors-conf-convert script. Otherwise just" + @echo "*** overwrite your old configuration file with the new default one." + @echo "*** * As of lm-sensors 3.1.0, the default configuration file only" + @echo "*** contains statements which do not depend on how chips are wired." + @echo "*** If you miss parts of the bigger configuration file that used to be" + @echo "*** the default, copy the relevant parts from etc/sensors.conf.eg to" + @echo "*** $(ETCDIR)/sensors3.conf." +all :: user +install :: all user_install + +clean:: + $(RM) lm_sensors-* lex.backup + +user_uninstall:: + +uninstall :: user_uninstall + +help: + @echo 'Make targets are:' + @echo ' all (default): build library and userspace programs' + @echo ' install: install library and userspace programs' + @echo ' uninstall: uninstall library and userspace programs' + @echo ' clean: cleanup' + +# Generate html man pages to be copied to the lm_sensors website. +# This uses the man2html from here +# http://ftp.math.utah.edu/pub/sgml/ +# which works directly from the nroff source +manhtml: + $(MKDIR) html + cp $(MANPAGES) html + cd html ; \ + export LOGNAME=sensors ; \ + export HOSTNAME=www.lm-sensors.org ; \ + man2html *.[1-8] ; \ + $(RM) *.[1-8] + +# Here, we define all implicit rules we want to use. + +.SUFFIXES: + +# We need to create dependency files. Tricky. The sed rule puts dir/file.d and +# dir/file.c in front of the dependency file rule. + + +# .ro files are used for programs (as opposed to modules) +%.ro: %.c + $(CC) $(PROGCPPFLAGS) $(PROGCFLAGS) -c $< -o $@ + +%.rd: %.c + $(CC) -M -MG $(PROGCPPFLAGS) $(PROGCFLAGS) $< | \ + $(SED) -e 's@^\(.*\)\.o:@$*.rd $*.ro: Makefile '`dirname $*.rd`/Module.mk' @' > $@ + + +# .ao files are used for static archives +%.ao: %.c + $(CC) $(ARCPPFLAGS) $(ARCFLAGS) -c $< -o $@ + +%.ad: %.c + $(CC) -M -MG $(ARCPPFLAGS) $(ARCFLAGS) $< | \ + $(SED) -e 's@^\(.*\)\.o:@$*.ad $*.ao: Makefile '`dirname $*.ad`/Module.mk' @' > $@ + + +# .lo files are used for shared libraries +%.lo: %.c + $(CC) $(LIBCPPFLAGS) $(LIBCFLAGS) -c $< -o $@ + +%.ld: %.c + $(CC) -M -MG $(LIBCPPFLAGS) $(LIBCFLAGS) $< | \ + $(SED) -e 's@^\(.*\)\.o:@$*.ld $*.lo: Makefile '`dirname $*.ld`/Module.mk' @' > $@ + + +# Flex and Bison +%.c: %.y + @if ! which $(BISON) 2> /dev/null ; then \ + echo "Please install $(BISON), then run \"make clean\" and try again" ; \ + false ; \ + fi + $(BISON) -p sensors_yy -d $< -o $@ + +ifeq ($(DEBUG),1) +FLEX_FLAGS := -Psensors_yy -t -b -Cfe -8 +else +FLEX_FLAGS := -Psensors_yy -t -Cfe -8 +endif + +%.c: %.l + @if ! which $(FLEX) 2> /dev/null ; then \ + echo "Please install $(FLEX), then run \"make clean\" and try again" ; \ + false ; \ + fi + $(FLEX) $(FLEX_FLAGS) $< > $@ diff --git a/README b/README new file mode 100644 index 0000000..acd3c6e --- /dev/null +++ b/README @@ -0,0 +1,119 @@ +OVERVIEW OF THE LM-SENSORS PACKAGE +================================== + +The lm-sensors package, version 3, provides user-space support for the +hardware monitoring drivers in Linux 2.6.5 and later. For older kernel +versions, you have to use lm-sensors version 2. + +The directories within this package: + +* doc + Documentation. +* etc + A sample configuration file for libsensors, and a script to convert + lm-sensors version 2 configuration files to work with version 3. +* lib + The user-space sensors support library code (libsensors). +* prog + Several supporting programs. The most important ones are: + - sensors-detect: A stand-alone program for detecting installed + hardware and recommending specific modules to load. + - sensors: A console tool to report sensor readings and set new + sensor limits. + - sensord: A daemon to watch sensor values and log problems. It + includes RRD support. +* configs + This directory contains sample configurations of various boards, + contributed by users of lm-sensors. + + Older sample configurations can be found on an old lm-sensors wiki + archived here: + http://web.archive.org/web/20150901092438/http://www.lm-sensors.org:80/wiki/Configurations + + Please contribute back a configuration of your board so other users with + the same hardware won't need to recreate it again and again. + +INSTALLING LM-SENSORS +--------------------- + +See the INSTALL file. + + +HARDWARE SUPPORT +---------------- + +To find out what hardware you have, just run 'sensors-detect' as root. + +Most modern mainboards incorporate some form of hardware monitoring chips. +These chips read things like chip temperatures, fan rotation speeds and +voltage levels. There are quite a few different chips which can be used by +mainboard builders for approximately the same results. + +Laptops, on the other hand, rarely expose any hardware monitoring +chip. They often have some BIOS and/or ACPI magic to get the CPU +temperature value, but that's about it. For such laptops, the lm-sensors +package is of no use (sensors-detect will not find anything), and you have +to use acpi instead. + +This package doesn't contain chip-specific knowledge. It will support all +the hardware monitoring chips your kernel has drivers for. In other words, +if you find out that you have unsupported hardware (e.g. sensors-detect +told you so) then it means that you need a more recent kernel, or you +even need to wait for a new kernel driver to be written. Updating the +lm-sensors package itself will not help. + + +LIBSENSORS +---------- + +The kernel drivers communicate their information through the /sys +interface. Because every motherboard is different, the drivers always +advert the measurements at their pins. This means that the values they +report are not always immediately relevant to you. They have to be +labelled properly, and sometimes they must be scaled to correspond to +real-world values. + +libsensors is a (shared or static) library of access functions. It +offers a simple-to-use interface for applications to access the sensor +chip readings and configure them as you like. It has a configuration +file where you can put all the motherboard-specific labels and +conversion rules. That way, all applications do not need to duplicate +the effort and can simply link with libsensors and work out of the box. + + +APPLICATIONS +------------ + +This package contains an example console program that reports all current +sensors values. This program is called 'sensors'. You can use it as a +reference implementation for more intricate programs. It also contains a +daemon watching for sensor values, logging alarms and feeding an RRD +database with the sensor measurements. + +This package does not contain a nice graphical monitor. See +http://sensors-applet.sourceforge.net/ +https://01.org/powertop/ +https://wpitchoune.net/psensor/ +https://amanusk.github.io/s-tui/ +for such programs. + + +OTHER INFORMATION +----------------- + +The developers of this package can be reached through github. +(see https://github.com/groeck/lm-sensors). Do not hesitate to contact +us if you have questions, suggestions, problems, want to contribute, +or just want to report it works for you. But please try to +read the documentation before you ask any questions! It's all under doc/. + +The latest version of this package can always be found at: +https://github.com/groeck/lm-sensors. + +LICENSE +------- + +The library (libsensors) is released under the GNU Lesser General Public +License (LGPL), as included in the file COPYING.LGPL. The rest of this +package may be distributed according to the GNU General Public License +(GPL), as included in the file COPYING. diff --git a/configs/ASRock/AB350_Pro4.conf b/configs/ASRock/AB350_Pro4.conf new file mode 100644 index 0000000..5464eeb --- /dev/null +++ b/configs/ASRock/AB350_Pro4.conf @@ -0,0 +1,93 @@ +# ASRock AB350 Pro4 +# 2018, contributed by Leigh Brown +# +# dmi: board_name: AB350 Pro4 +# dmi: board_vendor: ASRock +# dmi: bios_version: P4.60 +# cpu: AMD Ryzen 5 1600 Six-Core Processor +# driver: nct6775 + +chip "k10temp-pci-00c3" + label temp1 "CPU Core Temp" + +chip "nct6779-isa-0290" + label in0 "Vcore" + compute in0 @*2, @/2 + set in0_min 0.30 + set in0_max 1.45 + + label in1 "+5.0V" + compute in1 @*4, @/4 + set in1_min 5.00 * 0.90 + set in1_max 5.00 * 1.10 + + label in2 "AVCC" + set in2_min 3.30 * 0.90 + set in2_max 3.30 * 1.10 + + label in3 "+3.3V" + set in3_min 3.30 * 0.90 + set in3_max 3.30 * 1.10 + + label in4 "+12.0V" + compute in4 @*(66/10), @/(66/10) + set in4_min 12.0 * 0.95 + set in4_max 12.0 * 1.05 + + label in5 "VDDCR_SOC" + set in5_min 0.80 + set in5_max 1.20 + + label in6 "DRAMV" + set in6_min 1.10 # DDR4 Underclocking + set in6_max 1.50 # DDR4 Intel XMP2.0 recommended max safe voltage + + label in7 "3VSB" + set in7_min 3.30 * 0.90 + set in7_max 3.30 * 1.10 + + label in8 "VBAT" + set in8_min 3.00 * 0.90 + set in8_max 3.30 * 1.10 + + ignore in9 + + label in10 "VDDP" + set in10_min 0.90 + set in10_max 1.20 + + label in11 "+1.05V" + set in11_min 1.05 * 0.9 + set in11_max 1.05 * 1.1 + + ignore in12 + ignore in13 + + label in14 "+1.8V" + set in14_min 1.8 * 0.9 + set in14_max 1.8 * 1.1 + + label fan1 "Chassis Fan 3" + label fan2 "CPU Fan 1" + set fan2_min 400 + ignore fan3 + label fan4 "Chassis Fan 1" + label fan5 "Chassis Fan 2" + + label temp1 "Motherboard Temp" + set temp1_max 55.0 + set temp1_max_hyst 50.0 + + label temp2 "CPU Temp" + + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore temp7 + ignore temp8 + ignore temp9 + ignore temp10 + + ignore intrusion0 + ignore intrusion1 diff --git a/configs/ASRock/G41C-GS.conf b/configs/ASRock/G41C-GS.conf new file mode 100644 index 0000000..1c742e7 --- /dev/null +++ b/configs/ASRock/G41C-GS.conf @@ -0,0 +1,61 @@ +### Sensors configuration for ASRock G41C-GS motherboard +### 2014-02-19, ianp +### Thanks to Jean Delvare and Guenter Roeck +### Comments are welcome. + + +chip "w83627dhg-*" + + +### Voltages + + ignore in1 # Ignored until + ignore in4 # properly identified + label in5 "+5V" + label in6 "+12V" + ignore cpu0_vid # Always at 0 in my case, so ignore it + + ### Scale +5V and +12V. + + compute in5 @*3, @/3 + compute in6 @*(1+56/10), @/(1+56/10) + + ### Set in0 according to CPU nominal voltage. + + set in0_min 0.8500 + set in0_max 1.3625 + set in5_min 5 * 0.95 + set in5_max 5 * 1.05 + set in6_min 12 * 0.95 + set in6_max 12 * 1.05 + +### Temperatures + + # temp3 is not identified + + label temp1 "N/B Temp" + label temp2 "CPU Temp" + + ### Set according to CPU and preference. + + set temp1_max 60 + set temp1_max_hyst 55 + set temp2_max 60 + set temp2_max_hyst 55 + +### Fans + + ### Ignore fan4 and fan5. There are + ### only 3 fan connectors on this board. + + label fan1 "POW Fan" + label fan2 "CPU Fan" + label fan3 "CHA Fan" + ignore fan4 + ignore fan5 + + ### Set according to preference. + + set fan1_min 0 + set fan2_min 900 + set fan3_min 0 diff --git a/configs/ASRock/K7VT2.conf b/configs/ASRock/K7VT2.conf new file mode 100644 index 0000000..5adf8fc --- /dev/null +++ b/configs/ASRock/K7VT2.conf @@ -0,0 +1,62 @@ +# Configuration file contributed by Marcus Roeckrath + +# Sample configuration for ASRock K7VT2 + +chip "w83697hf-*" + + label in0 "VCore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "-12V" + label in6 "-5V" + label in7 "V5SB" + label in8 "VBat" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((28/10)+1)*@ , @/((28/10)+1) + # These are the compute lines for -12V and -5V from the + # sample config file sensors.conf.eg from the lm-sensors + # source archive. + # But these lines give positive values on the K7VT2 board. + # compute in5 (5.14 * @) - 14.91 , (@ + 14.91) / 5.14 + # compute in6 (3.14 * @) - 7.71 , (@ + 7.71) / 3.14 + # Therefor I use the compute lines for the positive + # voltages for the negative voltages also and added a "-" + # to get plausible negative values. + compute in5 -((28/10)+1)*@ , -@/((28/10)+1) + compute in6 -((6.8/10)+1)*@ , -@/((6.8/10)+1) + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + + set in0_min 1.5 * 0.95 + set in0_max 1.65 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + set in5_min -12 * 0.9 + set in5_max -12 * 1.1 + set in6_min -5 * 0.9 + set in6_max -5 * 1.1 + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 + set in8_min 3.0 * 0.8 + set in8_max 3.0 * 1.2 + + label temp1 "System Temp" + label temp2 "CPU Temp" + + set temp1_max 50 + set temp1_max_hyst 45 + set temp2_max 52 + set temp2_max_hyst 47 + + label fan1 "CPU Fan" + label fan2 "Chassis Fan" + + set fan1_div 4 + set fan1_min 2000 + set fan2_div 8 + set fan2_min 1000 diff --git a/configs/ASRock/M2NF3-VSTA.conf b/configs/ASRock/M2NF3-VSTA.conf new file mode 100644 index 0000000..e0fa463 --- /dev/null +++ b/configs/ASRock/M2NF3-VSTA.conf @@ -0,0 +1,68 @@ +# lm_sensors configuration file for the ASRock M2NF3-VSTA motherboard +# 2008-01-01, Hans de Goede +# Comments welcome! + +# Winbond W83627EHF configuration for ASRock AM2NF3-VSTA +chip "w83627ehf-*" "w83627dhg-*" + + label in0 "VCore" + label in1 "VCore2" + label in2 "AVCC" + label in3 "3VCC" + label in6 "12V" + label in7 "VSB" + label in8 "VBAT" + label in9 "5V" + +# +12V and +5V use dividers recommended by datasheet + compute in6 @*(1+(56/10)), @/(1+(56/10)) + compute in9 @*(1+(22/10)), @/(1+(22/10)) + +# in4 and in5 are not used (they seem to be hooked up to 3.3v/2, but thats +# already monitored) + ignore in4 + ignore in5 + +# we need to set all voltage limits (hurray for a well written BIOS) +# Note you may need to adapt in0 and in1 depending on your CPU + set in0_min 0.9 + set in0_max 1.5 + set in1_min 0.9 + set in1_max 1.5 + set in2_min 3.3*0.95 + set in2_max 3.3*1.05 + set in3_min 3.3*0.95 + set in3_max 3.3*1.05 + set in6_min 12.0*0.9 + set in6_max 12.0*1.1 + set in7_min 3.3*0.95 + set in7_max 3.3*1.05 + set in8_min 3.0 + set in8_max 3.3*1.05 + set in9_min 5.0*0.95 + set in9_max 5.0*1.05 + +# Fans + label fan1 "Case Fan" + label fan2 "CPU Fan" + ignore fan3 + ignore fan5 +# Fan minumums, disable fan1 min as a case fan isn't always connected, + set fan1_min 0 +# set fan2_min 1700 + +# Temperatures + label temp1 "Sys Temp" + label temp2 "CPU Temp" + label temp3 "CPU2 Temp" + + set temp1_max 45 + set temp1_max_hyst 40 + + +chip "k8temp-*" + + label temp1 "Core0 Temp" + label temp2 "Core0 Temp" + label temp3 "Core1 Temp" + label temp4 "Core1 Temp" diff --git a/configs/Abit/AA8-DuraMAX.conf b/configs/Abit/AA8-DuraMAX.conf new file mode 100644 index 0000000..05ab62d --- /dev/null +++ b/configs/Abit/AA8-DuraMAX.conf @@ -0,0 +1,68 @@ +# lm_sensors configuration file for the Abit AA8-DuraMAX motherboard +# 2006-06-07, Hans de Goede +# Comments welcome! + + +chip "abituguru-*" + + +### Voltages + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "ATX +12V" + compute in3 @*4.153 , @/4.153 + + label in4 "FSB VTT Voltage" + + label in5 "NB Voltage" + + label in6 "NB 2.5V Voltage" + + label in7 "ATX +5V" + compute in7 @*1.788 , @/1.788 + + label in8 "ATX +3.3V" + compute in8 @*1.248 , @/1.248 + + label in9 "Standby Voltage (+5V)" + compute in9 @*1.788 , @/1.788 + + ignore in10 + + +### Temperatures + + + label temp1 "CPU Temperature" + + label temp2 "SYS Temperature" + + label temp3 "PWM Temperature 1" + + label temp4 "PWM Temperature 2" + + ignore temp5 + ignore temp6 + ignore temp7 + + +### Fans + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "AUX1 FAN Speed" + + label fan5 "AUX2 FAN Speed" + + ignore fan6 diff --git a/configs/Abit/AA8XE-Fatal1ty.conf b/configs/Abit/AA8XE-Fatal1ty.conf new file mode 100644 index 0000000..ac3aa93 --- /dev/null +++ b/configs/Abit/AA8XE-Fatal1ty.conf @@ -0,0 +1,159 @@ +# lm_sensors configuration file for the Abit AA8XE-Fatal1ty motherboard + +# 2006-05-29, Author: Roger Lucas + +# Please send comments to: + + + +chip "abituguru-*" + + + +### Voltages + + + + label in0 "DDR VTT Voltage" + + label in1 "CPU Core Voltage" + + label in2 "Unknown Voltage" + + label in3 "DDR Voltage" + + label in4 "NB Voltage" + + label in5 "Unknown Voltage" + + label in6 "FSB VTT Voltage" + + label in7 "NB 2.5V Voltage" + + ignore in8 + + ignore in9 + + ignore in10 + + ignore in11 + + + +### Temperatures + + + + label temp1 "CPU Temperature" + + label temp2 "SYS Temperature" + + label temp3 "PWM#1 Temperature" + + label temp4 "PWM#2 Temperature" + + label temp5 "PWM#3 Temperature" + + label temp6 "PWM#4 Temperature" + + ignore temp7 + + + +### Fans + + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "OTES1 FAN Speed" + + label fan5 "OTES2 FAN Speed" + + ignore fan6 + + + + + +# The AA8XE Fatal1ty motherboard also contains a w83627hf which is used to + +# measure the ATX power supply rails. Below is the correct config for this + + + +chip "w83782d-*" "w83627hf-*" + + + + ignore in0 + + ignore in1 + + label in2 "ATX +3.3V" + + label in3 "ATX +5V" + + label in4 "ATX +12V" + + ignore in5 + + ignore in6 + + label in7 "Standby Voltage (+5V)" + + ignore in8 + + + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + + compute in4 ((28/10)+1)*@ , @/((28/10)+1) + + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + + + + set in2_min 3.3 * 0.95 + + set in2_max 3.3 * 1.05 + + set in3_min 5.0 * 0.95 + + set in3_max 5.0 * 1.05 + + set in4_min 12 * 0.90 + + set in4_max 12 * 1.10 + + set in7_min 5 * 0.95 + + set in7_max 5 * 1.05 + + + + ignore fan1 + + ignore fan2 + + ignore fan3 + + + + ignore temp1 + + ignore temp2 + + ignore temp3 + + + + ignore vid + + ignore alarms + + ignore beep_enable diff --git a/configs/Abit/AI7.conf b/configs/Abit/AI7.conf new file mode 100644 index 0000000..930c110 --- /dev/null +++ b/configs/Abit/AI7.conf @@ -0,0 +1,83 @@ +# This configuration is derived from the AN7 configuration and currently +# untested, it should work fine though. Please send any success or failure +# using this config to: Hans de Goede . + +# Notice that this motherboard contains version 1 of the uGuru. This version +# does not seem to properly support autodetecting the type of the bank1 +# sensors, nor does the autodetection of the number of fan sensors work +# properly on this chip. + + +# lm_sensors configuration file for the Abit AI7 motherboard +# 2006-06-24, Hans de Goede +# Comments welcome! +# Note it might be nessecaryto load the driver with the following params: +# bank1_types=1,1,0,0,0,0,0,2,0,0,0,0,2,0,0,1 fan_sensors=5 + +chip "abituguru-*" + + +### Voltages + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "ATX +12V" + compute in3 @*4.153 , @/4.153 + + # I believe this is FSB VTT, in some Abit files its called GMCHVTT, below is the BIOS name + label in4 "AUXC Voltage" + + label in5 "NB Core Voltage" + + label in6 "VCCVID Voltage" + + label in7 "ATX +5V Voltage" + compute in7 @*1.788 , @/1.788 + + label in8 "ATX +3.3V Voltage" + compute in8 @*1.248 , @/1.248 + + label in9 "Standby Voltage (+5V)" + compute in9 @*1.788 , @/1.788 + + label in10 "3VDUAL Voltage" + compute in10 @*1.248 , @/1.248 + + +### Temperatures + + + label temp1 "CPU Temperature" + + label temp2 "System Temperature" + + label temp3 "PWM Temperature" + + ignore temp4 + + ignore temp5 + + ignore temp6 + + ignore temp7 + + +### Fans + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "FAN4" + + label fan5 "FAN5" + + ignore fan6 diff --git a/configs/Abit/AN7.conf b/configs/Abit/AN7.conf new file mode 100644 index 0000000..df84d69 --- /dev/null +++ b/configs/Abit/AN7.conf @@ -0,0 +1,79 @@ +# Notice that this was the first motherboard by Abit with the uGuru and thus +# contains version 1 of the uGuru. This version does not seem to properly +# support autodetecting the type of the bank1 sensors, nor does the +# autodetection of the number of fan sensors work properly on this chip. + + +# lm_sensors configuration file for the Abit AN7 motherboard +# 2006-06-24, Hans de Goede +# Comments welcome! +# Note the driver MUST be loaded with the following params: +# bank1_types=1,1,0,0,0,0,0,2,0,0,0,0,2,0,0,1 fan_sensors=5 + +chip "abituguru-*" + + +### Voltages + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "ATX +12V" + compute in3 @*4.153 , @/4.153 + + # I believe this is FSB VTT, in some Abit files its called GMCHVTT, below is the BIOS name + label in4 "AUXC Voltage" + + label in5 "NB Core Voltage" + + label in6 "AGP VDDQ Voltage" + + label in7 "ATX +5V Voltage" + compute in7 @*1.788 , @/1.788 + + label in8 "ATX +3.3V Voltage" + compute in8 @*1.248 , @/1.248 + + label in9 "Standby Voltage (+5V)" + compute in9 @*1.788 , @/1.788 + + label in10 "3VDUAL Voltage" + compute in10 @*1.248 , @/1.248 + + +### Temperatures + + + label temp1 "CPU Temperature" + + label temp2 "System Temperature" + + label temp3 "PWM Temperature" + + ignore temp4 + + ignore temp5 + + ignore temp6 + + ignore temp7 + + +### Fans + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "FAN4" + + label fan5 "FAN5" + + ignore fan6 diff --git a/configs/Abit/AN8-SLI.conf b/configs/Abit/AN8-SLI.conf new file mode 100644 index 0000000..f970939 --- /dev/null +++ b/configs/Abit/AN8-SLI.conf @@ -0,0 +1,83 @@ +# lm_sensors configuration file for the Abit AN8-SLI motherboard + +# 2006-05-29, Hans de Goede + +# Comments welcome! + + + +chip "abituguru-*" + + + +### Voltages + + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "nForce4 Standby Voltage" + + label in4 "CPU VDDA 2.5V Voltage" + + label in5 "HyperTransport Voltage" + + label in6 "nForce4 Voltage" + + label in7 "ATX +5V" + + compute in7 @*1.788 , @/1.788 + + label in8 "ATX +3.3V" + + compute in8 @*1.248 , @/1.248 + + label in9 "ATX 5VSB Voltage" + + compute in9 @*1.788 , @/1.788 + + label in10 "ATX +12V" + + compute in10 @*4.153 , @/4.153 + + + +### Temperatures + + + + label temp1 "CPU Temperature" + + label temp2 "SYS Temperature" + + label temp3 "PWM Temperature" + + ignore temp4 + + ignore temp5 + + ignore temp6 + + ignore temp7 + + + +### Fans + + + + label fan1 "CPU FAN Speed" + + label fan2 "NF4 FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "OTES1 FAN Speed" + + label fan5 "OTES2 FAN Speed" + + label fan6 "AUX FAN Speed" diff --git a/configs/Abit/AV8.conf b/configs/Abit/AV8.conf new file mode 100644 index 0000000..2e610f7 --- /dev/null +++ b/configs/Abit/AV8.conf @@ -0,0 +1,83 @@ +# lm_sensors configuration file for the Abit AV8 motherboard + +# 2006-05-29, Hans de Goede + +# Comments welcome! + + + +chip "abituguru-*" + + + +### Voltages + + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "NB Voltage" + + label in4 "SB Voltage" + + label in5 "HyperTransport Voltage" + + label in6 "AGP VDDQ Voltage" + + label in7 "ATX +5V" + + compute in7 @*1.788 , @/1.788 + + label in8 "ATX +3.3V" + + compute in8 @*1.248 , @/1.248 + + label in9 "Standby Voltage (+5V)" + + compute in9 @*1.788 , @/1.788 + + label in10 "3VDual Voltage" + + compute in10 @*1.248 , @/1.248 + + + +### Temperatures + + + + label temp1 "CPU Temperature" + + label temp2 "SYS Temperature" + + label temp3 "PWM Temperature" + + ignore temp4 + + ignore temp5 + + ignore temp6 + + ignore temp7 + + + +### Fans + + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "AUX1 FAN Speed" + + label fan5 "AUX2 FAN Speed" + + ignore fan6 diff --git a/configs/Abit/AX8.conf b/configs/Abit/AX8.conf new file mode 100644 index 0000000..8d89e11 --- /dev/null +++ b/configs/Abit/AX8.conf @@ -0,0 +1,83 @@ +# lm_sensors configuration file for the Abit AX8 motherboard + +# 2006-05-29, Hans de Goede + +# Comments welcome! + + + +chip "abituguru-*" + + + +### Voltages + + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "NB Voltage" + + label in4 "SB Voltage" + + label in5 "HyperTransport Voltage" + + label in6 "ATX +5V" + + compute in6 @*1.788 , @/1.788 + + label in7 "ATX +3.3V" + + compute in7 @*1.248 , @/1.248 + + label in8 "Standby Voltage (+5V)" + + compute in8 @*1.788 , @/1.788 + + label in9 "ATX +12V" + + compute in9 @*4.153 , @/4.153 + + ignore in10 + + + +### Temperatures + + + + label temp1 "CPU Temperature" + + label temp2 "SYS Temperature" + + label temp3 "PWM Temperature" + + ignore temp4 + + ignore temp5 + + ignore temp6 + + ignore temp7 + + + +### Fans + + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "AUX FAN Speed" + + ignore fan5 + + ignore fan6 diff --git a/configs/Abit/Aa7-Max.conf b/configs/Abit/Aa7-Max.conf new file mode 100644 index 0000000..6ff3833 --- /dev/null +++ b/configs/Abit/Aa7-Max.conf @@ -0,0 +1,83 @@ +# lm_sensors configuration file for the Abit Aa7-Max motherboard + +# 2006-05-29, Hans de Goede + +# Comments welcome! + + + +chip "abituguru-*" + + + +### Voltages + + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "ATX +12V" + + compute in3 @*4.153 , @/4.153 + + label in4 "FSB VTT Voltage" + + label in5 "NB Voltage" + + label in6 "NB 2.5V Voltage" + + label in7 "ATX +5V Voltage" + + compute in7 @*1.788 , @/1.788 + + label in8 "ATX +3.3V Voltage" + + compute in8 @*1.248 , @/1.248 + + label in9 "5VDual Voltage" + + compute in9 @*1.788 , @/1.788 + + ignore in10 + + + +### Temperatures + + + + label temp1 "CPU Temperature" + + label temp2 "SYS Temperature" + + label temp3 "PWM1 Temperature" + + label temp4 "PWM2 Temperature" + + ignore temp5 + + ignore temp6 + + ignore temp7 + + + +### Fans + + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "AUX1 FAN Speed" + + label fan5 "AUX2 FAN Speed" + + ignore fan6 diff --git a/configs/Abit/Ag7.conf b/configs/Abit/Ag7.conf new file mode 100644 index 0000000..1b28e9c --- /dev/null +++ b/configs/Abit/Ag7.conf @@ -0,0 +1,83 @@ +# lm_sensors configuration file for the Abit Ag7 motherboard + +# 2006-05-29, Hans de Goede + +# Comments welcome! + + + +chip "abituguru-*" + + + +### Voltages + + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "ATX +12V" + + compute in3 @*4.153 , @/4.153 + + label in4 "FSB VTT Voltage" + + label in5 "NB Voltage" + + label in6 "NB 2.5V Voltage" + + label in7 "ATX +5V Voltage" + + compute in7 @*1.788 , @/1.788 + + label in8 "ATX +3.3V Voltage" + + compute in8 @*1.248 , @/1.248 + + label in9 "5VDual Voltage" + + compute in9 @*1.788 , @/1.788 + + ignore in10 + + + +### Temperatures + + + + label temp1 "CPU Temperature" + + label temp2 "SYS Temperature" + + label temp3 "PWM1 Temperature" + + label temp4 "PWM2 Temperature" + + ignore temp5 + + ignore temp6 + + ignore temp7 + + + +### Fans + + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "AUX1 FAN Speed" + + label fan5 "AUX2 FAN Speed" + + ignore fan6 diff --git a/configs/Abit/KN9-Ultra.conf b/configs/Abit/KN9-Ultra.conf new file mode 100644 index 0000000..159e8a8 --- /dev/null +++ b/configs/Abit/KN9-Ultra.conf @@ -0,0 +1,64 @@ +# "My best guesses at my ABIT KN9 Ultra" Contributed by Dawn Light +# Based on "Winbond W83627EHF configuration originally contributed by Leon Moonen" + +chip "w83627ehf-*" + + label in0 "CPU Core" + label in1 "DDR2" + label in2 "AVCC" + label in3 "3VCC" + label in4 "DDR2 VTT" + label in5 "PCIE" + label in6 "ATX +5V" + label in7 "VSB" + label in8 "VBAT" + label in9 "ATX +12V" + compute in1 @*(1+(10/10)), @/(1+(10/10)) + compute in6 @*(1+(22/10)), @/(1+(22/10)) + compute in9 @*(1+(61/10)), @/(1+(61/10)) + set in0_min 1.15 + set in0_max 1.25 + set in1_min 2.05 + set in1_max 2.15 + set in4_min 0.95 + set in4_max 1.15 + set in5_min 1.50*0.95 + set in5_max 1.50*1.05 + set in6_min 5.0*0.95 + set in6_max 5.0*1.05 + set in9_min 12.0*0.95 + set in9_max 12.0*1.05 + +# Set the 3.3V + set in2_min 3.3*0.95 + set in2_max 3.3*1.05 + set in3_min 3.3*0.95 + set in3_max 3.3*1.05 + set in7_min 3.3*0.95 + set in7_max 3.3*1.05 + set in8_min 3.3*0.90 + set in8_max 3.3*1.10 + +# Fans + label fan1 "SYS Fan" + label fan2 "CPU Fan" + label fan3 "AUX1 Fan" + label fan4 "AUX2 Fan" +# ignore fan3 + ignore fan4 + set fan1_min 400 + set fan2_min 2500 + set fan3_min 890 + +# Temperatures + label temp1 "Sys Temp" + label temp2 "CPU Temp" + label temp3 "PWM Temp" + +# ignore temp3 + set temp1_over 41 + set temp1_hyst 50 + set temp2_over 50 + set temp2_hyst 60 + set temp3_over 50 + set temp3_hyst 60 diff --git a/configs/Abit/KV8-MAX3.conf b/configs/Abit/KV8-MAX3.conf new file mode 100644 index 0000000..5e47c32 --- /dev/null +++ b/configs/Abit/KV8-MAX3.conf @@ -0,0 +1,83 @@ +# This configuration is derived from the AN7 configuration and currently +# untested, it should work fine though. Please send any success or failure +# using this config to: Hans de Goede . + +# Notice that this motherboard contains version 1 of the uGuru. This version +# does not seem to properly support autodetecting the type of the bank1 +# sensors, nor does the autodetection of the number of fan sensors work +# properly on this chip. + + +# lm_sensors configuration file for the Abit KV8-MAX3 motherboard +# 2006-06-24, Hans de Goede +# Comments welcome! +# Note it might be nessecaryto load the driver with the following params: +# bank1_types=1,1,0,0,0,0,0,2,0,0,0,0,2,0,0,1 fan_sensors=5 + +chip "abituguru-*" + + +### Voltages + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "ATX +12V" + compute in3 @*4.153 , @/4.153 + + # I believe this is FSB VTT, in some Abit files its called GMCHVTT, below is the BIOS name + label in4 "AUXC Voltage" + + label in5 "NB Core Voltage" + + label in6 "AGP VDDQ Voltage" + + label in7 "ATX +5V Voltage" + compute in7 @*1.788 , @/1.788 + + label in8 "ATX +3.3V Voltage" + compute in8 @*1.248 , @/1.248 + + label in9 "Standby Voltage (+5V)" + compute in9 @*1.788 , @/1.788 + + label in10 "3VDUAL Voltage" + compute in10 @*1.248 , @/1.248 + + +### Temperatures + + + label temp1 "CPU Temperature" + + label temp2 "System Temperature" + + label temp3 "PWM Temperature" + + ignore temp4 + + ignore temp5 + + ignore temp6 + + ignore temp7 + + +### Fans + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "OTES FAN Speed" + + label fan4 "FAN4" + + label fan5 "FAN5" + + ignore fan6 diff --git a/configs/Abit/Kv8Pro.conf b/configs/Abit/Kv8Pro.conf new file mode 100644 index 0000000..169563e --- /dev/null +++ b/configs/Abit/Kv8Pro.conf @@ -0,0 +1,83 @@ +# lm_sensors configuration file for the Abit Kv8Pro motherboard + +# 2006-05-29, Hans de Goede + +# Comments welcome! + + + +chip "abituguru-*" + + + +### Voltages + + + + label in0 "CPU Core Voltage" + + label in1 "DDR Voltage" + + label in2 "DDR VTT Voltage" + + label in3 "NB Voltage" + + label in4 "SB Voltage" + + label in5 "HyperTransport Voltage" + + label in6 "AGP VDDQ Voltage" + + label in7 "ATX +5V" + + compute in7 @*1.788 , @/1.788 + + label in8 "ATX +3.3V" + + compute in8 @*1.248 , @/1.248 + + label in9 "Standby Voltage (+5V)" + + compute in9 @*1.788 , @/1.788 + + label in10 "3VDual Voltage" + + compute in10 @*1.248 , @/1.248 + + + +### Temperatures + + + + label temp1 "CPU Temperature" + + label temp2 "SYS Temperature" + + label temp3 "PWM Temperature" + + ignore temp4 + + ignore temp5 + + ignore temp6 + + ignore temp7 + + + +### Fans + + + + label fan1 "CPU FAN Speed" + + label fan2 "NB FAN Speed" + + label fan3 "SYS FAN Speed" + + label fan4 "AUX1 FAN Speed" + + label fan5 "AUX2 FAN Speed" + + ignore fan6 diff --git a/configs/Abit/VA-20.conf b/configs/Abit/VA-20.conf new file mode 100644 index 0000000..3f8a9cb --- /dev/null +++ b/configs/Abit/VA-20.conf @@ -0,0 +1,41 @@ +#### Abit VA-20 contributed by DawnLight #### + +chip "it87-*" "it8712-*" + + label in0 "CPU VCore" + label in1 "+2.5V" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + ignore in5 + ignore in6 + ignore in7 + label in8 "VBat" + + ignore vid + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((30/10) +1)*@ , @/((30/10) +1) + + set in0_min 1.55 * 0.95 + set in0_max 1.55 * 1.05 + set in1_min 2.4 + set in1_max 2.6 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5.0 * 0.95 + set in3_max 5.0 * 1.05 + set in4_min 12.5 * 0.95 + set in4_max 12.5 * 1.05 + + label temp1 "M/B Temp" + set temp1_over 44 + set temp1_low 15 + label temp2 "CPU Temp" + set temp2_over 45 + set temp2_low 15 + ignore temp3 + + set fan1_min 3000 + ignore fan2 + ignore fan3 diff --git a/configs/Asus/H87-Pro.conf b/configs/Asus/H87-Pro.conf new file mode 100644 index 0000000..772940d --- /dev/null +++ b/configs/Asus/H87-Pro.conf @@ -0,0 +1,69 @@ +# Configuration file for ASUS H87-PRO +# 2014-01-21/mg + +chip "nct6791-*" + +label in0 "Vcore" + compute in0 @*2 , @/2 + +label in1 "+5V" + compute in1 @ * (40/8), @ / (40/8) + set in1_min 5 * 0.95 + set in1_max 5 * 1.05 + +label in2 "AVCC" + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + +label in3 "+3.3V" + set in3_min 3.3 * 0.95 + set in3_max 3.3 * 1.05 + +label in4 "+12V" + compute in4 @ * (96/8), @ / (96/8) + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + +ignore in5 # always 0.17V here +ignore in6 # always 0.82V here + +label in7 "3VSB" + set in7_min 3.3 * 0.95 + set in7_max 3.3 * 1.05 + +label in8 "Vbat" + set in8_min 3.0 * 0.90 + set in8_max 3.3 * 1.10 + +ignore in9 +ignore in10 +ignore in11 +ignore in12 +ignore in13 +ignore in14 + +label fan1 "CHA_FAN1" + set fan1_min 300 + +label fan2 "CPU fan" + set fan2_min 300 + +label fan3 "CHA_FAN2" + set fan3_min 300 + +label fan4 "CHA_FAN3" + set fan4_min 300 + +ignore fan5 # does not exist on this MB + +ignore temp1 # SYSTIN +ignore temp3 # AUXTIN, gets smaller under load +ignore temp4 # AUXTIN1 +ignore temp5 # AUXTIN2 +ignore temp6 # AUXTIN3 +ignore intrusion0 +ignore intrusion1 +ignore beep_enable +ignore temp8 # PCH_CHIP_CPU_MAX_TEMP +ignore temp9 # PCH_CHIP_TEMP +ignore temp10 # PCH_CPU_TEMP diff --git a/configs/Asus/KFN4-DRE.conf b/configs/Asus/KFN4-DRE.conf new file mode 100644 index 0000000..851df80 --- /dev/null +++ b/configs/Asus/KFN4-DRE.conf @@ -0,0 +1,62 @@ +# Contributed by Mark Nienberg + +# sensors-detect 2.10.6 suggested the w83627thf chip, but that is wrong. The +# board actually has a Winbond W83792D according to the manual. + + +# Here are configurations for Winbond W83792AD/D chip. +chip "w83792d-*" + + label in0 "VCoreA" + label in1 "VCoreB" + label in2 "VIN0" + label in3 "VIN1" + label in4 "VIN2" + label in5 "VIN3" + label in6 "5VCC" + label in7 "5VSB" + label in8 "VBAT" + +# These are the corresponding fan names from motherboard manual. +# Rear_Fan1 through Rear_Fan4 are not read by lm_sensors, but the manual +# says that all fans are controlled by "smart fan" in BIOS. +# fan6 doesn not show up in sensor output for me. + label fan1 "Frnt_Fan3" + label fan2 "Frnt_Fan1" + label fan3 "Frnt_Fan2" + label fan4 "Frnt_Fan4" + label fan5 "Frnt_Fan5" +# label fan6 "Nothing" + label fan7 "Frnt_Fan6" + +# Here is my installed fans layout +# Yours will be different +# ignore fan1 +# label fan2 "Case Fan" +# ignore fan3 +# label fan4 "CPU1 Fan" +# label fan5 "P/S Fan" +# ignore fan6 +# ignore fan7 + +# Fix Case fan because speed read 0 at low speeds. +# set fan2_div 8 + +# Temps - I'm guessing here. +# Add 5 degrees to CPU temperatures to match BIOS +# (very limited data on which to base this) + compute temp2 @+5,@-5 + compute temp3 @+5,@-5 + + label temp1 "MB Temp" + label temp2 "CPU1 Temp" + label temp3 "CPU2 Temp" + +# Ignore chassis alarm, I don't have one + ignore chassis + +# prevent alarm on in0, the actual value is about 1.1 +# this is probably due to my low power 55 watt CPU + set in0_min 0.8 + set in0_max 1.6 + diff --git a/configs/Asus/KGPE-D16.conf b/configs/Asus/KGPE-D16.conf new file mode 100644 index 0000000..97fad13 --- /dev/null +++ b/configs/Asus/KGPE-D16.conf @@ -0,0 +1,95 @@ +# Configuration file for the Asus KGPE-D16 motherboard, +# contributed by Seth Bardash. + +chip "w83795g-*" "w83795ag-*" + + label in0 "VCORE1" + label in1 "VCORE2" + label in2 "P1DDR3" + label in3 "P2DDR3" + label in4 "P1_+1.2V" + label in5 "P2_+1.2V" + label in6 "P1_VDDNB" + label in7 "+1.8V" + label in8 "+1.2V" + label in9 "+1.1V" + label in10 "+5VSB" + label in12 "+3.3V" + label in13 "+3.3VSB" + label in14 "VBAT" + label in15 "+12V" + label in16 "+5V" + + label temp2 "TR1 Tempearture" + label temp3 "TR2 Temperature" + label temp7 "CPU1 Temperature" + label temp8 "CPU2 Temperature" + + label fan1 "CPU_FAN1" + label fan2 "CPU_FAN2" + label fan3 "FRNT_FAN1" + label fan4 "FRNT_FAN2" + label fan5 "FRNT_FAN3" + label fan6 "FRNT_FAN4" + label fan7 "FRNT_FAN5" + label fan8 "REAR_FAN1" + + compute in10 (3.2)*@ , @/(3.2) + compute in15 (12)*@ , @/(12) + compute in16 (3.2)*@ , @/(3.2) + + set in0_min 0.72 + set in0_max 1.43 + set in1_min 0.72 + set in1_max 1.43 + set in2_min 1.125 + set in2_max 1.625 + set in3_min 1.125 + set in3_max 1.625 + set in4_min 1.14 + set in4_max 1.26 + set in5_min 1.14 + set in5_max 1.26 + set in6_min 0.92 + set in6_max 1.21 + set in7_min 1.62 + set in7_max 1.98 + set in8_min 1.08 + set in8_max 1.32 + set in9_min 0.99 + set in9_max 1.21 + set in10_min 4.5 + set in10_max 5.5 + set in12_min 2.97 + set in12_max 3.63 + set in13_min 2.97 + set in13_max 3.63 + set in14_min 1.9 + set in14_max 3.6 + set in15_min 10.8 + set in15_max 13.2 + set in16_min 4.5 + set in16_max 5.5 + + set fan1_min 700 + set fan2_min 700 + set fan3_min 700 + set fan4_min 700 + set fan5_min 700 + set fan6_min 700 + set fan7_min 700 + set fan8_min 700 + +# DO NOT add temp5_crit, temp5_crit_hyst, temp6_crit and temp6_crit_hyst +# Because these features are configuration of smart fan. +# set temp2_max 60 +# set temp2_max_hyst 55 +# set temp3_max 60 +# set temp3_max_hyst 55 + +# temp7_max and temp7_max_hyst are also features of temp8 + set temp7_max 70 + set temp7_max_hyst 65 + + ignore beep_enable + diff --git a/configs/Asus/M2N-SLI_Deluxe.conf b/configs/Asus/M2N-SLI_Deluxe.conf new file mode 100644 index 0000000..d5ee90d --- /dev/null +++ b/configs/Asus/M2N-SLI_Deluxe.conf @@ -0,0 +1,89 @@ +# Contributed by Matt Roberds. + + +# Second cut at a minimal sensors3.conf for Asus M2N-SLI Deluxe motherboard +# Based on existing entries in sensors3.conf and Jean Delvare's configuration +# for the Asus M2N32-SLI +# Matt Roberds, 21 Feb 2008 + + +chip "it8716-*" + +# Voltages + + label in0 "VCore" + label in1 "VDDR" # Not in BIOS + ignore in2 # 3.3 V is monitored by adt7475 + label in3 "+5V" # VCC + label in4 "+12V" + ignore in5 # -12 V not monitored + ignore in6 # -5 V not monitored + label in7 "5VSB" # Not in BIOS + label in8 "VBat" # Not in BIOS + + # Vcore, VDDR, and Vbat are connected directly, so no compute + # line is needed for these. For +5V, +12V and 5VSB, the default + # resistors seem to have been used. + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((30/10)+1)*@ , @/((30/10)+1) + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# Temperatures + +# Not sure. temp1 always reads close to what k8temp reports for Core0, +# and to what the BIOS reports as the CPU temperature. temp2 is between +# temp1 and temp3; it is close to what the BIOS reports as the motherboard +# temperature. temp3 always reads approximate ambient temperature. + + label temp1 "CPU Temp" + label temp2 "MB Temp" + label temp3 "MB Temp" + +# Fans + + label fan1 "CPU Fan" + label fan2 "Chassis Fan 1" + label fan3 "Power Supply Fan" + + # Ignore fans you don't have +# ignore fan2 +# ignore fan3 + + +chip "adt7475-*" + +# Note: this section depends on some further hacks I have made to +# Jordan Crouse's driver + +# Voltages + + ignore in1 + label in2 "+3.3V" + +# Temperatures + +# temp1 and temp3 don't appear to be hooked up; temp2 is on board the +# adt7475 chip itself. + + ignore temp1 + label temp2 "ADT7475 Temp" + ignore temp3 + +# Fans + + label fan1 "Chassis Fan 4" + label fan2 "Chassis Fan 2" + label fan3 "Chassis Fan 3" + ignore fan4 + + # Ignore fans you don't have +# ignore fan1 +# ignore fan2 +# ignore fan3 + + +chip "k8temp-*" + + label temp1 "core0 temp" + label temp3 "core1 temp" + diff --git a/configs/Asus/M3A78-CM.conf b/configs/Asus/M3A78-CM.conf new file mode 100644 index 0000000..9856382 --- /dev/null +++ b/configs/Asus/M3A78-CM.conf @@ -0,0 +1,41 @@ +# Sample configuration file contributed by Martin Desormeaux. Note that this +# board also implements the ATK0110 interface, so starting with kernel 2.6.30 +# you can use the asus_atk0110 driver instead of the it87 driver. It is +# suggested you don't use both at once. + + +chip "it8712-*" + # The values below have been tested on Asus M3A78-CM motherboards. + + label in0 "VCore" + ignore in1 + label in2 "+3.3V" + ignore in3 + label in4 "+12V" + label in5 "+5V" + ignore in6 + ignore in7 + label in8 "VBat" + ignore cpu0_vid + compute in4 ((28/10) +1)*@ , @/((28/10) +1) + compute in5 @*(1+(22/10)), @/(1+(22/10)) + set in0_min 1.30 * 0.95 + set in0_max 1.30 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + set in5_min 5 * 0.95 + set in5_max 5 * 1.05 + + set temp1_type 2 + set temp2_type 2 + set temp3_type 3 + ignore temp3 + label temp1 "CPU Temp" + label temp2 "M/B Temp" + + label fan1 "CPU Fan" + label fan2 "Chassis Fan" + label fan3 "Power Fan" + diff --git a/configs/Asus/M5A97-Pro.conf b/configs/Asus/M5A97-Pro.conf new file mode 100644 index 0000000..4c7f679 --- /dev/null +++ b/configs/Asus/M5A97-Pro.conf @@ -0,0 +1,31 @@ +# Configuration file contributed by Felipe Almeida Lessa. + + +# Asus M5A97 PRO +# http://blog.felipe.lessa.nom.br/?p=93 + +chip "k10temp-pci-00c3" + label temp1 "CPU Temp (rel)" + +chip "it8721-*" + label in0 "+12V" + label in1 "+5V" + label in2 "Vcore" + ignore in4 + ignore in5 + ignore in6 + + compute in0 @ * (515/120), @ / (515/120) + compute in1 @ * (215/120), @ / (215/120) + + ignore temp3 + label temp1 "CPU Temp" + label temp2 "M/B Temp" + + label fan1 "CPU Fan" + label fan2 "Chassis Fan" + label fan3 "Power Fan" + + ignore intrusion0 + + diff --git a/configs/Asus/P3-PH4C.conf b/configs/Asus/P3-PH4C.conf new file mode 100644 index 0000000..00e5dab --- /dev/null +++ b/configs/Asus/P3-PH4C.conf @@ -0,0 +1,70 @@ +# Winbond W83627EHF configuration originally contributed by Leon Moonen +# Modified for ASUS P3-PH4C by Florian Kleinmanns +chip "w83627ehf-*" "w83627dhg-*" + + label in0 "VCore" + label in1 "+12V" + label in2 "AVCC" +# ACPI says nothing about AVCC, so you might want to uncomment: +#ignore in2 + label in3 "+3.3V" + ignore in4 + label in5 "+5V" + ignore in6 + label in7 "VSB" + label in8 "VBAT" +# ACPI says nothing about VSB and VBAT, so you might want to uncomment: +#ignore in7 +#ignore in8 + +# The W83627DHG has no in9, uncomment the following line + ignore in9 + +# ACPI says: + compute in1 @*(1+(56/10)), @/(1+(56/10)) +# ACPI says... but obviously wrong: +# compute in3 @*(1+(34/34)), @/(1+(34/34)) +# ACPI says: + compute in5 @*(1+(22/10)), @/(1+(22/10)) +# ACPI says nothing about in8, so I guess: + compute in8 @*1.42, @/1.42 + +# Values for Conroe-L (Celeron 420/430/440) + set in0_min 1.0*0.95 + set in0_max 1.3375*1.05 + + set in1_min 12.0*0.9 + set in1_max 12.0*1.1 + set in2_min 3.3*0.95 + set in2_max 3.3*1.05 + set in3_min 3.3*0.95 + set in3_max 3.3*1.05 + set in5_min 5.0*0.95 + set in5_max 5.0*1.05 + set in7_min 3.3*0.95 + set in7_max 3.3*1.05 + set in8_min 3.0*0.85 + set in8_max 3.0*1.15 + +# Fans + label fan1 "Case Fan" + label fan2 "CPU Fan" + label fan3 "Aux Fan" + ignore fan1 + ignore fan3 + ignore fan4 + ignore fan5 + set fan2_min 600 + +# Temperatures + label temp1 "Sys Temp" + label temp2 "CPU Temp" + label temp3 "AUX Temp" + + ignore temp3 +# ACPI says: + set temp1_over 60 + set temp1_hyst 55 + set temp2_over 45 + set temp2_hyst 40 + diff --git a/configs/Asus/P5B-E.conf b/configs/Asus/P5B-E.conf new file mode 100644 index 0000000..bf62b6e --- /dev/null +++ b/configs/Asus/P5B-E.conf @@ -0,0 +1,95 @@ +# Contributed by Frank Enderle. + + +# This is the sensors.conf configuration file for ASUS P5B-E (and maybe it's different versions) +# Everythings based on the guide at http://www.lm-sensors.org/wiki/AsusFormulaHacking. The formulas +# and ranges are based on the /proc/acpi/dsdt readings of a P5B-E board with a E6600 CPU. + +chip "w83627dhg-*" +# == VOLTAGES == +# Vcore + label in0 "Vcore" + set in0_min 0.85 + set in0_max 1.6 + +# +12V + label in1 "+12V" + compute in1 @*(66/10), @/(66/10) + set in1_min 10.2 + set in1_max 13.8 + +# unused + ignore in2 + +# +3.3V + label in3 "+3.3V" + # this formula is stored in the ACPI, but it seems not to work + # compute in3 @*(68/34), @/(68/34) + set in3_min 2.97 + set in3_max 3.63 + +# unused + ignore in4 + +# +5V + label in5 "5V" + compute in5 @*(32/10), @/(32/10) + set in5_min 4.5 + set in5_max 5.5 + +# unused + ignore in6 + ignore in7 + ignore in8 + ignore in9 + +# == TEMPERATURES == +# Mainboard + label temp1 "Sys Temp" + set temp1_over 95 + set temp1_hyst 60 + +# CPU + label temp2 "CPU Temp" + set temp2_over 95 + set temp2_hyst 45 + +# unused + ignore temp3 + +# == FANS == +# If you miss a certain fan set it to ignore +# Chassis 1 + # ignore fan1 + label fan1 "Cha1 Fan" + set fan1_min 800 + +# CPU + # ignore fan2 + label fan2 "CPU Fan" + set fan2_min 600 + +# Powersupply + ignore fan3 + #label fan3 "Pwr Fan" + #set fan3_min 800 + +# unused + ignore fan4 + +# Chassis 2 + # ignore fan5 + label fan5 "Cha2 Fan" + set fan5_min 800 + +# == CORE TEMPERATURES == +# This requires the coretemp patch applied +# Maximums are autodetected by the driver depending on the CPU +# Core0 +chip "coretemp-isa-0000" + label temp1 "Core0 Temp" + +# Core1 +chip "coretemp-isa-0001" + label temp1 "Core1 Temp" + diff --git a/configs/Asus/P5E3.conf b/configs/Asus/P5E3.conf new file mode 100644 index 0000000..5aef313 --- /dev/null +++ b/configs/Asus/P5E3.conf @@ -0,0 +1,59 @@ +# Contributed by Alexey Torkhov + +# Main difference with existing config is different coefficient in voltage +# formula and different input (in5 instead of in6) for +5V. + + +# This is for an Asus P5E3 +chip "w83627dhg-*" + + label in0 "VCore" + label in1 "+12V" + label in3 "+3.3V" + label in5 "+5V" + + ignore in2 + ignore in4 + ignore in6 + ignore in7 + ignore in8 + +# +12V is in1 and +5V is in5 + compute in1 @*(1+(60/10)), @/(1+(60/10)) + compute in5 @*(1+(20/10)), @/(1+(20/10)) + # 10% tolerance for 12V + set in1_min 12.0*0.9 + set in1_max 12.0*1.1 + + # 5% for others + set in5_min 5.0*0.95 + set in5_max 5.0*1.05 + +# Set the 3.3V + set in3_min 3.3*0.95 + set in3_max 3.3*1.05 + +# Fans + label fan1 "Case Fan" + label fan2 "CPU Fan" + label fan3 "Aux Fan" +# ignore fan4 +# ignore fan5 + set fan1_min 600 + set fan2_min 600 + set fan3_min 600 + set fan4_min 600 + set fan5_min 600 + +# Temperatures + label temp1 "Sys Temp" + label temp2 "CPU Temp" + ignore temp3 + + set temp1_max 60 + set temp1_max_hyst 55 + set temp2_max 72 + set temp2_max_hyst 67 + set temp3_max 60 + set temp3_max_hyst 55 + diff --git a/configs/Asus/P5N32-E_SLI_Plus.conf b/configs/Asus/P5N32-E_SLI_Plus.conf new file mode 100644 index 0000000..8632e09 --- /dev/null +++ b/configs/Asus/P5N32-E_SLI_Plus.conf @@ -0,0 +1,118 @@ +# Contributed by Stéphane Urbanovski. + + +# Linux sensor configuration for an Asus P5N32-E SLI Plus +# 5/2007 s.urbanovski#ac-nancy-metz.fr +# (see http://www.lm-sensors.org/wiki/AsusFormulaHacking) + +chip "w83791d-*" + +## Voltage control : + + label in0 "1.2VHT Voltage" + set in0_min 1.2 + set in0_max 1.4 + + label in1 "SB CORE Voltage" + set in1_min 1.3 + set in1_max 1.7 + + label in2 "CPU VTT Voltage" + set in2_min 1.1 + set in2_max 1.4 + +# not sure ... + ignore in3 + + label in4 "DDR2 TERM Voltage" + set in4_min 0.5 + set in4_max 1.3 + +# not sure ... + ignore in5 + +# not sure ... + label in6 "NB CORE Voltage" + set in6_min 1.1 + set in6_max 1.6 + +# not sure ... + ignore in7 + +# pure speculation ... +# label in8 "Battery" +# set in8_min 2.5 +# set in8_max 3.5 + ignore in8 + +# not sure ... + label in9 "MEMORY Voltage" + set in9_min 1.6 + set in9_max 2.5 + +## Fan control + + label fan1 "OPT1 FAN Speed" + label fan2 "OPT2 FAN Speed" + label fan3 "OPT3 FAN Speed" + label fan4 "OPT4 FAN Speed" + label fan5 "OPT5 FAN Speed" + +## Temp control + + ignore temp1 + ignore temp2 + ignore temp3 + + + +chip "it8718-*" + +## Voltage control : + +# not sure ... + label in0 "CPU Core Voltage" + set in0_min 1.1 + set in0_max 1.5 + compute in0 @+0.08, @-0.08 + + label in1 "+3.3 Voltage" + set in1_min 3.00 + set in1_max 3.60 + + ignore in2 + + label in3 "+5.0 Voltage" + set in3_min 4.50 + set in3_max 5.50 + compute in3 @*(84/50), @*(50/84) + + label in4 "+12.0 Voltage" + set in4_min 11.2 + set in4_max 13.2 + compute in4 @*4, @/4 + + ignore in5 + + label in6 "VIN6 ?" + + ignore in7 + ignore in8 + + ignore vid + +## Fan control + + label fan1 "CPU FAN Speed" + label fan2 "CHA FAN Speed" + +## Temp control + + label temp1 "CPU Temp" + set temp1_over 50 + set temp1_low 15 + + label temp2 "MB Temp" + set temp2_over 55 + set temp2_low 15 + ignore temp3 diff --git a/configs/Asus/P5PE-VM.conf b/configs/Asus/P5PE-VM.conf new file mode 100644 index 0000000..fdd5759 --- /dev/null +++ b/configs/Asus/P5PE-VM.conf @@ -0,0 +1,70 @@ +### Import note: separately listed for this motherboard, merged with config: + +# sensors-detect will report a W83627DHG device and suggest loading the +# w83627ehf driver. However this motherboard has an ACPI BIOS which accesses +# the W83627DHG device already, so using the w83627ehf driver is not safe and +# thus discouraged. + +################## + +### Sensors configuration for Asus P5PE-VM motherboard +### 2014-02-28, ianp +### Comments are welcome. + + +chip "w83627ehf-*" + + +### Voltages + + label in1 "+12V" + ignore in4 # ignored (not used?) + label in5 "+5V" + ignore in6 # ignore these + ignore in9 # as well (not used) + ignore cpu0_vid # Always at 0 in my case, so ignore it + + ### Scale +5V and +12V. + + compute in5 @*(1+22/10), @/(1+22/10) + compute in1 @*(1+56/10), @/(1+56/10) + + ### Set in0 according to CPU nominal voltage. + + set in0_min 1.2000 + set in0_max 1.3375 + set in5_min 5 * 0.95 + set in5_max 5 * 1.05 + set in1_min 12 * 0.95 + set in1_max 12 * 1.05 + +### Temperatures + + # temp3 is unidentified + + label temp1 "M/B Temp" + label temp2 "CPU Temp" + + ### Set according to preference. + + set temp1_max 60 + set temp1_max_hyst 55 + set temp2_max 60 + set temp2_max_hyst 55 + +### Fans + + ### Ignore fan3 and fan5. There are + ### only 2 fan connectors on this board. + ### fan4 is missing. + + label fan1 "CHA Fan" + label fan2 "CPU Fan" + ignore fan3 + ignore fan5 + + ### Set according to preference. + + set fan1_min 0 + set fan2_min 900 + diff --git a/configs/Asus/P8B75-V.conf b/configs/Asus/P8B75-V.conf new file mode 100644 index 0000000..7472c49 --- /dev/null +++ b/configs/Asus/P8B75-V.conf @@ -0,0 +1,72 @@ +# ASUSTeK COMPUTER INC. P8B75-V Motherboard +# 2018, contributed by Leigh Brown +# +# dmi: board_name: P8B75-V +# dmi: board_vendor: ASUSTeK COMPUTER INC. +# dmi: bios_version: 1608 +# cpu: Intel(R) Core(TM) i3-3220 CPU @ 3.30GHz +# driver: nct6775 +# +# NB: temp7 (PECI Agent 0) is very inaccurate at low temperatures +# NB: Vcore limits may be different for different CPUs + +chip "nct6779-isa-*" + label in0 "Vcore" + set in0_min 0.44 # Will reduce when idle + set in0_max 1.08 * 1.10 # Allow for a small amount of overclocking + + label in1 "+5V" + compute in1 @*5, @/5 + set in1_min 5.00 * 0.90 + set in1_max 5.00 * 1.10 + + label in2 "AVCC" + set in2_min 3.30 * 0.90 + set in2_max 3.30 * 1.10 + + label in3 "+3.3V" + set in3_min 3.30 * 0.90 + set in3_max 3.30 * 1.10 + + label in4 "+12V" + compute in4 @*12, @/12 + set in4_min 12.0 * 0.95 + set in4_max 12.0 * 1.05 + + label in7 "3VSB" + set in7_min 3.30 * 0.90 + set in7_max 3.30 * 1.10 + + label in8 "VBAT" + set in8_min 3.00 * 0.90 + set in8_max 3.30 * 1.10 + + ignore in5 + ignore in6 + ignore in9 + ignore in10 + ignore in11 + ignore in12 + ignore in13 + ignore in14 + + # Fans + label fan1 "CHA_FAN1" + label fan2 "CPU_FAN1" + ignore fan3 + label fan4 "CHA_FAN2" + ignore fan5 + + set temp1_max 40.0 + set temp1_max_hyst 35.0 + + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore temp8 + ignore temp9 + ignore temp10 + + ignore intrusion0 + ignore intrusion1 diff --git a/configs/Asus/P8H77-I.conf b/configs/Asus/P8H77-I.conf new file mode 100644 index 0000000..ed9cd91 --- /dev/null +++ b/configs/Asus/P8H77-I.conf @@ -0,0 +1,38 @@ +# lm-sensors configuration file for the Asus P8H77-I motherboard +# Victor Serverov gmail.com> +# 29-Aug-2013 +# + +chip "it8771-*" + + label in0 "Vcore" + label in1 "Vram" + label in2 "+12V" + label in3 "+5V" + label in4 "+3.3V" + ignore in5 + ignore in6 + ignore in7 # Value changes all the time + + compute in2 @*(72/12), @/(72/12) + compute in3 @*(30/12), @/(30/12) + compute in4 @*(1978/1200), @/(1978/1200) + + # Vcore limits for a Pentium G2020 processor + set in0_min 0.86 * 0.95 + set in0_max 0.92 * 1.05 + set in1_min 1.5 * 0.95 + set in1_max 1.5 * 1.05 + set in2_min 12.0 * 0.95 + set in2_max 12.0 * 1.05 + set in3_min 5.0 * 0.95 + set in3_max 5.0 * 1.05 + set in4_min 3.3 * 0.95 + set in4_max 3.3 * 1.05 + + label fan1 "CPU Fan" + label fan2 "Chassis Fan" + + label temp1 "CPU Temp" + label temp2 "M/B Temp" + ignore temp3 diff --git a/configs/Asus/P8P67_Pro.conf b/configs/Asus/P8P67_Pro.conf new file mode 100644 index 0000000..93b6ab2 --- /dev/null +++ b/configs/Asus/P8P67_Pro.conf @@ -0,0 +1,57 @@ +# Preliminary configuration file contributed by Artem S. Tashkinov. + + +chip "nct6776-*" +# nct6776 values for Asus P8P67 PRO + +label in0 "Vcore" + set in0_min 0.75 + set in0_max 1.35 + +label in1 "+12V" + compute in1 @ * 12, @ / 12 + set in1_min 12 * 0.95 + set in1_max 12 * 1.05 + +label in2 "AVCC" + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + +label in3 "+3.3V" + set in3_min 3.3 * 0.95 + set in3_max 3.3 * 1.05 + +label in4 "+5V" + compute in4 @ * 5, @ / 5 + set in4_min 5 * 0.95 + set in4_max 5 * 1.05 + +# always reads +2.04V, ignoring +ignore in5 + +label in7 "3VSB" + set in7_min 3.3 * 0.95 + set in7_max 3.3 * 1.05 + +label in8 "Vbat" + set in8_min 3.3 * 0.95 + set in8_max 3.3 * 1.05 + +label temp1 "MB" + set temp1_max 50 + set temp1_max_hyst 40 + +# always reads -60C, ignoring +ignore temp2 + +label temp3 "MB's CPU sensor" + +label fan2 "CPU Fan" + set fan2_min 500 + +# Ignore these fans if not present +#ignore fan1 +#ignore fan3 +#ignore fan4 +#ignore fan5 + diff --git a/configs/Asus/Q1900-ITX.conf b/configs/Asus/Q1900-ITX.conf new file mode 100644 index 0000000..92f71fc --- /dev/null +++ b/configs/Asus/Q1900-ITX.conf @@ -0,0 +1,38 @@ +# Q1900 ITX Motherboard with a intel DTS Sensor, ITX format +# 2018, by J. Schwender +# dmi: Q1900-ITX +# driver: nct6775 +# +chip "soc_dts0-virtual-*" + label temp1 "DTS 1" + +chip "soc_dts1-virtual-*" + label temp1 "DTS 2" + +# ACPI thermal zone: +chip "acpitz-virtual-*" + label temp1 "CPU Socket" + +# ADC has 8 mV conversion steps +chip "nct6776-isa-*" + label fan1 "System fan" + ignore fan2 + ignore fan3 + ignore in4 # not shown in BIOS + ignore in6 # not shown in BIOS + ignore intrusion0 + ignore intrusion1 + ignore PCH_CHIP_TEMP +# BIOS shows 24 mV steps in Readout for +5 V + label in5 "+5 V" + set in5_min 5 * 0.95 + set in5_max 5 * 1.05 + compute in5 @*3.00,@/3.00 +# BIOS shows 53 mV steps for 12 V + label in1 "+12 V" + set in1_min 12 * 0.95 + set in1_max 12 * 1.05 + compute in1 @*6.625,@/6.625 + + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 diff --git a/configs/Asus/TUSI-M.conf b/configs/Asus/TUSI-M.conf new file mode 100644 index 0000000..a64f734 --- /dev/null +++ b/configs/Asus/TUSI-M.conf @@ -0,0 +1,49 @@ +# Asus TUSI-M motherboard configuration contributed by Dawn Light +chip "it87-*" + + label in0 "VCore 1" + label in1 "VCore 2" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "3.3 Stdby" + label in6 "-12V" + label in7 "Stdby" + label in8 "VBat" + + set in0_min 1.5 * 0.95 + set in0_max 1.5 * 1.05 + set in1_min 2.4 + set in1_max 2.6 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5.0 * 0.95 + set in3_max 5.0 * 1.05 + set in4_min 12 * 0.90 + set in4_max 12 * 1.10 + set in5_min 3.3 * 0.95 + set in5_max 3.3 * 1.05 + set in6_max -12 * 0.90 + set in6_min -12 * 1.10 + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 + + ignore vid + + compute in2 @ * 2 , @ / 2 + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((30/10) +1)*@ , @/((30/10) +1) + compute in6 (1+232/56)*@ - 4.096*232/56, (@ + 4.096*232/56)/(1+232/56) + compute in5 @ * 2 , @ / 2 + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + + # Temperature + label temp1 "CPU Temp" +# ignore temp2 +# ignore temp3 + + # Fans + label fan2 "CPU Fan" +# set fan2_min 3000 +# ignore fan1 +# ignore fan3 diff --git a/configs/Asus/TX97-E.conf b/configs/Asus/TX97-E.conf new file mode 100644 index 0000000..cb4e1ac --- /dev/null +++ b/configs/Asus/TX97-E.conf @@ -0,0 +1,82 @@ +# lm_sensors 3 configuration file for the Asus TX97-E motherboard +# 2005-11-14, Jean Delvare +# Comments welcome! + +chip "lm78-*" + +### Voltages + + # Vcore is monitored twice because this is a "dual plane" CPU + # (Intel Pentium 166 MMX). + label in0 "Vcore 1" + label in1 "Vcore 2" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "-12V" + label in6 "-5V" + + compute in3 @*((6.8/10)+1), @/((6.8/10)+1) + compute in4 @*((28/10)+1), @/((28/10)+1) + compute in5 @*(-210/60.4), @/(-210/60.4) + compute in6 @*(-90.9/60.4), @/(-90.9/60.4) + + # It looks like you can't trust VID readings when using a dual plane + # CPU (e.g. Intel Pentium MMX or AMD K6) on the TX97-E. It will report + # the "equivalent" (jumper-wise) single plane voltage. At least this is + # what I can observe since I use a Pentium 166 MMX, which uses 2.8V + # dual plane, and VID reads 3.4V, which is the same jumper combination + # for single plane. This also seems to suggest that the VID value comes + # from the motherboard and not the CPU itself as is the case with later + # models. + ignore cpu0_vid + + set in0_min 2.7 + set in0_max 2.9 + set in1_min 2.7 + set in1_max 2.9 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5.0 * 0.95 + set in3_max 5.0 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + set in5_min -12 * 0.95 + set in5_max -12 * 1.05 + set in6_min -5 * 0.95 + set in6_max -5 * 1.05 + +### Fans + + label fan1 "Case Fan" + label fan2 "CPU Fan" + label fan3 "P/S Fan" + + # I only have a CPU fan on this system. Note that the power supply fan + # header surprisingly did not seem to be powered anyway, so I couldn't + # have used it if I had wanted to. + ignore fan1 + ignore fan3 + + set fan2_div 2 + set fan2_min 4800 + +### Temperatures + + label temp1 "M/B Temp" + + set temp1_max 40 + set temp1_max_hyst 38 + +chip "lm75-*" + + label temp1 "CPU Temp" + + # Contrary to most motherboards, the Asus TX97-E needs scaling, + # supposedly to compensate for the thermistor-to-CPU distance. The + # formula doesn't make much physical sense, but will give the same + # value as the BIOS displays. + compute temp1 @*2, @/2 + + set temp1_max 80 + set temp1_max_hyst 75 diff --git a/configs/Axiomtek/CAPA800.conf b/configs/Axiomtek/CAPA800.conf new file mode 100644 index 0000000..04176fc --- /dev/null +++ b/configs/Axiomtek/CAPA800.conf @@ -0,0 +1,25 @@ +# input routing and scaling mostly based on datasheet recommended setup, +# differences were determined experimentally + +chip "w83627uhg-*" + label in0 "Vcore" + + label in1 "+12V" + compute in1 @ * (10 + 150) / 10, @ * 10 / (10 + 150) + set in1_min 12 * 0.95 + set in1_max 12 * 1.05 + + #label in4 "+2.5V" + #compute in4 @ * 2 / 1, @ * 1 / 2 + # ^ probable, not in BIOS + ignore in4 + + label in5 "+3.3V" + compute in5 @ * 2 / 1, @ * 1 / 2 + set in5_min 3.3 * 0.95 + set in5_max 3.3 * 1.05 + + ignore fan1 + label fan2 "CPUFAN" + + ignore intrusion0 diff --git a/configs/Biostar/N68S+.conf b/configs/Biostar/N68S+.conf new file mode 100644 index 0000000..be340df --- /dev/null +++ b/configs/Biostar/N68S+.conf @@ -0,0 +1,122 @@ +# Configuration file contributed by Lee Marriott. + + +# libsensors configuration file +# ----------------------------- +# +# This is a first attempt at a custom configuration file for the Biostar N68S+. +# This custom configuration file should be copied to /etc/sensors.d/Biostar-N68S+.conf. +# +# Custom configuration files for some specific mainboards can be found at +# http://www.lm-sensors.org/wiki/Configurations + +# READ THE MAN PAGE DOCUMENTATION OF 'sensors.conf' FOR MORE +# COMPLETE INFORMATION. ie: + +# man sensors.conf + +# Regarding the Biostar N68S+ motherboard: This motherboard supports +# both manual overclocking by individual settings and preconfigured +# overclocking using predefined sets of overclock settings. + +chip "it8716-*" + +# All labels set to match Biostar N68S+ BIOS displayed labels. See +# the 'PC Health' screen in the BIOS. + +# Voltage settings + + label in0 " Vcore" + label in1 "Chipset" + ignore in2 # +3.3 V not in BIOS + label in3 " +5 V" # VCC + label in4 " +12 V" + label in5 " DDR" + label in6 " HT" + label in7 " 5VSB" + label in8 " Vbat" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((30/10)+1)*@ , @/((30/10)+1) + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + + ignore cpu0_vid + +# Other than +3.3, +5.0 and +12.0 voltages (here set plus/minus 10%), the +# indicated min/max voltages are a guess based on present measurements +# and similar to those on my Asus m/b. +# + + set in0_min 0.80 + set in0_max 1.80 + set in1_min 1.1 + set in1_max 1.76 +# set in2_min 3.3 * 0.90 +# set in2_max 3.3 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + set in4_min 12.0 * 0.90 + set in4_max 12.0 * 1.10 + set in5_min 1.60 + set in5_max 2.20 + set in6_min 0.95 + set in6_max 1.4 + set in7_min 5.0 * 0.90 + set in7_max 5.0 * 1.10 + +# Fan settings + + label fan1 "CPU fan" + label fan2 "Sys1fan" + label fan3 " NB fan" + + # Ignore fans you don't have + ignore fan3 + +# +# The Biostart N68S+ is based upon the nVidia GeForce 7025/nForce 630a +# chipset and comes with active (fan based) cooling. + +# Biostar N68S+ can allow 0 rpm for the CPU fan when in SMART +# fan control mode. Set min speeds as applicable for your system. + +# set fan1_min 1000 + set fan1_min 0 + set fan2_min 1000 +# set fan3_min 5600 + +# Temperature sensor settings + + label temp1 "CPU Tmp" + label temp2 "M/B Tmp" + label temp3 "NB " + +# BioStar N68S+ BIOS doesn't use 'temp2' and 'temp3'. + + ignore temp2 + ignore temp3 + +# Only set tempX_type if you have PC Health [disabled] +# in your BIOS???? Generally, the kernel {lmsensors} will +# correctly detect individual temperature sensor type and +# set values accordingly. +# 2 = thermistor; 3 = thermal diode; 0 = unused + +# set temp1_type 2 +# set temp2_type 2 +# set temp3_type 3 + +# Set your temparature max values. Warning: If your values here +# are set higher than the values set in your BIOS, then you may +# shutdown at a lower temperature than you think. It's probably +# best to assume that shutdown will occur at the lowest setting +# whenever the value here and the BIOS are different. + + set temp1_max 50 + set temp1_min 10 +# set temp2_max 50 +# set temp2_min 10 + +# The other possibility is that a value set here will always +# override the BIOS. You may or may not want that behavior. + diff --git a/configs/DFI/CFX3200-M2-G-infinity.conf b/configs/DFI/CFX3200-M2-G-infinity.conf new file mode 100644 index 0000000..75b8d20 --- /dev/null +++ b/configs/DFI/CFX3200-M2-G-infinity.conf @@ -0,0 +1,61 @@ +# lm_sensors configuration file for the CFX3200-M2/G infinity motherboard +# 2007-07-06, George Multescu + +chip "it8716-*" + +# Voltages + + label in0 "VCore" #-->cpu voltage + label in1 "VDDR" + label in2 "+3.3V" # VCC3 + label in3 "+5V" # VCC + label in4 "V_NBr" #--> notrh bridge voltage + label in5 "+12V" + ignore in6 + label in7 "5VSB" # VCCH + label in8 "VBat" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in5 ((30/10)+1.02)*@ , @/((30/10)+1.02) #-->not sure about this one, check this value(+12v) against bios + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# If vid (nominal CPU voltage) isn't correct, hardcode the correct value +# instead. +# set in0_min vid * 0.95 +# set in0_max vid * 1.05 +# set in1_min 1.8 * 0.95 +# set in1_max 1.8 * 1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5 * 0.95 +# set in3_max 5 * 1.05 + set in4_min 1.18 * 0.95 + set in4_max 1.18 * 1.05 + set in5_max 12 * 1.05 + set in5_min 12 * 0.95 +# set in6_max -5 * 0.95 +# set in6_min -5 * 1.05 +# set in7_min 5 * 0.95 +# set in7_max 5 * 1.05 +# The chip does not support in8 min/max + +# Temperatures + + +label temp1 "System Temp" +label temp2 "CPU Temp" +label temp3 "ChipsetTemp" + +# set temp1_over 60 +# set temp1_low 10 +# set temp2_over 50 +# set temp2_low 10 + +# Fans + +label fan1 "Chipset Fan" +label fan2 "CPU Fan" +label fan3 "System fan" + +# set fan1_min 2000 +# set fan2_min 2000 diff --git a/configs/DFI/EL620-C.conf b/configs/DFI/EL620-C.conf new file mode 100644 index 0000000..e77d7e4 --- /dev/null +++ b/configs/DFI/EL620-C.conf @@ -0,0 +1,82 @@ +# lm_sensors configuration file for DFI Itox EL620-C industrial motherboard +# 2012-06-20, Paul Crawford +# Based on feedback from DFI and the schematic sheet 15 of 24, revision A1, 28 October 2011 + +# Winbond W83627DHG configuration for EL620-C +chip "w83627dhg-*" + + label in0 "VCore" + label in1 "+5V" + label in2 "AVCC" + label in3 "+3.3V" + label in4 "+1.1V" + label in5 "Vmemory" + label in6 "+12V" + label in7 "Vstandby" + label in8 "VBAT" + +# +12V and +5V use dividers from schematic + compute in1 @*(1+(30.1/10)), @/(1+(30.1/10)) + compute in6 @*(1+(60.4/10)), @/(1+(60.4/10)) + +# We need to set voltage limits. + set in0_min 0.80 + set in0_max 1.55 + + set in1_min 5.0*0.95 + set in1_max 5.0*1.05 + + set in2_min 3.3*0.95 + set in2_max 3.3*1.05 + + set in3_min 3.3*0.95 + set in3_max 3.3*1.05 + + set in4_min 1.1*0.95 + set in4_max 1.1*1.05 + +# DDR3 voltage range + set in5_min 1.30 + set in5_max 1.58 + +# Original ATX spec was +/-10% on +12V, but recent ATX12V version 2.2 spec is 5% (still 10% on unmonitored -12V) + set in6_min 12.0*0.95 + set in6_max 12.0*1.05 + + set in7_min 3.3*0.95 + set in7_max 3.3*1.05 + +# Battery voltage, assume CR2032 Lithium-Manganese Dioxide Battery. +# This actually seems not to be needed as hard-coded? + set in8_min 2.7 + set in8_max 3.3 + +# Fans + label fan1 "System Fan" + label fan2 "CPU Fan" + label fan3 "2nd Fan" + ignore fan4 + ignore fan5 + +# Fan minimums, disable fan1 & fan3 as a case fan is not always connected + set fan1_min 0 + set fan2_min 500 + set fan3_min 0 + +# Temperatures. Can we assume temp2 limit for CPU is set by BIOS? + + label temp1 "System Temp" + label temp2 "CPU Temp" + label temp3 "NB Temp" + + set temp1_max 65 + set temp1_max_hyst 55 + + set temp3_max 65 + set temp3_max_hyst 55 + +# Not sure what this is, always reported 0.000 and the VID0-VID7 pins are not connected on schematic. + ignore cpu0_vid + +# From the Intel CPU itself? Seems not to need any special configuration. +#chip "coretemp-*" diff --git a/configs/DFI/Lanparty_MI_P55-T36.conf b/configs/DFI/Lanparty_MI_P55-T36.conf new file mode 100644 index 0000000..e1b2d6d --- /dev/null +++ b/configs/DFI/Lanparty_MI_P55-T36.conf @@ -0,0 +1,88 @@ +# lm_sensors configuration file for the board +# DFI LP MI P55-T36 +# (The above name is reported by sensors-detect -A rev. 5818) +# 2010-06-06, Lars Kr. Lundin +# 2010-06-27, in3, in4 and in7 configuration added by Jean Delvare + +chip "it8720-*" +# (sensors-detect -A: Found `ITE IT8720F Super IO Sensors') + +# Voltages + +# All these voltages match those listed in the BIOS: + +label in0 "Vcore" +label in1 "Vtt" +label in2 "+3.30V" +label in3 "+5V" +label in4 "+12V" +label in5 "CPU PLL" +label in6 "DRAM Voltage" +label in7 "5VSB" + +compute in3 @ * (6.8/10+1), @ / (6.8/10+1) +compute in4 @ * (30/10+1), @ / (30/10+1) +compute in7 @ * (6.8/10+1), @ / (6.8/10+1) + +# Temperatures + +# (sensors-detect -A finds NVIDIA i2c adapter i2c-[012345] +# with clients found for i2c-1 and i2c-5. +# The GPU temperature sensor is however not detected). + +label temp1 "PCH Temp" +label temp2 "PWM Temp" +label temp3 "CPU Temp" + +# Default sensors output for temp3 is "disabled" and a too low temp shown. + +# From intel.com: +# Digital Thermal Sensor (DTS) Provides for more efficient processor and platform thermal control, improving system acoustics. The DTS continuously measures the temperature at each processing core. The ability to continuously measure and detect variations in processor temperature enables system fans to spin only as fast as needed to cool the system. The combination of these technologies can result in significantly lower noise emissions from the PC. + +# True Shown +# 18 4 + +# Correct the CPU temperature (at least at 18C): +compute temp3 14+@, @-14 + +# With the above correction the CPU temperature looks meaningful +# and well correlated with the PWM temperature for varying CPU loads +# and CPU fan speeds. +# However the CPU temperature sensor responds to changes in the +# CPU load almost instantaneously. + +# The sensor type for the DTS sensor currently comes out as: disabled +# Don't know what sensor type to use for DTS sensor, so leave the default +# set temp3_type 0 + +# Fans + +ignore fan1 + +# The BIOS labels the PWM (Pulse Width Modulated) fan "CPU fan". +# The BIOS labels the other, non-PWM fan "PWM fan". This may be +# because this second fan is intended to cool the mainboards +# MOSFET PWMs. +label fan2 "PWM fan" +label fan3 "CPU fan" + +# Example sensors output (CPU busy): + +# it8720-isa-0a10 +# Adapter: ISA adapter +# Vcore: +1.12 V (min = +0.00 V, max = +4.08 V) +# Vtt: +1.15 V (min = +0.00 V, max = +4.08 V) +# +3.30V: +3.26 V (min = +0.00 V, max = +4.08 V) +# +5V: +4.87 V (min = +0.00 V, max = +6.85 V) +# +12V: +11.71 V (min = +0.00 V, max = +16.32 V) +# CPU PLL: +1.81 V (min = +0.00 V, max = +4.08 V) +# DRAM Voltage: +1.65 V (min = +0.00 V, max = +4.08 V) +# 5VSB: +4.87 V (min = +0.00 V, max = +6.85 V) +# Vbat: +3.38 V +# PWM fan: 4560 RPM (min = 0 RPM) +# CPU fan: 602 RPM (min = 0 RPM) +# PCH Temp: +54.0°C (low = -1.0°C, high = +127.0°C) sensor = thermistor +# PWM Temp: +59.0°C (low = -1.0°C, high = +127.0°C) sensor = thermistor +# CPU Temp: +58.0°C (low = +13.0°C, high = +141.0°C) sensor = disabled +# cpu0_vid: +1.300 V +# diff --git a/configs/Epox/M1697.conf b/configs/Epox/M1697.conf new file mode 100644 index 0000000..4db62b4 --- /dev/null +++ b/configs/Epox/M1697.conf @@ -0,0 +1,39 @@ +# lm_sensors configuration file for the Epox EP-9U1697 GLI motherboard +# 2007-07-06, Hans de Goede +# Comments welcome! + +# Notice that the Epox ep1308 chip on the board in reality is a Fintek f71883fg + +chip "f71882fg-*" + +# Temperature + label temp1 "CPU" + label temp2 "System" + ignore temp3 + +# Fans + label fan1 "CPU" + ignore fan2 + ignore fan3 + ignore fan4 + +# Voltage + label in0 "3.3V" + label in1 "Vcore" + label in2 "Vdimm" + label in3 "Vchip" + label in4 "+5V" + label in5 "12V" + label in6 "5VSB" + label in7 "3VSB" + label in8 "Batery" + +# never change the in0, in7 and in8 compute, these are hardwired in the chip! + compute in0 (@ * 2), (@ / 2) + compute in2 (@ * 2), (@ / 2) + compute in3 (@ * 2), (@ / 2) + compute in4 (@ * 5.25), (@ / 5.25) + compute in5 (@ * 12.83), (@ / 12.83) + compute in6 (@ * 5.25), (@ / 5.25) + compute in7 (@ * 2), (@ / 2) + compute in8 (@ * 2), (@ / 2) diff --git a/configs/Epox/MF4-Ultra3.conf b/configs/Epox/MF4-Ultra3.conf new file mode 100644 index 0000000..e0608f8 --- /dev/null +++ b/configs/Epox/MF4-Ultra3.conf @@ -0,0 +1,48 @@ +# lm_sensors configuration file for the Epox MF4 Ultra3 motherboard +# 2007-08-14, Hans de Goede +# Comments welcome! + +# Notice that the Epox ep1308 chip on the board in reality is a Fintek f71883fg + +chip "k8temp-*" + + label temp1 "Core0 Temp" + label temp2 "Core0 Temp" + label temp3 "Core1 Temp" + label temp4 "Core1 Temp" + + +chip "f71882fg-*" + +# Temperature + label temp1 "CPU" + label temp2 "System" + ignore temp3 + +# Fans + label fan1 "CPU" + label fan2 "System" + label fan3 "Power" + label fan4 "Aux" + +# Voltage + label in0 "3.3V" + label in1 "+5V" + label in2 "Vdimm" + label in3 "5VSB" + label in4 "12V" + label in5 "Vchip" + label in6 "Vcore" + label in7 "3VSB" + label in8 "Battery" + +# never change the in0, in7 and in8 compute, these are hardwired in the chip! + compute in0 (@ * 2), (@ / 2) + compute in1 (@ * 5.25), (@ / 5.25) + compute in2 (@ * 2.5), (@ / 2.5) + compute in3 (@ * 5.25), (@ / 5.25) + compute in4 (@ * 11), (@ / 11) + compute in5 (@ * 1.5), (@ / 1.5) + compute in6 (@ * 1.5), (@ / 1.5) + compute in7 (@ * 2), (@ / 2) + compute in8 (@ * 2), (@ / 2) diff --git a/configs/Evga/x58-SLI.conf b/configs/Evga/x58-SLI.conf new file mode 100644 index 0000000..2a287f6 --- /dev/null +++ b/configs/Evga/x58-SLI.conf @@ -0,0 +1,37 @@ +# I have changed it for Evga x58 SLI board. -devsk 06-11-2009 +# +chip "f71882fg-*" + +# Temperature + label temp1 "CPU" + label temp2 "VREG" + label temp3 "System" + #ignore temp3 + +# Fans + label fan1 "CPU" + label fan2 "Power" + label fan3 "Chassis" + label fan4 "Aux" + +# Voltage + label in0 "3.3V" + label in1 "Vcore" + label in2 "Vdimm" + label in3 "Vtt" + label in4 "NB" + label in5 "+5V" + label in6 "+12V" + label in7 "3VSB" + label in8 "Battery" + +# never change the in0, in7 and in8 compute, these are hardwired in the chip! + compute in0 (@ * 2), (@ / 2) + compute in1 (@ * 1.47), (@ / 1.47) + compute in2 (@ * 1.45), (@ / 1.45) + compute in3 (@ * 1.241), (@ / 1.241) + compute in4 (@ * 1.241), (@ / 1.241) + compute in5 (@ * 5.25), (@ / 5.25) + compute in6 (@ * 9.23), (@ / 9.23) + compute in7 (@ * 2), (@ / 2) + compute in8 (@ * 2), (@ / 2) diff --git a/configs/Foxconn/A7GM-S_2.0.conf b/configs/Foxconn/A7GM-S_2.0.conf new file mode 100644 index 0000000..89171e2 --- /dev/null +++ b/configs/Foxconn/A7GM-S_2.0.conf @@ -0,0 +1,41 @@ +# Configuration file contributed by Göran Uddeborg. + + +chip "it8716-*" + + label in0 "CPU core" + label in1 "DRAM voltage" + label in2 "+3.3V" + # +5V + label in4 "+12V" + label in5 "+1.1V" + ignore in6 + ignore in7 + label in8 Vbat + + compute in3 @ * (1 + 6.8 / 10), @ / (1 + 6.8 / 10) + compute in4 @ * 4, @ / 4 + + label fan1 "CPU fan" + label fan2 "Chassis fan" + ignore fan3 + + label temp1 "CPU temp" + label temp2 "System temp" + ignore temp3 + + # Min and max for Athlon II X2 245e + set in0_min 0.875 + set in0_max 1.4 + # JEDEC standard for DDR2 + set in1_min 1.7 + set in1_max 1.9 + # 5 % tolerance on the remaining measurements + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5.0 * 0.95 + set in3_max 5.0 * 1.05 + set in4_min 12.0 * 0.95 + set in4_max 12.0 * 1.05 + set in5_min 1.1 * 0.95 + set in5_max 1.1 * 1.05 diff --git a/configs/FujitsuTechnologySolutions/D2312_(A1,_A2,_C1,_C2).conf b/configs/FujitsuTechnologySolutions/D2312_(A1,_A2,_C1,_C2).conf new file mode 100644 index 0000000..e2c4a02 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2312_(A1,_A2,_C1,_C2).conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions Fujitsu D2312 (A1, A2, C1, C2), "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2314_(A1,_A2).conf b/configs/FujitsuTechnologySolutions/D2314_(A1,_A2).conf new file mode 100644 index 0000000..05509c7 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2314_(A1,_A2).conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions Fujitsu D2314 (A1, A2), "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2317_(A1,_A2).conf b/configs/FujitsuTechnologySolutions/D2317_(A1,_A2).conf new file mode 100644 index 0000000..915e5d0 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2317_(A1,_A2).conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2317 (A1, A2), "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2344_(A1,_A2).conf b/configs/FujitsuTechnologySolutions/D2344_(A1,_A2).conf new file mode 100644 index 0000000..5c38480 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2344_(A1,_A2).conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2344 (A1, A2), "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2348_(A1,_A2).conf b/configs/FujitsuTechnologySolutions/D2348_(A1,_A2).conf new file mode 100644 index 0000000..c13bcae --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2348_(A1,_A2).conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2348 (A1, A2), "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2364_(A1,_A2).conf b/configs/FujitsuTechnologySolutions/D2364_(A1,_A2).conf new file mode 100644 index 0000000..404facb --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2364_(A1,_A2).conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2364 (A1, A2), "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2438_(A1,_A2).conf b/configs/FujitsuTechnologySolutions/D2438_(A1,_A2).conf new file mode 100644 index 0000000..e664c7b --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2438_(A1,_A2).conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2438 (A1, A2), "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2584_(A1,_A5).conf b/configs/FujitsuTechnologySolutions/D2584_(A1,_A5).conf new file mode 100644 index 0000000..4d45996 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2584_(A1,_A5).conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2584 (A1, A5), "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2587A1.conf b/configs/FujitsuTechnologySolutions/D2587A1.conf new file mode 100644 index 0000000..2d50a70 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2587A1.conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2587A1, "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2598A1.conf b/configs/FujitsuTechnologySolutions/D2598A1.conf new file mode 100644 index 0000000..a091a00 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2598A1.conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2598A1, "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2608_(A1,_K1).conf b/configs/FujitsuTechnologySolutions/D2608_(A1,_K1).conf new file mode 100644 index 0000000..ff14b9a --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2608_(A1,_K1).conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2608 (A1, K1), "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2618_(A1,_B1,_C1).conf b/configs/FujitsuTechnologySolutions/D2618_(A1,_B1,_C1).conf new file mode 100644 index 0000000..efe4400 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2618_(A1,_B1,_C1).conf @@ -0,0 +1,26 @@ +# Fujitsu Technology Solutions D2618 (A1, B1, C1), "Syleus"-Chip +# Contributed by Thilo Cestonaro + +chip "fscsyl-*" + +# Temperatures + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + label temp4 "Super I/O Temp" + label temp5 "Northbridge Temp" + +# Fans + label fan1 "CPU Fan" + label fan2 "System FAN2" + label fan3 "System FAN3" + label fan4 "System FAN4" + label fan7 "PSU Fan" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + ignore in4 + label in3 "+3.3V" + label in5 "+3.3V-Aux" diff --git a/configs/FujitsuTechnologySolutions/D2628_(A1,_B1,_C1).conf b/configs/FujitsuTechnologySolutions/D2628_(A1,_B1,_C1).conf new file mode 100644 index 0000000..09040ac --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2628_(A1,_B1,_C1).conf @@ -0,0 +1,26 @@ +# Fujitsu Technology Solutions D2628 (A1, B1, C1), "Syleus"-Chip +# Contributed by Thilo Cestonaro + +chip "fscsyl-*" + +# Temperatures + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + label temp4 "Super I/O Temp" + label temp5 "Northbridge Temp" + +# Fans + label fan1 "CPU Fan" + label fan2 "System FAN2" + label fan3 "System FAN3" + label fan4 "System FAN4" + label fan7 "PSU Fan" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + ignore in4 + label in3 "+3.3V" + label in5 "+3.3V-Aux" diff --git a/configs/FujitsuTechnologySolutions/D2679A1.conf b/configs/FujitsuTechnologySolutions/D2679A1.conf new file mode 100644 index 0000000..a88f524 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2679A1.conf @@ -0,0 +1,24 @@ +# Fujitsu Technology Solutions D2679A1, "Hades"-Chip +# Contributed by Thilo Cestonaro + +chip "fschds-*" + + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + ignore temp4 + ignore temp5 + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" diff --git a/configs/FujitsuTechnologySolutions/D2778_(A1,_B1,_C1,_X1,_Y1).conf b/configs/FujitsuTechnologySolutions/D2778_(A1,_B1,_C1,_X1,_Y1).conf new file mode 100644 index 0000000..210371b --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2778_(A1,_B1,_C1,_X1,_Y1).conf @@ -0,0 +1,26 @@ +# Fujitsu Technology Solutions D2778 (A1, B1 ,C1, X1, Y1), "Syleus"-Chip +# Contributed by Thilo Cestonaro + +chip "fscsyl-*" + +# Temperatures + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + label temp4 "Super I/O Temp" + label temp5 "Northbridge Temp" + +# Fans + label fan1 "CPU Fan" + label fan2 "System FAN2" + label fan3 "System FAN3" + label fan4 "System FAN4" + label fan7 "PSU Fan" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + ignore in4 + label in3 "+3.3V" + label in5 "+3.3V-Aux" diff --git a/configs/FujitsuTechnologySolutions/D2812_(A1,_A2).conf b/configs/FujitsuTechnologySolutions/D2812_(A1,_A2).conf new file mode 100644 index 0000000..66571d6 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2812_(A1,_A2).conf @@ -0,0 +1,26 @@ +# Fujitsu Technology Solutions D2812 (A1, A2), "Syleus"-Chip +# Contributed by Thilo Cestonaro + +chip "fscsyl-*" + +# Temperatures + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + label temp4 "Super I/O Temp" + label temp5 "Northbridge Temp" + +# Fans + label fan1 "CPU Fan" + label fan2 "System FAN2" + label fan3 "System FAN3" + label fan4 "System FAN4" + label fan7 "PSU Fan" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + ignore in4 + label in3 "+3.3V" + label in5 "+3.3V-Aux" diff --git a/configs/FujitsuTechnologySolutions/D2817A1.conf b/configs/FujitsuTechnologySolutions/D2817A1.conf new file mode 100644 index 0000000..ee56059 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2817A1.conf @@ -0,0 +1,26 @@ +# Fujitsu Technology Solutions D2817A1, "Syleus"-Chip +# Contributed by Thilo Cestonaro + +chip "fscsyl-*" + +# Temperatures + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + label temp4 "Super I/O Temp" + label temp5 "Northbridge Temp" + +# Fans + label fan1 "CPU Fan" + label fan2 "System FAN2" + label fan3 "System FAN3" + label fan4 "System FAN4" + label fan7 "PSU Fan" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + ignore in4 + label in3 "+3.3V" + label in5 "+3.3V-Aux" diff --git a/configs/FujitsuTechnologySolutions/D2828_(A1,_A2).conf b/configs/FujitsuTechnologySolutions/D2828_(A1,_A2).conf new file mode 100644 index 0000000..1ddbdd7 --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2828_(A1,_A2).conf @@ -0,0 +1,26 @@ +# Fujitsu Technology Solutions D2828 (A1, A2), "Syleus"-Chip +# Contributed by Thilo Cestonaro + +chip "fscsyl-*" + +# Temperatures + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + label temp4 "Super I/O Temp" + label temp5 "Northbridge Temp" + +# Fans + label fan1 "CPU Fan" + label fan2 "System FAN2" + label fan3 "System FAN3" + label fan4 "System FAN4" + label fan7 "PSU Fan" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + ignore in4 + label in3 "+3.3V" + label in5 "+3.3V-Aux" diff --git a/configs/FujitsuTechnologySolutions/D2831S1.conf b/configs/FujitsuTechnologySolutions/D2831S1.conf new file mode 100644 index 0000000..4e52b5b --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2831S1.conf @@ -0,0 +1,26 @@ +# Fujitsu Technology Solutions D2831S1, "Syleus"-Chip +# Contributed by Thilo Cestonaro + +chip "fscsyl-*" + +# Temperatures + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + label temp4 "Super I/O Temp" + label temp5 "Northbridge Temp" + +# Fans + label fan1 "CPU Fan" + label fan2 "System FAN2" + label fan3 "System FAN3" + label fan4 "System FAN4" + label fan7 "PSU Fan" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + ignore in4 + label in3 "+3.3V" + label in5 "+3.3V-Aux" diff --git a/configs/FujitsuTechnologySolutions/D2836S1.conf b/configs/FujitsuTechnologySolutions/D2836S1.conf new file mode 100644 index 0000000..7faf9ab --- /dev/null +++ b/configs/FujitsuTechnologySolutions/D2836S1.conf @@ -0,0 +1,26 @@ +# Fujitsu Technology Solutions D2836S1, "Syleus"-Chip +# Contributed by Thilo Cestonaro + +chip "fscsyl-*" + +# Temperatures + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + label temp4 "Super I/O Temp" + label temp5 "Northbridge Temp" + +# Fans + label fan1 "CPU Fan" + label fan2 "System FAN2" + label fan3 "System FAN3" + label fan4 "System FAN4" + label fan7 "PSU Fan" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + ignore in4 + label in3 "+3.3V" + label in5 "+3.3V-Aux diff --git a/configs/Gigabyte/B75-D3V.conf b/configs/Gigabyte/B75-D3V.conf new file mode 100644 index 0000000..9fa2334 --- /dev/null +++ b/configs/Gigabyte/B75-D3V.conf @@ -0,0 +1,107 @@ +# Configuration file contributed by Dominik Egert. + + +# libsensors configuration file +# ----------------------------- +# +# For the Gigabyte B75-D3V Rev: 1.2 +# +# +# + + ###################################### + # VOLTAGES # + # These figures are from estimations # + # based on values provided in BIOS. # + # This means that some of them may # + # be mixed up. # + ###################################### + + +############################################## +chip "it8728-isa-0a30" + +######## +# Fans +label fan1 "CPU-Fan" +set fan1_min 1000 + +label fan2 "System Fan 1" +set fan2_min 450 + +label fan3 "System Fan 2" +set fan3_min 450 + +label fan4 "System Fan 3" +set fan4_min 450 + +ignore fan5 #"Chassis Fan" # It is not connected, no pinout available. + + +################ +# Temperatures +label temp1 "System Temperature" +set temp1_min 10 +set temp1_max 60 + +ignore temp2 +#label temp2 "Unknown" # Does not seem to give sensible data (Always shows 25) + +label temp3 "Chipset Temperature" +set temp3_min 10 +set temp3_max 55 + + +############ +# Voltages +label in0 "Vtt" +set in0_min 1.020 +set in0_max 1.080 + +label in1 "+3.3V" +set in1_min 3.3 * 0.95 +set in1_max 3.3 * 1.05 +compute in1 1.635*@,@/1.635 + +label in2 "+12V" +set in2_min 12.0 * 0.95 +set in2_max 12.0 * 1.05 +compute in2 6.0*@,@/6.0 + +label in3 "+5V" +set in3_min 5.0 * 0.95 +set in3_max 5.0 * 1.05 +compute in3 2.5*@,@/2.5 + +label in4 "Vaxg IGD" +set in4_min 0.800 +set in4_max 1.000 + +label in5 "CPU Vcore" +set in5_min 0.750 +set in5_max 1.150 + +label in6 "Dram Voltage" +set in6_min 1.450 +set in6_max 1.550 + +label in7 "3.3 VSB" +set in7_min 3.3 * 0.95 +set in7_max 3.3 * 1.05 + +label in8 "Vbat" + +# Other sensor readings +label intrusion0 "Chassis Open" +#set intrusion0_alarm 0 + + +############################################## +chip "acpitz-virtual-0" + +ignore temp1 +#label temp1 "ACPI Thermal Zone 0 Temp1" # Shows always 27.8 + +ignore temp2 +#label temp2 "ACPI Thermal Zone 0 Temp2" # Shows always 29.8 + diff --git a/configs/Gigabyte/C1037UN-EU.conf b/configs/Gigabyte/C1037UN-EU.conf new file mode 100644 index 0000000..61cd4d3 --- /dev/null +++ b/configs/Gigabyte/C1037UN-EU.conf @@ -0,0 +1,50 @@ +# Motherboard Gigabyte C1037UN-EU see $(dmidecode|grep -s baseboard-product-name) +# driver: coretemp +# driver: it87 +# IT8728F: 0…3,06V corresponds 0…255, 1 bit = 12 mV +chip "it8728-isa-*" + label in0 "Vcore" + set in0_min 0.500 + set in0_max 0.992 + compute in0 1.0*@,@/1.0 + + ignore in1 # in1 is permanantly 2232 + + label in2 "+12V" + compute in2 6.0*@,@/6.0 + set in2_min 12 / 1.05 + set in2_max 12 * 1.05 + + label in3 "+5V" + set in3_min 5 / 1.05 + set in3_max 5 * 1.05 + compute in3 2.5*@,@/2.5 + + ignore in4 # in4 is permanantly 2232 + + label in5 "CPU VTT" + + label in8 "Battery" + + label in6 "V DRAM" + set in6_min 0.9 + set in6_max 1.56 + +# label in7 3VBattery + set in7_min 2.8 + set in7_max 3.8 + + label temp1 "System temperature" + set temp1_min 1.000 + + label temp3 "CPU" + set temp3_min 1.000 + + label fan1 "CPU fan" + + label fan2 "Sys fan" + + # Those are not valid, not connected + ignore fan3 + ignore intrusion0 + ignore temp2 diff --git a/configs/Gigabyte/EX38-DS4.conf b/configs/Gigabyte/EX38-DS4.conf new file mode 100644 index 0000000..f2e29ac --- /dev/null +++ b/configs/Gigabyte/EX38-DS4.conf @@ -0,0 +1,47 @@ +# Configuration file contributed by Marc Muehlfeld. + + +chip "it8718-*" + + # Voltages + label in0 "CPU Vcore" + label in1 "DDR" + label in2 "+3.3V" + label in3 "+5V" + ignore in4 + ignore in5 + ignore in6 + label in7 "+12V" + label in8 "VBat" + + compute in3 @ * (6.8/10+1), @ / (6.8/10+1) + compute in7 @ * 3.963, @ / 3.963 + + set in0_min 1.120 * 0.95 + set in0_max 1.120 * 1.05 + set in1_min 1.89 * 0.95 + set in1_max 1.89 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in7_min 12 * 0.95 + set in7_max 12 * 1.05 + + + # Temperatures + label temp1 "CPU temp" + label temp2 "System temp" + ignore temp3 + + set temp1_min 10 + set temp1_max 65 + set temp2_min 10 + set temp2_max 55 + + + # Fans + label fan1 "CPU fan" + label fan2 "Chassis fan" + label fan3 "Sys fan 2" + label fan4 "Sys fan 1" diff --git a/configs/Gigabyte/G33-DS3R.conf b/configs/Gigabyte/G33-DS3R.conf new file mode 100644 index 0000000..fc1c13e --- /dev/null +++ b/configs/Gigabyte/G33-DS3R.conf @@ -0,0 +1,63 @@ +# Configuration file contributed by Eduardo Diaz Rodriguez, based on earlier +# work by Jean Delvare. This is basically the same as for the 965P DS3, except +# that the G33 DS3R has a 3rd fan header. + + +# lm_sensors configuration file for the Gigabyte G33 DS3R motherboard + +chip "it8718-*" + +### Voltages + + label in0 "Vcore" + label in1 "Vram" # "DDR18V" in BIOS + label in2 "+3.3V" + label in3 "+5V" # Not in BIOS + ignore in4 + ignore in5 + ignore in6 + label in7 "+12V" + label in8 "Vbat" # Not in BIOS + + # Vcore, Vram, +3.3V and Vbat are connected directly, so no compute + # line is needed for these. For +5V the chip is configured to use + # internal scaling. For +12V the default resistors seem to have been + # used. + compute in3 @ * (6.8/10+1), @ / (6.8/10+1) + compute in7 @ * ( 30/10+1), @ / ( 30/10+1) + + # The BIOS won't set any limit for voltages. + + set in0_min vid * 0.95 + set in0_max vid * 1.05 + set in1_min 1.8 * 0.95 + set in1_max 1.8 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in7_min 12 * 0.95 + set in7_max 12 * 1.05 + +### Temperatures + + label temp1 "NBr Temp" + label temp2 "CPU Temp" + ignore temp3 + + set sensor3 0 + + set temp1_low 10 + set temp1_over 50 + set temp2_low 10 + set temp2_over 60 + +### Fans + + label fan1 "CPU Fan" + label fan2 "Case Fan" + + # Adjust for your own fans + set fan1_min 1000 + set fan2_min 4000 + diff --git a/configs/Gigabyte/GA-770TA-UD3.conf b/configs/Gigabyte/GA-770TA-UD3.conf new file mode 100644 index 0000000..42781a3 --- /dev/null +++ b/configs/Gigabyte/GA-770TA-UD3.conf @@ -0,0 +1,68 @@ +# Configuration file for the Gigabyte GA-770TA-UD3. +# Submitted by Ancoron Luciferis + + +# libsensors3 configuration file for the Gigabyte GA-770TA-UD3 + +chip "it8720-isa-*" +### Voltages + + # in5 is mysterious. + + label in0 "Vcore" + label in1 "Vdram" # "DDR3" in BIOS + label in2 "+3.3V" + label in3 "+5V" # Not in BIOS + label in4 "+12V" + ignore in5 + ignore in6 + label in7 "5VSB" # Not in BIOS + label in8 "Vbat" # Not in BIOS + ignore cpu0_vid + + # Vcore, Vdram, +3.3V and Vbat are connected directly, so no compute + # line is needed for these. +5V and 5VSB are internal so we use the + # standard scaling factor. Scaling for +12V is apparently not standard, + # factor 3.963 is guessed from BIOS and EasyTune values (3.943 was + # another candidate.) + compute in3 @ * (6.8/10+1), @ / (6.8/10+1) + compute in4 @ * 3.963, @ / 3.963 + compute in7 @ * (6.8/10+1), @ / (6.8/10+1) + + # The BIOS won't set any limit for voltages. + + set in0_min 0.825 * 0.95 + set in0_max 1.425 * 1.05 + set in1_min 1.5 * 0.95 + set in1_max 1.5 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 + +### Temperatures + + # The BIOS only shows 2 temperature values: + # - temp1: the system temprature + # - temp2: the CPU temperature + + label temp1 "SYS Temp" + label temp2 "CPU Casing Temp" + ignore temp3 + +### Fans + + label fan1 "CPU Fan" + ignore fan2 + ignore fan3 + # ignore fan4 # doesn't exist on GA-770TA-UD3 + ignore fan5 + + # Adjust for your own fans + set fan1_min 1000 + # set fan3_min 3000 + diff --git a/configs/Gigabyte/GA-790XTA-UD4.conf b/configs/Gigabyte/GA-790XTA-UD4.conf new file mode 100644 index 0000000..2c55e69 --- /dev/null +++ b/configs/Gigabyte/GA-790XTA-UD4.conf @@ -0,0 +1,76 @@ +# Configuration file for the Gigabyte GA-790XTA-UD4. +# Submitted by Ancoron Luciferis + + +# libsensors3 configuration file for the Gigabyte GA-790XTA-UD4 + +chip "it8720-isa-*" +### Voltages + + # in5 is mysterious. + + label in0 "Vcore" + label in1 "Vdram" # "DDR3" in BIOS + label in2 "+3.3V" + label in3 "+5V" # Not in BIOS + label in4 "+12V" + ignore in5 + ignore in6 + label in7 "5VSB" # Not in BIOS + label in8 "Vbat" # Not in BIOS + ignore cpu0_vid + + # Vcore, Vdram, +3.3V and Vbat are connected directly, so no compute + # line is needed for these. +5V and 5VSB are internal so we use the + # standard scaling factor. Scaling for +12V is apparently not standard, + # factor 3.963 is guessed from BIOS and EasyTune values (3.943 was + # another candidate.) + compute in3 @ * (6.8/10+1), @ / (6.8/10+1) + compute in4 @ * 3.963, @ / 3.963 + compute in7 @ * (6.8/10+1), @ / (6.8/10+1) + + # The BIOS won't set any limit for voltages. + + set in0_min 0.825 * 0.95 + set in0_max 1.425 * 1.05 + set in1_min 1.5 * 0.95 + set in1_max 1.5 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 + +### Temperatures + + # The BIOS only shows 2 temperature values, so temp1 and temp3 + # might not be actually both used, and I don't know which one + # is reported by the BIOS as the system temperature. + + label temp1 "SYS Temp" + set temp1_min 0 + set temp1_max 50 # Tropical ambient max plus a bit + + label temp2 "CPU Casing Temp" + set temp2_min 0 + set temp2_max 65 # BIOS "CPU Warning Temperature" - 5 + + label temp3 "NB Temp" + set temp3_min 0 + set temp3_max 55 # BIOS "CPU Warning Temperature" - 15 + +### Fans + + label fan1 "CPU Fan" + ignore fan2 + label fan3 "SYS Fan 2" + # ignore fan4 # doesn't exist on GA-790XTA-UD4 + ignore fan5 + + # Adjust for your own fans + set fan1_min 300 + set fan3_min 300 + diff --git a/configs/Gigabyte/GA-870A-UD3.conf b/configs/Gigabyte/GA-870A-UD3.conf new file mode 100644 index 0000000..9cb8d5a --- /dev/null +++ b/configs/Gigabyte/GA-870A-UD3.conf @@ -0,0 +1,91 @@ +# Configuration file for the Gigabyte GA-870A-UD3, +# contributed by Gary Myers and Zeke Fast. + +# libsensors3 configuration file for the Gigabyte GA-870A-UD3 +# 2011-06-16 Gary Myers +# Updates welcome. + +# CPU sensor + +chip "k10temp-*" + + label temp1 "CPU Temp (K10)" # Set for gnome-sensors-applet. + # See second CPU temp below. + +# Motherboard sensors + +chip "it8720-isa-*" + +### Voltages + + label in0 "Vcore" + label in1 "DDR3 1.5V" # as labelled in the BIOS. + label in2 "+3.3V" + label in3 "+5V" # Not shown in BIOS. + label in4 "+12V" + ignore in5 # Ambiguous - ignoring. + ignore in6 # Ambiguous - ignoring. + label in7 "5VSB" # Not shown in BIOS. + label in8 "Vbat" # Not shown in BIOS. + ignore cpu0_vid + + # "Vcore", "DDR3 1.5V", "+3.3V" and "Vbat" are connected directly, so no compute + # line is needed for these. +5V and 5VSB are internal so we use the + # standard scaling factor. Scaling for +12V is apparently not standard, + # factor 3.963 is guessed from BIOS and EasyTune values (3.943 was + # another candidate.) + compute in3 @ * (6.8/10+1), @ / (6.8/10+1) + compute in4 @ * 3.963, @ / 3.963 + compute in7 @ * (6.8/10+1), @ / (6.8/10+1) + + # The BIOS will not set any limit for voltages. + + set in0_min 0.825 * 0.95 + set in0_max 1.425 * 1.05 + set in1_min 1.5 * 0.95 + set in1_max 1.5 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 + +### Temperatures + + label temp1 "System Temp" + # This sensor appears to be around or inside the ITE8720F chip. + # The temperature drops if the chip and board area are cooled with + # freezer spray. This sensor may be over-reading! + # Adjustment applied to match internal case thermal sensor from my Antec P160. + compute temp1 (@ -20), (@ + 20) + set temp1_min 0 + set temp1_max 50 # Tropical ambient max plus a bit + + label temp2 "CPU Temp" + # This sensor can show 2 degrees difference to the K10 sensor. + # The end user can choose which one they prefer. + set temp2_min 0 + set temp2_max 70 # Set to match your BIOS "CPU Warning Temperature" + + ignore temp3 # No idea what this sensor is for. It always shows + # +78 deg C regardless of BIOS settings. + +### Fans + + # Label based on motherboard connectors. + label fan1 "CPU Fan" # M/B label: CPU_FAN (4-pin - near ATX 12V) + label fan5 "Power Fan" # M/B label: PWR_FAN (3-pin - near ATX) + label fan2 "System Fan 1" # M/B label: SYS_FAN1 (4-pin - near F_PANEL) + label fan3 "System Fan 2" # M/B label: SYS_FAN2 (3-pin - near SATA3_4) + + # Minimum fan speeds. + # Comment/un-comment fan headers you are using if you want alarms. + set fan1_min 300 # CPU Fan + set fan5_min 300 # Power Fan + #set fan2_min 300 # System Fan 1 + set fan3_min 300 # System Fan 2 + + diff --git a/configs/Gigabyte/GA-870A-USB3.conf b/configs/Gigabyte/GA-870A-USB3.conf new file mode 100644 index 0000000..39fcbdd --- /dev/null +++ b/configs/Gigabyte/GA-870A-USB3.conf @@ -0,0 +1,90 @@ +# Configuration file for the Gigabyte GA-870A-USB3, +# contributed by Gary Myers and Zeke Fast. + + +# libsensors3 configuration file for the Gigabyte GA-870A-USB3 +# 2011-06-16 Gary Myers +# Updates welcome. + +# CPU sensor + +chip "k10temp-*" + + label temp1 "CPU Temp (K10)" # Set for gnome-sensors-applet. + # See second CPU temp below. + +# Motherboard sensors + +chip "it8720-isa-*" + +### Voltages + + label in0 "Vcore" + label in1 "DDR3 1.5V" # as labelled in the BIOS. + label in2 "+3.3V" + label in3 "+5V" # Not shown in BIOS. + label in4 "+12V" + ignore in5 # Ambiguous - ignoring. + ignore in6 # Ambiguous - ignoring. + label in7 "5VSB" # Not shown in BIOS. + label in8 "Vbat" # Not shown in BIOS. + ignore cpu0_vid + + # "Vcore", "DDR3 1.5V", "+3.3V" and "Vbat" are connected directly, so no compute + # line is needed for these. +5V and 5VSB are internal so we use the + # standard scaling factor. Scaling for +12V is apparently not standard, + # factor 3.963 is guessed from BIOS and EasyTune values (3.943 was + # another candidate.) + compute in3 @ * (6.8/10+1), @ / (6.8/10+1) + compute in4 @ * 3.963, @ / 3.963 + compute in7 @ * (6.8/10+1), @ / (6.8/10+1) + + # The BIOS will not set any limit for voltages. + + set in0_min 0.825 * 0.95 + set in0_max 1.425 * 1.05 + set in1_min 1.5 * 0.95 + set in1_max 1.5 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 + +### Temperatures + + label temp1 "System Temp" + # This sensor appears to be around or inside the ITE8720F chip. + # The temperature drops if the chip and board area are cooled with + # freezer spray. This sensor may be over-reading! + # Adjustment applied to match internal case thermal sensor from my Antec P160. + compute temp1 (@ -20), (@ + 20) + set temp1_min 0 + set temp1_max 50 # Tropical ambient max plus a bit + + label temp2 "CPU Temp" + # This sensor can show 2 degrees difference to the K10 sensor. + # The end user can choose which one they prefer. + set temp2_min 0 + set temp2_max 70 # Set to match your BIOS "CPU Warning Temperature" + + ignore temp3 # No idea what this sensor is for. It always shows + # +78 deg C regardless of BIOS settings. + +### Fans + + # Label based on motherboard connectors. + label fan1 "CPU Fan" # M/B label: CPU_FAN (4-pin - near ATX 12V) + label fan5 "Power Fan" # M/B label: PWR_FAN (3-pin - near ATX) + label fan2 "System Fan 1" # M/B label: SYS_FAN1 (4-pin - near F_PANEL) + label fan3 "System Fan 2" # M/B label: SYS_FAN2 (3-pin - near SATA3_4) + + # Minimum fan speeds. + # Comment/un-comment fan headers you are using if you want alarms. + set fan1_min 300 # CPU Fan + set fan5_min 300 # Power Fan + #set fan2_min 300 # System Fan 1 + set fan3_min 300 # System Fan 2 diff --git a/configs/Gigabyte/GA-945GCM-S2L.conf b/configs/Gigabyte/GA-945GCM-S2L.conf new file mode 100644 index 0000000..0bf344b --- /dev/null +++ b/configs/Gigabyte/GA-945GCM-S2L.conf @@ -0,0 +1,63 @@ +# Configuration file contributed by Ian Pangilinan. + + +### Sensors configuration for Gigabyte GA-945GCM-S2L motherboard +### 2014-02-21, ianp +### Thanks to Jean Delvare +### Comments are welcome. + + +chip "it8718-*" + +### Voltages + + label in0 "Vcore" + label in1 "Vram" # "DDR18V" in BIOS + label in2 "+3.3V" + ignore in3 # no +5V monitor, not used + label in4 "+12V" + ignore in5 # these inputs + ignore in6 # are not used + ignore in7 # by the board + + ### Scale +12V. + + compute in4 @*3.9633, @/3.9633 + + ### Set in0 according to CPU VID voltage range. + ### Set min and max values according to preference. + + set in0_min 0.850 + set in0_max 1.362 + set in1_min 1.8 * 0.95 + set in1_max 1.8 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + +### Temperatures + + ### Ignore temp1 and temp2 as those aren't used. + + ignore temp1 + ignore temp2 + label temp3 "CPU Temp" + + ### Set according to CPU. + + set temp3_min 10 + set temp3_max 60 + +### Fans + + ### Ignore fan3 as it isn't used. + + label fan1 "CPU Fan" + label fan2 "CHA Fan" + ignore fan3 + + ### Set according to preference. + + set fan1_min 900 + set fan2_min 0 diff --git a/configs/Gigabyte/GA-990FXA-UD3.conf b/configs/Gigabyte/GA-990FXA-UD3.conf new file mode 100644 index 0000000..eb48930 --- /dev/null +++ b/configs/Gigabyte/GA-990FXA-UD3.conf @@ -0,0 +1,70 @@ +# Configuration file contributed by Ki'Sak. + + +# libsensors3 configuration file for the GA-990FXA-UD3 Rev. 1.1 +# This is strongly based on the Gigabyte GA-790XTA-UD4 sensors3.conf + +chip "it8720-isa-*" + +### Voltages + + # in5 is mysterious. It is -12V in other uses of this chip, but unstable here + # -12V is in the ATX spec for ISA, which is used sparingly in modern hardware + + label in0 "Vcore" + label in1 "Vdram" # "DDR3" in BIOS + label in2 "+3.3V" + label in3 "+5V" # Not in BIOS + label in4 "+12V" + ignore in5 # -12V unused + ignore in6 + label in7 "5VSB" # Not in BIOS + label in8 "Vbat" # Not in BIOS + ignore cpu0_vid + +### Fan labels as found on the motherboard + + label fan1 "CPU_FAN" # controlled by temp3 + label fan2 "SYS_FAN1" # controlled by temp1 + label fan3 "SYS_FAN2" + label fan4 "PWR_FAN" # unregulated max speed + + # Vcore, Vdram, +3.3V and Vbat are connected directly, so no compute + # line is needed for these. +5V and 5VSB are internal so we use the + # standard scaling factor. Scaling for +12V is apparently not standard, + # factor 3.963 is guessed from BIOS and EasyTune values (3.943 was + # another candidate.) + # These values have not been rechecked from the GA-790XTA-UD4 + compute in3 @ * (6.8/10+1), @ / (6.8/10+1) + compute in4 @ * 3.963, @ / 3.963 + compute in7 @ * (6.8/10+1), @ / (6.8/10+1) + + # The BIOS won't set any limit for voltages. + + set in0_min 0.825 * 0.95 + set in0_max 1.425 * 1.05 + set in1_min 1.5 * 0.95 + set in1_max 1.5 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 + +### Temperatures + + label temp1 "VRM Temp" # This is unconfirmed, Possibly near NB, but the NB + set temp1_min 0 # operates at significantly higher temps than temp1 + set temp1_max 65 # Default max fan speed reference point + + label temp2 "SB Temp" # This sensor reacts to nearby heat from the GPU + set temp2_min 0 + set temp2_max 55 # Tropical ambient temperature plus a bit + + label temp3 "CPU Temp" # k10temp truncated to whole number +12C. k10temp + set temp3_min 0 # reports thermal margin, and reports -10C when idle + set temp3_max 65 # Bulldozer Published limit +3C + diff --git a/configs/Gigabyte/GA-AB350-GAMING.conf b/configs/Gigabyte/GA-AB350-GAMING.conf new file mode 100644 index 0000000..db6e728 --- /dev/null +++ b/configs/Gigabyte/GA-AB350-GAMING.conf @@ -0,0 +1,31 @@ +# The temp3 temperature offset depends on the CPU type and needs to be +# adjusted. Compare against the output of k10temp for the correct value. + +chip "it8686-isa-*" + + label fan1 "CPU_FAN" + label fan2 "SYS_FAN1" + label fan3 "SYS_FAN2" + label fan4 "SYS_FAN3_PUMP" + + label temp1 "System 1" + label temp2 "Chipset Temp" + + compute temp3 @+15,@+15 + label temp3 "CPU Temp" + + label temp4 "PCI-EX16 Temp" + label temp5 "VRM MOS Temp" + label temp6 "vSOC MOS Temp" + + label in0 "CPU Vcore" + label in6 "DRAM Channel A/B" + +# A configuration for the Super-IO chip it8792 can be taken from the configuration +# file for the board GA-AB350-GAMING3 but has not been checked for this board + +chip "it8792-isa-*" + ignore fan1 + ignore fan2 + ignore fan3 + diff --git a/configs/Gigabyte/GA-AB350-GAMING3.conf b/configs/Gigabyte/GA-AB350-GAMING3.conf new file mode 100644 index 0000000..1db6981 --- /dev/null +++ b/configs/Gigabyte/GA-AB350-GAMING3.conf @@ -0,0 +1,64 @@ +# The temp3 temperature offset depends on the CPU type and needs to be +# adjusted. Compare against the output of k10temp for the correct value. + +# The temp3 temperature offset depends on the CPU type and needs to be +# adjusted. Compare against the output of k10temp for the correct value. + +chip "it8686-isa-0a40" + label temp1 "System 1" + label temp2 "Chipset" + label temp3 "CPU Socket" + label temp4 "PCI-EX16" + label temp5 "VRM MOS" + label temp6 "vSOC MOS" + label in0 "CPU Vcore" + label in1 "+3.3v" + label in2 "+12v" + label in3 "+5v" + label in4 "CPU Vcore SOC" + label in5 "CPU Vddp" + label in6 "DRAM A/B" + label in7 "3VSB" + label in8 "Battery" + label fan1 "CPU_FAN" + label fan2 "SYS_FAN1" + label fan3 "SYS_FAN2" + label fan4 "SYS_FAN3_PUMP" + label fan5 "CPU_OPT" + + compute temp3 @+15,@+15 + compute in1 @*1.65,@*1.65 + compute in2 @*6,@*6 + compute in3 @*2.5,@*2.5 + + set in0_min 0.6 + set in0_max 1.45 + set in2_min 1.97 + set in2_max 2.05 + set in6_min 1.2 * 0.97 + set in6_max 1.2 * 1.2 + set in7_min 3.3 * 0.97 + set in7_max 3.3 * 1.05 + +chip "it8792-isa-0a60" + label temp1 "PCI-EX8" + label temp2 "Temp 2" + label temp3 "System 2" + label in0 "CPU Vcore" + label in1 "DDR VTT" + label in2 "Chipset Core" + label in3 "VIN3" + label in4 "CPU Vdd18" + label in5 "DDR Vpp" + label in6 "3VSB" + label in7 "Battery" + + set in0_min 0.6 + set in0_max 1.45 + set in7_min 3.3 * 0.97 + set in7_max 3.3 * 1.03 + + ignore fan1 + ignore fan2 + ignore fan3 + ignore in8 diff --git a/configs/Gigabyte/GA-AX370-GAMING5.conf b/configs/Gigabyte/GA-AX370-GAMING5.conf new file mode 100644 index 0000000..1de799a --- /dev/null +++ b/configs/Gigabyte/GA-AX370-GAMING5.conf @@ -0,0 +1,93 @@ +# Reported to work for both GA-AX370-GAMING5 and GA-AX370-Gaming K7. + +chip "it8792-isa-*" + label in0 "CPU Vcore" + label in1 "DDR Vtt A/B" + label in2 "Chipset Core" + label in4 "CPU Vdd18" + label in5 "DDR Vpp A/B" + + compute in5 @ * (208/125), @ / (208/125) + + set in0_min 0.35 + set in0_max 1.45 + set in1_min 1.1 / 2 + set in1_max 1.6 / 2 + set in2_min 1.05 * 0.95 + set in2_max 1.05 * 1.05 + set in4_min 1.8 * 0.97 + set in4_max 1.8 * 1.03 + set in5_min 2.5 * 0.95 + set in5_max 2.5 * 1.05 + set in7_min 3.3 * 0.97 + set in7_max 3.3 * 1.03 + + label temp1 "PCIe X8" + label temp2 "EC_temp 2" + label temp3 "System 2" + + label fan1 "SYS5 fan/pump" + label fan2 "SYS6 fan/pump" + label fan3 "SYS4 fan" + + set fan1_min 300 + set fan2_min 300 + set fan3_min 300 + + ignore in0 + ignore in3 + ignore in6 + ignore intrusion0 + +chip "it8686-isa-*" + label in0 "CPU Vcore" + label in1 "+3.3V" + label in2 "+12V" + label in3 "+5V" + label in4 "Vcore SOC" + label in5 "CPU Vddp" + label in6 "DRAM A/B" + + compute in1 @ * (33/20), @ / (33/20) + compute in2 @ * (120/20), @ / (120/20) + compute in3 @ * (50/20), @ / (50/20) + + set in0_min 0.35 + set in0_max 1.45 + set in1_min 3.3 * 0.97 + set in1_max 3.3 * 1.03 + set in2_min 12 * 0.97 + set in2_max 12 * 1.03 + set in3_min 5 * 0.97 + set in3_max 5 * 1.03 + set in4_min 0.9 + set in4_max 1.26 + set in5_min 0.9 * 0.95 + set in5_max 0.9 * 1.05 + set in6_min 1.1 + set in6_max 1.6 + + label temp1 "System 1" + label temp2 "Chipset" + label temp3 "CPU" + label temp4 "PCIe X16" + label temp5 "VRM MOS" + label temp6 "EC_temp 1" + + compute temp3 @ + 10, @ - 10 + + label fan1 "CPU fan" + label fan2 "SYS1 fan" + label fan3 "SYS2 fan" + label fan4 "SYS3 fan" + label fan5 "CPUOPT fan" + + set fan1_min 300 + set fan2_min 300 + set fan3_min 300 + set fan4_min 300 + set fan5_min 300 + + ignore in7 + ignore in8 + ignore intrusion0 diff --git a/configs/Gigabyte/GA-M720-US3.conf b/configs/Gigabyte/GA-M720-US3.conf new file mode 100644 index 0000000..953a4e2 --- /dev/null +++ b/configs/Gigabyte/GA-M720-US3.conf @@ -0,0 +1,38 @@ +# input routing and scaling based on schematic of a similar MA770T-UD3 board + +chip "it8720-*" + label in0 "Vcore" + + label in1 "VDDR" + + label in2 "+3.3V" + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + + # pin has probably ATX power good signal connected, + # but is not configured as such + ignore in3 + + label in4 "+12V" + compute in4 @ * (8.2 + 24.3) / 8.2, @ * 8.2 / (8.2 + 24.3) + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + + # probably CPU current sense + ignore in5 + + ignore in6 + + compute in7 @ * (6.8 / 10 + 1), @ / (6.8 / 10 + 1) + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 + + ignore cpu0_vid + + label fan1 "CPU FAN" + label fan2 "SYSTEM FAN 1" + label fan3 "SYSTEM FAN 2" + label fan4 "POWER FAN" + + label temp1 "System Temp" + label temp3 "CPU Temp" diff --git a/configs/Gigabyte/H170+D3.conf b/configs/Gigabyte/H170+D3.conf new file mode 100644 index 0000000..cff3121 --- /dev/null +++ b/configs/Gigabyte/H170+D3.conf @@ -0,0 +1,64 @@ +# Gigabyte H170+D3 Motherboard, see $(dmidecode -s baseboard-product-name) +# 2018, contributed by J. Schwender +# dmi: board_name: H170-PLUS D3 +# dmi: board_vendor: ASUSTeK COMPUTER INC. +# dmi: board_version: Rev X.0x +# dmi: bios_version: 0403 +# driver: nct6775 +# cpu: intel core i5, you may have to adjust voltage limits for other processors +# no chassis fan installed, you may adjust fan labels accordingly +# +chip "nct6793-isa-*" + ignore fan1 + label fan2 "CPU fan" # CPU_FAN + #label fan3 "Chassis1" + #label fan4 "Chassis2" + ignore fan3 + ignore fan4 + ignore fan5 + ignore fan6 + ignore intrusion0 + ignore intrusion1 + ignore temp1 #SYSTIN + ignore temp3 #AUXTIN + ignore temp4 #AUXTIN1 + ignore temp5 #AUXTIN2 + ignore temp6 #AUXTIN3 + ignore temp9 #PCH_CPU + ignore temp10 #PCH_CHIP_TEMP + label in0 "Vcore" + set in0_min 1 * 0.80 + set in0_max 1 * 1.35 + label in1 "+12V" + compute in1 @ * 12, @ / 12 + set in1_min 12 * 0.90 + set in1_max 12 * 1.10 + label in2 "AVCC" + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + label in3 "+3.3V" + set in3_min 3.3 * 0.90 + set in3_max 3.3 * 1.10 + label in4 "+5V" + compute in4 @ * 5, @ / 5 + set in4_min 5 * 0.90 + set in4_max 5 * 1.10 + label in7 "3VSB" + set in7_min 3.3 * 0.90 + set in7_max 3.3 * 1.10 + label in8 "Vbat" + set in8_min 3.3 * 0.90 + set in8_max 3.3 * 1.10 + ignore in5 + ignore in6 + ignore in9 + ignore in10 + ignore in11 + ignore in12 + ignore in13 + ignore in14 + +chip "acpitz-*" + label temp1 "Motherboard" + label temp2 "Unknown" + diff --git a/configs/Gigabyte/H55M-D2H.conf b/configs/Gigabyte/H55M-D2H.conf new file mode 100644 index 0000000..07fd4ad --- /dev/null +++ b/configs/Gigabyte/H55M-D2H.conf @@ -0,0 +1,36 @@ +# Machine: Device: desktop, Mobo: Gigabyte model: H55M-D2H BIOS: Award v: F4 date: 02/06/2012 +# dmi: H55M-D2H +# driver: coretemp +# driver: it87 +chip "it8720-isa-0290" + label in0 "Vcore" + set in0_min 0.5 # This depends on the Processor!!! + set in0_max 2.15 # This depends on the Processor!!! + + label in1 "RAM" + set in1_min 1.5*0.95 + set in1_max 1.5*1.15 + label in2 "3,3V" + set in2_min 3.3*0.95 + set in2_max 3.3*1.15 + + ignore in4 # no idea what that is + + compute in3 1.7*@,@/1.7 + set in3_min 5*0.95 + set in3_max 5*1.15 + + label in5 "+12V" + compute in5 3.89*@,@/3.89 + set in5_min 12*0.95 + set in5_max 12*1.05 + + ignore in6 # no idea what that might be + + label temp1 "System Temp" + label temp2 "unknown" + label temp3 "CPU Temp" + + label fan1 "CPU fan" + ignore fan2 # comment out if you have one conected + ignore intrusion0 # in out case there is nothing conneted diff --git a/configs/Gigabyte/H67MA-UD2H.conf b/configs/Gigabyte/H67MA-UD2H.conf new file mode 100644 index 0000000..25a92e7 --- /dev/null +++ b/configs/Gigabyte/H67MA-UD2H.conf @@ -0,0 +1,55 @@ +# Provided by Ivan Bulatovic, who says it might possibly work on other +# P65/H61/H67 Gigabyte boards too. + + +chip "it8728-*" + + label in0 "Vtt" + set in0_min 1.02 # I'm liberal with these, 2-3% tops + set in0_max 1.08 # after that, cpu gets very unstable + + ignore in1 +# label in1 "+3.3V" +# set in1_min 3.14 # Some boards including GA-H67MA-UD2H +# set in1_max 3.47 # don't have 3.3V voltage reading + + label in2 "+12V" + set in2_min 11.40 # according to ATX 12V PSU design guide + set in2_max 12.60 # + + ignore in3 # reports 3VSB + + ignore in4 # really don't know what's this one for + + label in5 "Vcore" + set in5_min 0.65 + set in5_max 1.50 # heavy o/c + + label in6 "Vdram" + set in6_min 1.45 # adjust these, 1.35 for LVDDR3 + set in6_max 1.55 # 1.5V is recommended, 1.65 tops + + label in7 "3VSB" + set in7_min 3.14 + set in7_max 3.47 + + label in8 "Vbat" + + label fan1 "CPU fan" + set fan1_min 700 + + label fan2 "System fan" + set fan2_min 0 + + label temp1 "PCH temp" + set temp1_min 10 + set temp1_max 60 # seen those rising to 55C + + label temp2 "CPU temp" + set temp2_min 10 + set temp2_max 85 + + ignore temp3 + + compute in1 1.649*@,@/1.649 # multipliers provided by + compute in2 4.090*@,@/4.090 # Martin Malik author of hwinfo diff --git a/configs/Gigabyte/K8N51GMF-9.conf b/configs/Gigabyte/K8N51GMF-9.conf new file mode 100644 index 0000000..1bd28cf --- /dev/null +++ b/configs/Gigabyte/K8N51GMF-9.conf @@ -0,0 +1,73 @@ +# Preliminary configuration file contributed by Denzel Holmes. +# Improvements welcome. + +# lm_sensors configuration for Gigabyte GA-K8N51GMF-9 (C51-MCP51) Socket 7 motherboard + +chip "k8temp-*" + +## cpu core temp ## + label temp1_input "CPU Core1 Temp" + label temp3_input "CPU Core2 Temp" + +chip "w83627ehf-*" + +## Voltage ## + + label in0 "VCore" # CPU Core Voltage + label in1 "VPCIEx" # PCI Express Voltage + label in2 "AVCC" + label in3 "3VCC" + label in6 "+3.3V" # +3.3V, or so i think + label in7 "3VSB" + label in8 "VBat" + label in9 "+12V" # +12V, or so i think + +## +12V is in9 and +5V is in6 ## + compute in9 @*(1+(56/10)), @/(1+(56/10)) + compute in6 @*1.78, @/1.78 + + set in9_min 12.0*0.7916 + set in9_max 12.0*1.1 + set in6_min 3.3*0.9 + set in6_max 3.3*1.10 + + set in0_min 0.9 + set in0_max 1.7 + set in1_min 1.3 + set in1_max 2.0 + set in2_min 3.3*0.9 + set in2_max 3.3*1.1 + set in3_min 3.3*0.9 + set in3_max 3.3*1.1 + set in4_min 1.4 + set in4_max 1.6 + set in5_min 1.86 + set in5_max 1.9 + set in7_min 3.3*0.9 + set in7_max 3.3*1.1 + set in8_min 3.0*0.9 + set in8_max 3.3*1.1 + + ## Temperatures ## + + label temp1 "Sys Temp" + label temp2 "CPU Temp" + label temp3 "Aux Temp" + + set temp1_max 55 + set temp1_max_hyst 48 + set temp2_max 55 + set temp2_max_hyst 47 + set temp3_max 55 + set temp3_max_hyst 50 + +## Fans ## + + label fan1 "Sys Fan" + label fan2 "CPU Fan" + + set fan2_min 800 + + ignore fan3 + ignore fan4 + ignore fan5 diff --git a/configs/Gigabyte/M61P-S3.conf b/configs/Gigabyte/M61P-S3.conf new file mode 100644 index 0000000..a8566c3 --- /dev/null +++ b/configs/Gigabyte/M61P-S3.conf @@ -0,0 +1,63 @@ +# Configuration contributed by Artem S. Tashkinov. + + +# lm_sensors configuration for Gigabyte M61P-S3 AM2+ motherboard + +chip "it8716-*" + +# Voltages + + label in0 "VCore" # CPU Core Voltage + label in1 "VDDR" # DDR2 1.8V + label in2 "+3.3V" # VCC3 + label in3 "+5V" # VCC + label in4 "+12V" + label in5 "-12V" # Not in the BIOS, maybe not really -12V + label in6 "-5V" # Not in the BIOS, maybe not really -5V + label in7 "5VSB" # VCCH + label in8 "VBat" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((30/10)+1)*@ , @/((30/10)+1) + compute in5 -(30/10+1)*@, -@/(30/10+1) + compute in6 (1+120/56)*@ - 4.096*120/56 , (@ + 4.096*120/56)/(1+120/56) + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# Not setting in0 min/max, because different AMD CPUs have +# different voltages, besides with C'n'Q enabled this voltage +# can fluctuate a lot +# set in0_min vid * 0.95 +# set in0_max vid * 1.05 + set in1_min 1.8 * 0.95 + set in1_max 1.8 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + set in5_max -12 * 0.95 + set in5_min -12 * 1.05 + set in6_max -5 * 0.95 + set in6_min -5 * 1.05 + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 +# The chip does not support in8 min/max + +# Temperatures + + label temp1 "M/B Temp" + label temp2 "CPU Temp" + label temp3 "M/B Temp" + + set temp2_max 60 + +# Fans + + label fan1 "CPU Fan" + label fan2 "Case Fan" + ignore fan3 # This motherboard doesn't have the second system fan + +# My fans can stop if the temperature is OK, adjust for your situation +# set fan1_min 2000 +# set fan2_min 2000 diff --git a/configs/Gigabyte/MA770-DS3.conf b/configs/Gigabyte/MA770-DS3.conf new file mode 100644 index 0000000..cd97cd6 --- /dev/null +++ b/configs/Gigabyte/MA770-DS3.conf @@ -0,0 +1,126 @@ +# Configuration file contributed by Charles A. from India. + + +# libsensors configuration file for Gigabyte GA-MA770-DS3 motherboard + +chip "it8718-*" + + # lmsensors' values were compared with values from monitoring + # software running on the same computer under Windows XP SP2 + # abbreviated in comments: + # ET6: Gigabyte's EasyTune 6 + # Everest: Lavalys's Everest Ultimate 4.6.0 (trial version) + # OverDrive: AMD's OverDrive 2.1.5 + + # Labels are copied from BIOS setup screens when value shown + + # Voltages + + label in0 "Vcore" + # BIOS: 1.264V, ET6: 1.260, Everest: 1.26, OverDrive: 1.26 + # No scaling so no compute + # Values seen using powernow-k8 in "on demand" mode: + # 1.06, 1.07, 1.25, 1.26, 1.28 + # Nominal values written to /var/log/kern.log by powernow-k8 + # as vid numbers in hex. For AMD K8, these translate to V by + # 1.550 - 0.025 * vid. Gave 1.000, 1.175 and 1.200 V + set in0_min 1.000 * 0.95 # 95% of nominal min + set in0_max 1.200 * 1.05 # 105% of nominal max + + label in1 "DDR2 1.8V" + # No scaling so no compute + set in1_min 1.8 * 0.95 # 95% of nominal + set in1_max 1.8 * 1.05 # 105% of nominal + + label in2 "+3.3V" + # No scaling so no compute + set in2_min 3.3 * 0.95 # 95% of nominal + set in2_max 3.3 * 1.05 # 105% of nominal + + label in3 "Vcc" + # BIOS: -, ET6: -, Everest: -, OverDrive: - + # dmesg reports as VCC + # Assume standard Winbond scaling resistors + compute in3 @ * ((6.8/10)+1), @ / ((6.8/10)+1) + set in3_min 5 * 0.95 # 95% of nominal + set in3_max 5 * 1.05 # 105% of nominal + + label in4 "5VSB?" # Guess + # BIOS: -, ET6: -, Everest: -, OverDrive (VIN4): 12.74 + # Values seen: 3.15, 3.17, 3.19 + # Assume standard Winbond scaling resistors + compute in4 @ * ((6.8/10)+1), @ / ((6.8/10)+1) + set in4_min 5 * 0.95 # 95% of nominal + set in4_max 5 * 1.05 # 105% of nominal + + label in5 "+12V" + # BIOS: 12.619V, ET6: 12.610, Everest: -, OverDrive: - + # Assume standard Winbond scaling resistors + compute in5 @ * ((30/10)+1), @ / ((30/10)+1) + set in5_min 12 * 0.95 # 95% of nominal + set in5_max 12 * 1.05 # 105% of nominal + + ignore in6 # Seen always 4.08, too big (max 4.096) to signify + ignore in7 # Seen always 0.03, too small to be significant + + label in8 "Vbat" + # BIOS: -, ET6: -, Everest: 3.17, OverDrive: - + # Connected directly so no compute + # in8_min and _max not supported by chip + + ignore cpu0_vid # Not dynamic under lm-sensors 3.0.0 + + # Temperatures + + label temp1 "Current System Temperature" + # BIOS: 30, ET6: 30, Everest: 33, OverDrive: - + compute temp1 @ -5, @ +5 # Correct bad sensor on Charles' mobo + set temp1_min 0 + set temp1_max 45 # Tropical ambient max plus a bit + + label temp2 "Current CPU Casing Temperature" + # BIOS: 29, ET6: 28, Everest: 32, OverDrive (both cores): 33 + set temp2_min 0 + # Max is lowest available BIOS "CPU Warning Temperature" - 5 + set temp2_max 55 + + ignore temp3 + # Values seen: 77-79, rising from cold start. + # Sheilding Northbridge from CPU cooling draft did not change + + # Fans + # The labels chosen are the ones printed on the motherboard + label fan1 "CPU_FAN" + set fan1_min 0 # fancontrol may stop fan + label fan2 "SYS_FAN1" + label fan3 "SYS_FAN2" + ignore fan4 # "NB_FAN" does not set an RPM signal + label fan5 "PWR_FAN" + + # Beep + # lm-sensors 3.0.0 does not support on this chip + # Was enabled by default + +chip "k8temp-*" + + # Temperatures + # For CPU revisions F and G, according to AMD's "Revision + # Guide for AMD NPT Family 0Fh Processors", "The internal + # thermal sensor ... is inaccurate". This may be the reason + # for many reports of k8temp giving absurdly low CPU core + # temperatures and for there being no generally accepted + # computation to derive actual temperature from the raw data. + # The workaround is to ignore core temperatures and use the + # CPU case temperature as was done before core temperatures + # were available. On this motherboard the CPU case temperature + # is reported by the it8718 chip's temp2 (see above). + + # For CPU revisions other than F and G, the proper use of + # k8temp temperatures may be to compute an average for each + # core rather than to report two temperatures for each core. + # For a sample computation see mingus' posting at + # http://forums.opensuse.org/archives/sls-archives/archives-suse-linux/archives-hardware-support/381563-lm-sensors-2.html#post1793098 + + # If you don't trust the readings, you might as well not load + # the k8temp driver (which, in practice, means blacklisting it, + # as this driver auto-loads on most systems. diff --git a/configs/Gigabyte/MA785GM-US2H.conf b/configs/Gigabyte/MA785GM-US2H.conf new file mode 100644 index 0000000..15a6789 --- /dev/null +++ b/configs/Gigabyte/MA785GM-US2H.conf @@ -0,0 +1,81 @@ +# Contributed by Glen Journeay and David Santamaría Rogado. + + +# lm_sensors 3 configuration file for the Gigabyte MA785GM-US2H motherboard +# 2010-8-12 G. Journeay +# 2011-04-17, David Santamaría Rogado +# Written for board revision 1.0, may or may not be suitable for other +# revisions. +# Comments welcome! + +chip "it8718-*" + +### Voltages + + # in7 is mysterious, it lives in the range 2.19 to 2.94 V, change with + # CPU frequency (if you take the highest clock speed of all the cores + # you can guess it's value). No idea what it can be. + + label in0 "Vcore" + label in1 "Vram" # "DDR2" in BIOS + label in2 "+3.3V" + label in3 "+5V" # Not in BIOS + label in4 "+12V" + ignore in5 # Always fixed at 4.08 V + ignore in6 # Always fixed at 4.02 V + ignore in7 # Commented above + label in8 "Vbat" # Not in BIOS + + # Vcore, Vram, +3.3V and Vbat are connected directly, so no compute + # line is needed for these. For +5V the chip is configured to use + # internal scaling. For +12V, my guess is that the BIOS uses 4 as + # the scaling factor. Not sure if it matches the physical reality. + # BIOS values varies between 12.048 and 12.112 V, lm-sensors in4 + # between 3.040 and 3.056 V, is exactly a x4 scale +0.112 offset. + + compute in3 @ * (6.8/10+1), @ / (6.8/10+1) + compute in4 @ * ((30/10)+1), @ / ((30/10)+1) + + # The BIOS won't set any limit for voltages. + # You should set Vcore and Vram to match you setup, mine is: + # - CPU: AMD Athlon II X2 250 (VCore 0.85-1.425) + # - Mem: KHX8500D2/2G (Vram 1.8-2) + + set in0_min 0.850 * 0.95 + set in0_max 1.425 * 1.05 + set in1_min 1.8 * 0.95 + set in1_max 2.0 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + +### Temperatures + + # The BIOS only shows 2 temperature values, corresponding to Sys and CPU, + # temp3 is usually similar to Sys temp but under heavy load it raises more. + + label temp1 "Sys Temp" + label temp2 "CPU Temp" + label temp3 "NBr Temp" # Guessed + + set temp1_min 10 + set temp1_max 50 + set temp2_min 10 + set temp2_max 60 + set temp3_min 10 + set temp3_max 50 + +### Fans + + label fan1 "CPU Fan" + label fan2 "Case Fan" + ignore fan3 + label fan4 "NBr Fan" + + # Adjust for your own fans + set fan1_min 1000 + set fan2_min 1000 + set fan4_min 1000 diff --git a/configs/Gigabyte/P55-US3L.conf b/configs/Gigabyte/P55-US3L.conf new file mode 100644 index 0000000..c73f157 --- /dev/null +++ b/configs/Gigabyte/P55-US3L.conf @@ -0,0 +1,73 @@ +# Contributed by Yuri Nefedov (Russia.) + + +# Gigabyte P55-US3L (rev 1:0, BIOS F1) +# + +chip "it8720-*" + +# Voltages + + label in0 "VCore1" # ok + label in1 "DDR15V" # ok + label in2 "+3.3V" # ok + label in3 "+5V" # ok +# ignore in4 # ?? correlates with load_av/temp3/fan1 [0;2.4] + label in5 "+12V" # ok +# ignore in6 # ?? correlates with load_av/temp3/fan1 [0;0.3] + label in7 "5VSB" # internal + label in8 "VBat" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in5 ((28/10)+1)*@ , @/((28/10)+1) + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# VID Voltage Range for core-i5 750 +# (http://ark.intel.com/Product.aspx?id=42915) + set in0_min 0.65 + set in0_max 1.40 + + set in1_min 1.4 # depends from BIOS settings + set in1_max 1.6 # correct if it is wrong + + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + + set in5_min 12 * 0.95 + set in5_max 12 * 1.05 + + set in7_min 5 * 0.90 + set in7_max 5 * 1.10 + +# set in4_max 4.08 +# set in6_max 4.08 +# The chip does not support in8 min/max + +# Temperatures +# +# see man sensors.conf for available thermal sensor types. +# +# set temp1_type 4 + + label temp1 "PCH Temp" # PCH is the south bridge + ignore temp2 + label temp3 "CPU Temp" + + set temp1_max 50 + set temp3_max 70 + +# Fans + +# The motherboard has connectors: cpu_fan, sys_fan1/2, pwr_fan +# case fan == sys_fan1 + + label fan1 "CPU Fan" + ignore fan2 + ignore fan3 + label fan4 "Case Fan" + + set fan1_min 1000 + set fan4_min 0 diff --git a/configs/Gigabyte/X58-UD3R.conf b/configs/Gigabyte/X58-UD3R.conf new file mode 100644 index 0000000..59a7e75 --- /dev/null +++ b/configs/Gigabyte/X58-UD3R.conf @@ -0,0 +1,38 @@ +# Partial configuration file for the Gigabyte X58-UD3R, reported to work fine +# on the X58A-UD3R as well. + +# libsensors3 configuration file for the Gigabyte X58-UD3R + +chip "it8720-*" + +# Voltages + + label in0 "VCore" + label in1 "DDR15V" + label in2 "+3.3V" + label in3 "+5V" + ignore in4 + label in5 "+12V" + ignore in6 + label in7 "5VSB" # internal + label in8 "Vbat" + + # Exact scaling for +12V is unknown + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in5 3.964*@ , @/3.964 + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + + set in0_min 0.65 + set in0_max 1.40 + set in1_min 1.4 # depends from BIOS settings + set in1_max 1.6 # correct if it is wrong + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in5_min 12 * 0.95 + set in5_max 12 * 1.05 + set in7_min 5 * 0.90 + set in7_max 5 * 1.10 + + ignore cpu0_vid diff --git a/configs/Gigabyte/Z38MX-UD2H-B3.conf b/configs/Gigabyte/Z38MX-UD2H-B3.conf new file mode 100644 index 0000000..53a2376 --- /dev/null +++ b/configs/Gigabyte/Z38MX-UD2H-B3.conf @@ -0,0 +1,93 @@ +# Configuration file contributed by Martin Herrman. + + +# LM-Sensors config file for Gigabyte GA-Z38MX-UD2H-B3 mainboard with +# an Intel i5 Sandy Bridge quad core CPU installed. + +# Tested with kernel 3.10.x and lm-sensors 3.3.x on Gentoo Linux. + +# Created by Martin Herrman with help from Jean Delvare +# from the lm-sensors mailinglist. + +# Questions, comments or additions? Please share on the lm-sensors mailinglist. +# More info at http://www.lm-sensors.org/wiki/FeedbackAndSupport + +# Hint: Use sensors -u to list all variables. +http://lists.lm-sensors.org/pipermail/lm-sensors/2014-January/040952.html +chip "coretemp-*" +# chip coretemp measures cpu temperatures from i5 CPU temperature sensor +# _max, _crit and _crit_alarm are read from the cpu itself +# when temp is at _max, all cooling options must be at full throttle +# when temp is at _crit, cpu starts to fail +# _crit_alarm is automatically set by hardware when _input is at or above _crit +# libsensors currently doesn't support the trigger of a notification system +label temp1 "CPU Package temp" +label temp2 "Core 0" +label temp3 "Core 1" +label temp4 "Core 2" +label temp5 "Core 3" + +# IT8728F is on the mainboard and provides voltages and cpu/case fan speed +chip "it8728-*" + +# scythe kozuti min = 800 +# output of sensors will show ALARM (_alarm is set to 1) when actual fan +# speed (_input) is below set minimum (_min). If _beep is set to 1, and +# the motherboard is wired between the temperature sehttp://lists.lm-sensors.org/pipermail/lm-sensors/2014-January/040952.htmlnsor and the +# PC speaker, the PC speaker will start beeping. +# Unfortunately Gigabyte GA-Z68MX-UD2H-B3 is not properly wired. +label fan1 "CPU fan" +set fan1_min 800 +set fan1_beep 1 + +# I don't have a case fan installed via PWM +label fan2 "Case fan" +#set fan2_min 1000 +#set fan2_beep 1 + +# Motherboard temps + +# Note: tempX_type indicates the type of sensor and is set by the BIOS + +# When comparing temp1 and temp2 with BIOS value, temp1 seems to be similar to BIOS system temperature. +# temp2 increases like temp1 does, so I assume that it is another case temp but not shown in BIOS. +label temp1 "Case temp (shown in BIOS)" +label temp2 "Case temp (hidden in BIOS)" + +# The reported values seem to be correct. No need to add offset or compute. + +# Let's set some real world values for min and max +set temp1_min 25 +set temp1_max 50 +set temp2_min 25 +set temp2_max 50 + +# Let's alarm when temperatures are outside range +set temp1_beep 1 +set temp2_beep 1 + +# temp3 increases when cpu high load, so assuming this is CPU temperature. +label temp3 "CPU temp" + +# Note: PECI value is negative value relative to _crit, but driver calculates +# to real value. + +# Adding 10 to correct wrong BIOS values. +# Change offset is more efficient than computing new value, because offset is done in hardware. +# Note: using compute also increases min and max values. You will need to set the min and max values below. +# Note: offset default value is 72, so add 10 makes 82. +#compute temp3 @+10,@-10 +set temp3_offset 82 + +# In BIOS it is possible to set CPU warning temperature, but this does not influence +# temp3_input. However, it does change the temp3_max. My bios setting is at 60 +# degrees. Coretemp defines maximum of 76. I want a warning at 60. +# _min, _max +set temp3_min 25 +#set temp3_max 60 + +# Let's alarm when temperature is outside range +set temp3_beep 1 + +# ignore intrusion detection (case open?) +ignore intrusion0 diff --git a/configs/Gigabyte/Z77-D3H.conf b/configs/Gigabyte/Z77-D3H.conf new file mode 100644 index 0000000..7ec6bf9 --- /dev/null +++ b/configs/Gigabyte/Z77-D3H.conf @@ -0,0 +1,78 @@ +# Configuration file contributed by Mathias Gerber. + + +chip "acpitz-virtual-0" + ignore temp1 # stays always at 27.8 degrees C + ignore temp2 # dito + +chip "it8728-*" + + label in0 "CPU Vtt" + set in0_min 1.02 # I'm liberal with these, 2-3% tops + set in0_max 1.08 # after that, cpu gets very unstable + + label in1 "+3.3V" + set in1_min 3.3 * 0.95 # Some boards including GA-H67MA-UD2H + set in1_max 3.3 * 1.05 # don't have 3.3V voltage reading + compute in1 1.649*@,@/1.649 # multipliers provided by Martin Malik author of hwinfo + + label in2 "+12V" + set in2_min 12 * 0.95 + set in2_max 12 * 1.05 + compute in2 @ * (72/12), @ / (72/12) #mg,15.05.13 + + label in3 "+5V" + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + compute in3 2.5*@,@/2.5 + + label in4 "Vaxg" # Voltage used by the video controller embedded inside the CPU + set in4_min 0.4 + set in4_max 1.4 + + label in5 "Vcore" + set in5_min 0.825 * 0.95 + set in5_max 1.425 * 1.05 + + label in6 "Vdram" + set in6_min 1.5 * 0.95 # adjust these, 1.35 for LVDDR3 + set in6_max 1.5 * 1.05 # 1.5V is recommended, 1.65 tops + + # 3VSB + set in7_min 3.3 * 0.95 + set in7_max 3.3 * 1.05 + + # Vbat + set in8_min 3.0 * 0.90 + set in8_max 3.0 * 1.10 + +### fan + + label fan1 "CPU fan" + set fan1_min 700 + + label fan2 "Sys1 fan" + set fan2_min 200 + + label fan3 "Sys2 fan" + set fan3_min 200 + + label fan4 "Sys3 fan" + set fan4_min 200 + + label fan5 "Sys4 fan" + set fan5_min 200 + +### temperatures + + label temp1 "System temp" # tops at 33 degrees C + set temp1_min 10 + set temp1_max 60 + + ignore temp2 # shows always 25 degrees C + set temp2_min 0 + set temp2_max 60 + + label temp3 "CPU temp" + set temp3_min 10 + set temp3_max 85 diff --git a/configs/HP/MicroServer_N40L.conf b/configs/HP/MicroServer_N40L.conf new file mode 100644 index 0000000..e659fe5 --- /dev/null +++ b/configs/HP/MicroServer_N40L.conf @@ -0,0 +1,46 @@ +# HP MicroServer N40L +# 2018, contributed by Leigh Brown +# +# dmi: sys_vendor: HP +# dmi: product_name: ProLiant MicroServer +# dmi: bios_version: O41 +# cpu: AMD Turion(tm) II Neo N40L Dual-Core Processor +# module: w83795adg +# +# This configuration will probably also work with the N54L version + +bus "i2c-0" "SMBus PIIX4 adapter port 0 at 0b00" +bus "i2c-1" "SMBus PIIX4 adapter port 2 at 0b00" + +chip "jc42-i2c-0-18" + label temp1 "DIMM A Temp" + set temp1_max 60 + set temp1_crit 70 + set temp1_crit_hyst 65 + +chip "jc42-i2c-0-19" + label temp1 "DIMM B Temp" + set temp1_max 60 + set temp1_crit 70 + set temp1_crit_hyst 65 + +chip "k10temp-pci-*" + label temp1 "CPU Core Temp" + +chip "w83795adg-i2c-1-2f" + label in0 "VSEN1" + set in0_min 0.50 + set in0_max 1.20 + + label in1 "VSEN2" + set in1_min 1.424 + set in1_max 1.574 + + label in2 "VSEN3" + ignore in3 + + label fan1 "System Fan" + + label temp1 "CPU Temp" + label temp2 "Northbridge Temp" + label temp5 "System Temp" diff --git a/configs/InsideTechnology/786LCD.conf b/configs/InsideTechnology/786LCD.conf new file mode 100644 index 0000000..0d4ed09 --- /dev/null +++ b/configs/InsideTechnology/786LCD.conf @@ -0,0 +1,52 @@ +# Example configuration file for the Inside Technology 786LCD motherboard: + +chip "it87-*" + + label in0 "VCore 1" + label in1 "VCore 2" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "3.3 Stdby" + label in6 "-12V" + label in7 "Stdby" + label in8 "VBat" + + # vid not monitored by IT8705F + ignore cpu0_vid + + # in0 will depend on your processor VID value, set to voltage specified in + # bios setup screen + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((30/10) +1)*@ , @/((30/10) +1) + compute in6 (1+232/56)*@ - 4.096*232/56, (@ + 4.096*232/56)/(1+232/56) + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + + set in0_min 1.7 * 0.95 + set in0_max 1.7 * 1.05 + set in1_min 2.4 + set in1_max 2.6 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5.0 * 0.95 + set in3_max 5.0 * 1.05 + # +- 12V are very poor tolerance on this board. Verified with voltmeter + set in4_min 12 * 0.90 + set in4_max 12 * 1.10 + set in5_min 3.3 * 0.95 + set in5_max 3.3 * 1.05 + set in6_max -12 * 0.90 + set in6_min -12 * 1.10 + set in7_min 5 * 0.95 + set in7_max 5 * 1.05 + + # Temperature + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + + # Fans + set fan1_min 3000 + ignore fan2 + ignore fan3 diff --git a/configs/Intel/D201GLY2.conf b/configs/Intel/D201GLY2.conf new file mode 100644 index 0000000..54fe7eb --- /dev/null +++ b/configs/Intel/D201GLY2.conf @@ -0,0 +1,45 @@ +# Configuration file contributed by Eric Le Bras. + + +# Configuration file for Intel D201GLY2 motherboard +# Hardware monitor subsystem controlled by Winbond W83627DHG-B I/O controller. +# Created using information from BIOS and board documentation. + +chip "w83627dhg-*" + + label in1 "+12V" + label in4 "+5V" + label in6 "+1.5V" + +# in5 is obviously unconnected, so ignore it + ignore in5 + + compute in1 @*(55/8), @/(55/8) + compute in4 @*(1+18/10), @/(1+18/10) + + set in1_min 12.0 * 0.95 + set in1_max 12.0 * 1.05 + set in4_min 5.0 * 0.95 + set in4_max 5.0 * 1.05 + set in6_min 1.5 * 0.90 + set in6_max 1.5 * 1.10 + + label fan1 "Chassis fan" + label fan2 "CPU fan" + +# By default the D201GLY2 has a passive heatsink. If the optional active +# heatsink is present, then one of the following lines is to be commented out +# (very likely fan2, though not tried). + ignore fan2 + ignore fan3 + ignore fan4 + + label temp1 "Sys temp" + label temp2 "CPU temp" + ignore temp3 + + set temp1_max 50 + set temp1_max_hyst 48 + + ignore cpu0_vid + ignore intrusion0 diff --git a/configs/Intel/D2500CC.conf b/configs/Intel/D2500CC.conf new file mode 100644 index 0000000..10d750a --- /dev/null +++ b/configs/Intel/D2500CC.conf @@ -0,0 +1,61 @@ +# Configuration file contributed by Balint Szente. + + +# Intel D2500CC based on BIOS values +# + +chip "w83627uhg-*" + + ignore intrusion0 + +# Voltages + + # Processor Vcc + label in0 "Vcore" + set in0_min 0.91 * 0.99 + set in0_max 1.21 * 1.01 + + # +3.3V + label in1 "+3.3V" + compute in1 3.2*@, @/3.2 + set in1_min 3.3 * 0.95 + set in1_max 3.3 * 1.05 + + # +5.0V + label in3 "+5V" + set in3_min 5.0 * 0.95 + set in3_max 5.0 * 1.05 + + # +12.0V + label in4 "+12V" + compute in4 12*@, @/12 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + + # Memory Vcc + label in5 "Vdimm" + set in5_min 1.5 * 0.95 + set in5_max 1.5 * 1.05 + + # +5.0V Standby + label in7 "5VSB" + set in7_min 4.60 + set in7_max 5.40 + +# Fans + + label fan1 "System Fan" + set fan1_min 250 + ignore fan2 + +# Temperatures + + # Memory Temperature + label temp1 "DIMM temp" + set temp1_max 80 + set temp1_max_hyst 75 + + # VR Temperature + label temp2 "VR temp" + set temp2_max 80 + set temp2_max_hyst 75 diff --git a/configs/Intel/D945GCLF.conf b/configs/Intel/D945GCLF.conf new file mode 100644 index 0000000..1fecf9c --- /dev/null +++ b/configs/Intel/D945GCLF.conf @@ -0,0 +1,55 @@ +# Configuration contributed by Marcelo Coelho. + + +# Configuration for Intel DG945GCLF + +chip "smsc47m1-*" + + label fan1 "Case Fan" + label fan2 "CPU Fan" + +chip "smsc47m192-*" + + label in0 "+2.5V" + set in0_min 2.5 * 0.95 + set in0_max 2.5 * 1.05 + + label in1 "Vcore" + set in1_min 0.9 + set in1_max 1.162 + + label in2 "+3.3V" + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + + label in3 "+5V" + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + + label in4 "+12V" + set in4_min 12.0 * 0.90 + set in4_max 12.0 * 1.10 + + label in5 "VCC" + set in5_min 3.3 * 0.90 + set in5_max 3.3 * 1.10 + + label in6 "+1.5V" + set in6_min 1.5 * 0.90 + set in6_max 1.5 * 1.10 + + label in7 "+1.8V" + set in7_min 1.8 * 0.90 + set in7_max 1.8 * 1.10 + + label temp1 "Chipset Temp" + set temp1_min 0 + set temp1_max 90 + + label temp2 "CPU Temp" + set temp2_min 0 + set temp2_max 85 + + label temp3 "System Temp" + set temp3_min 0 + set temp3_max 75 diff --git a/configs/Intel/DH57JG.conf b/configs/Intel/DH57JG.conf new file mode 100644 index 0000000..bd1ac14 --- /dev/null +++ b/configs/Intel/DH57JG.conf @@ -0,0 +1,48 @@ +# Contributed by Guenter Roeck. + + +chip "nct6775-*" + + label in0 "VCore" + label in1 "+12V" + label in2 "AVCC" + label in3 "+3.3V" + label in4 "+5V" + label in5 "+1.5V" + label in7 "VSB" + label in8 "VBAT" + + compute in1 16*@, @/16 + compute in4 4*@, @/4 + compute in5 2*@, @/2 + + set in0_min 0.5 + set in1_min 12 * 0.9 + set in1_max 12 * 1.1 + set in2_min 3.3 * 0.9 + set in2_max 3.3 * 1.1 + set in3_min 3.3 * 0.9 + set in3_max 3.3 * 1.1 + set in4_min 5 * 0.9 + set in4_max 5 * 1.1 + set in5_min 1.5 * 0.9 + set in5_max 1.5 * 1.1 + set in7_min 3.3 * 0.90 + set in7_max 3.3 * 1.10 + set in8_min 3.0 * 0.90 + set in8_max 3.0 * 1.10 + + ignore in6 + + set temp1_max 70 + set temp1_max_hyst 60 + set temp2_max 70 + set temp2_max_hyst 60 + set temp3_max 70 + set temp3_max_hyst 60 + + # PCH is used to control the fans + ignore fan1 + ignore fan2 + ignore fan3 + ignore fan4 diff --git a/configs/Intel/DH67BL.conf b/configs/Intel/DH67BL.conf new file mode 100644 index 0000000..aeb4198 --- /dev/null +++ b/configs/Intel/DH67BL.conf @@ -0,0 +1,95 @@ +# Configuration file contributed by Arseny Klimovsky. + + +# Created for board DH67BL using information from Intel Desktop Utilities and BIOS +# "FRONT" and "REAR" fan labels correspond to the motherboard +# headers, but not necessarily the actual fan locations. + +chip "nct6775-isa-0290" + +# Fans + label fan1 "Rear fan" + set fan1_min 250 # From IDU + + label fan2 "CPU fan" + set fan2_min 250 # From IDU + + label fan3 "Front fan" + set fan3_min 250 # From IDU + + # There is no fan4 on the board + ignore fan4 + +# Voltages + + # Processor Vcc + label in0 "Vcore" + set in0_min 0.6 # From IDU + set in0_max 1.6 # From IDU + + # This should be "12 Volts", but computations are strange + label in1 "+12V" + compute in1 11*@, @/11 + set in1_min 11.1 # From IDU + set in1_max 12.9 # From IDU + + # AVCC(?) - Not shown in BIOS or IDU + label in2 "AVCC" + set in2_min 3.0 # same as +3.3V + set in2_max 3.6 # same as +3.3V + + # +3.3 Volts + label in3 "+3.3V" + set in3_min 3.0 # from IDU + set in3_max 3.6 # from IDU + + # +5 Volts + label in4 "+5V" + compute in4 5*@, @/5 + set in4_min 4.6 # from IDU + set in4_max 5.4 # from IDU + + # Memory Vcc ("SDRAM Vcc" in IDU) + label in5 "MemV" + compute in5 1.5*@, @/1.5 + set in5_min 0.4 # from IDU + set in5_max 2.0 # from IDU + + # PCH Vcc + label in6 "PCHV" + set in6_min 0.6 # from IDU + set in6_max 1.6 # from IDU + + # +3.3 Volt Standby + label in7 "3VSB" + set in7_min 3.0 # from IDU + set in7_max 3.6 # from IDU + + # VBAT(?) - Not shown in BIOS or IDU + label in8 "Vbat" + + # It shows +2.050 V, seems to be not used + ignore cpu0_vid + +# Temperatures + + # Labeled as "SYSTIN" + # Guess! + label temp1 "VR temp" + set temp1_max 90 # From IDU + set temp1_max_hyst 75 # From IDU + # Labeled as "CPUTIN" + label temp2 "CPU temp" + set temp2_max 93 # From IDU + set temp2_max_hyst 75 # From IDU + # Labeled as "PECI Agent 0" + # Guess! + label temp3 "Memory DIMM temp" + set temp3_max 90 # From IDU + set temp3_max_hyst 75 # From IDU + # Labeled as "PCH_CHIP_TEMP" + label temp4 "PCH temp" + + # Labeled as "PECI Agent 1" + # Not used + ignore temp8 diff --git a/configs/Intel/DN2800MT.conf b/configs/Intel/DN2800MT.conf new file mode 100644 index 0000000..d32031c --- /dev/null +++ b/configs/Intel/DN2800MT.conf @@ -0,0 +1,64 @@ +# Configuration file contributed by Balint Szente. + + +# Intel DN2800MT based on BIOS values +# + +chip "w83627dhg-*" + + ignore cpu0_vid + ignore intrusion0 + +# Voltages + + # Processor Vcc + label in0 "Vcore" + set in0_min 0.75 * 0.99 + set in0_max 1.21 * 1.01 + + # +12.0V + label in1 "+12V" + compute in1 12*@, @/12 + set in1_min 12 * 0.95 + set in1_max 12 * 1.05 + + # +3.3V + label in3 "+3.3V" + set in3_min 3.3 * 0.95 + set in3_max 3.3 * 1.05 + + # +5.0V + label in4 "+5V" + compute in4 5*@, @/5 + set in4_min 5.0 * 0.95 + set in4_max 5.0 * 1.05 + + # Memory Vcc + label in5 "Vdimm" + set in5_min 1.5 * 0.95 + set in5_max 1.5 * 1.05 + + # PCH Vcc + label in6 "PCH" + set in6_min 1.05 * 0.95 + set in6_max 1.05 * 1.05 + + # +3.3V Standby + label in7 "3VSB" + set in7_min 3.3 * 0.95 + set in7_max 3.3 * 1.05 + +# Temperatures + + # Memory Temperature + label temp1 "DIMM temp" + set temp1_max 80 + set temp1_max_hyst 75 + + # Always on 110.5 + ignore temp2 + + # VR Temperature + label temp3 "VR temp" + set temp3_max 80 + set temp3_max_hyst 75 diff --git a/configs/Intel/DP55WB.conf b/configs/Intel/DP55WB.conf new file mode 100644 index 0000000..fb347e8 --- /dev/null +++ b/configs/Intel/DP55WB.conf @@ -0,0 +1,18 @@ +# Contributed by Roderick Johnstone and Jean Delvare. + + +chip "adt7490-i2c-*-2c" + + label in0 "Vdimm" + label in1 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + + ignore temp1 + label temp2 "M/B Temp" + + label fan1 "CPU Fan" + label fan2 "Front Fan" + label fan3 "Rear Fan" + ignore fan4 diff --git a/configs/Intel/DQ67EP.conf b/configs/Intel/DQ67EP.conf new file mode 100644 index 0000000..fde5aad --- /dev/null +++ b/configs/Intel/DQ67EP.conf @@ -0,0 +1,94 @@ +# Created for board DQ67EP using information from Intel Desktop Utilities and BIOS +# "FRONT" and "REAR" fan labels correspond to the motherboard +# headers, but not necessarily the actual fan locations. + +chip "nct6775-isa-0290" + +# Fans + label fan1 "Rear fan" + set fan1_min 250 # From IDU + + label fan2 "CPU fan" + set fan2_min 250 # From IDU + + # There is no fan3 on the board + ignore fan3 + + # There is no fan4 on the board + ignore fan4 + +# Voltages + + # Processor Vcc + label in0 "Vcore" + set in0_min 0.6 # From IDU + set in0_max 1.6 # From IDU + + # This should be "12 Volts", but computations are strange + label in1 "+12V" + compute in1 16*@, @/16 + set in1_min 11.1 # From IDU + set in1_max 12.9 # From IDU + + # AVCC(?) - Not shown in BIOS or IDU + label in2 "AVCC" + set in2_min 3.1 # same as +3.3V + set in2_max 3.5 # same as +3.3V + + # +3.3 Volts + label in3 "+3.3V" + set in3_min 3.1 # from IDU + set in3_max 3.5 # from IDU + + # +5 Volts + label in4 "+5V" + compute in4 4*@, @/4 + set in4_min 4.7 # from IDU + set in4_max 5.3 # from IDU + + # Memory Vcc ("SDRAM Vcc" in IDU) + label in5 "+1.5V" + set in5_min 1.4 # from IDU + set in5_max 1.6 # from IDU + + # PCH Vcc + label in6 "PCH" + set in6_min 0.6 # from IDU + set in6_max 1.6 # from IDU + + # +3.3 Volt Standby + label in7 "3VSB" + set in7_min 3.1 # from IDU + set in7_max 3.5 # from IDU + + # VBAT(?) - Not shown in BIOS or IDU + label in8 "Vbat" + + # It shows +2.050 V, seems to be not used + ignore cpu0_vid + +# Temperatures + + # Labeled as "SYSTIN" + # Guess! + label temp1 "DIMM temp" + set temp1_max 80 # From IDU + set temp1_max_hyst 75 # From IDU + + # Labeled as "CPUTIN" + label temp2 "VR temp" + set temp2_max 80 # From IDU + set temp2_max_hyst 75 # From IDU + + # Labeled as "PECI Agent 0" + # Guess! + label temp3 "CPU temp" + set temp3_max 80 # From IDU + set temp3_max_hyst 75 # From IDU + + # Labeled as "PCH_CHIP_TEMP" + label temp7 "PCH temp" + + # Labeled as "PECI Agent 1" + # Not used + ignore temp8 diff --git a/configs/Intel/DQ67SW.conf b/configs/Intel/DQ67SW.conf new file mode 100644 index 0000000..29085c2 --- /dev/null +++ b/configs/Intel/DQ67SW.conf @@ -0,0 +1,342 @@ +# Configuration files contributed by Ian Pilcher. +# The first one is for old BIOS versions: + +################################################################################ +# +# +# lm_sensors configuration for Intel DQ67SW +# +# NOTES: +# +# BIOS = SWQ6710H.86A.0050.2011.0401.1409 (01-Apr-2011) +# +# IDU = Intel Desktop Utilities version 3.1.3.030 +# (Windows 7 Professional SP1, 64-bit) +# +# The minimum, maximum, and hysteresis values are generally the +# more conservative of the IDU- or BIOS-provided values. +# +# "FRONT" and "REAR" fan labels correspond to the motherboard +# headers, but not necessarily the actual fan locations. +# +# Minimum fan RPMs should be adjusted to reflect the behavior of +# the installed fans. +# +# "Memory DIMM Temperature" is presumably measured by a diode +# somewhere in the vicinity of the DIMM slots; "System Temperature +# might be a better name. +# +# 80 degrees Celcius might be a bit high for the "Memory DIMM +# Temperature" limit. +# +# +################################################################################ + +chip "nct6775-*" + + ignore cpu0_vid + + ######################################################################## + # + # Voltages + # + ######################################################################## + + # + # Processor Vcc + # + label in0 "VCORE" + set in0_min 0.2 # from IDU (BIOS = 0.00) + set in0_max 1.6 # from IDU (BIOS = 1.74) + + # + # +12 Volts + # + label in1 "+12V" + compute in1 16*@, @/16 + set in1_min 10.8 # from IDU (BIOS does not set) + set in1_max 13.2 # from IDU (BIOS does not set) + + # + # AVCC(?) - Not shown in BIOS or IDU + # + label in2 "AVCC" + set in2_min 3.1 # same as +3.3V (BIOS = 2.98) + set in2_max 3.5 # same as +3.3V (BIOS = 3.63) + + # + # +3.3 Volts + # + label in3 "+3.3V" + set in3_min 3.1 # from IDU (BIOS = 2.98) + set in3_max 3.5 # from IDU (BIOS = 3.63) + + # + # +5 Volts + # + label in4 "+5V" + compute in4 4*@, @/4 + set in4_min 4.7 # from IDU (BIOS does not set) + set in4_max 5.3 # from IDU (BIOS does not set) + + # + # SDRAM Vcc + # + label in5 "+1.5V" + set in5_min 1.4 # from IDU (BIOS does not set) + set in5_max 1.6 # from IDU (BIOS does not set) + + # + # PCH Vcc + # + label in6 "PCH" + set in6_min 0.6 # from IDU (BIOS does not set) + set in6_max 1.6 # from IDU (BIOS does not set) + + # + # +3.3 Volt Standby + # + label in7 "VSB" + set in7_min 3.0 # from IDU (BIOS = 2.98) + set in7_max 3.6 # from IDU (BIOS = 3.63) + + # + # VBAT(?) - Not shown in BIOS or IDU + # + label in8 "VBAT" + #set in8_min 2.7 # from BIOS + #set in8_max 3.3 # from BIOS + + ######################################################################## + # + # Fans + # + ######################################################################## + + ignore fan4 + + # + # Chassis Inlet Fan + # + label fan1 "FRONT" + set fan1_min 250 # from IDU (BIOS does not set) + + # + # Processor Fan + # + label fan2 "CPU" + set fan2_min 250 # from IDU (BIOS does not set) + + # + # Chassis Outlet Fan + # + label fan3 "REAR" + set fan3_min 250 # from IDU (BIOS does not set) + + ######################################################################## + # + # Temperatures + # + ######################################################################## + + ignore temp8 + + # + # Memory DIMM Temperature + # + label temp1 "DIMM" + set temp1_max 80 # same as VR (IDU = 90) + set temp1_max_hyst 75 # same as VR + + # + # VR Temperature + # + label temp2 "VR" + set temp2_max 80 # from BIOS (IDU = 90) + set temp2_max_hyst 75 # from BIOS + + # + # Processor Temperature + # + label temp3 "CPU" + set temp3_max 80 # from BIOS (IDU = 87) + set temp3_max_hyst 75 # from BIOS + + # + # PCH Temperature + # + label temp4 "PCH" + +And the second one is for new BIOS versions: + +################################################################################ +# +# +# lm_sensors configuration for Intel DQ67SW (with newer BIOS) +# +# NOTES: +# +# Temperature input mappings were changed by a BIOS update +# between SWQ6710H.86A.0050.2011.0401.1409 (01-Apr-2011) and +# SWQ6710H.86A.0065.2012.0917.1519 (17-Sep-2012). +# +# Minimum and maximum values are the defaults from BIOS version +# SWQ6710H.86A.0065.2012.0917.1519 (17-Sep-2012). +# +# Intel Desktop Utilities 3.2.3.052 appears to get its default +# values from the BIOS. +# +# "FRONT" and "REAR" fan labels correspond to the motherboard +# headers, but not necessarily the actual fan locations. +# +# Minimum fan RPMs should be adjusted to reflect the behavior of +# the installed fans. +# +# "Memory DIMM Temperature" is presumably measured by a diode +# somewhere in the vicinity of the DIMM slots; "System Temperature +# might be a better name. If this is correct, 90 degrees seems +# like an extremely high threshhold for this reading. +# +# All hysteresis values are set to 75 degrees, which seems to be +# the default for the chip/driver. +# +# +################################################################################ + +chip "nct6775-*" + + ignore cpu0_vid + + ######################################################################## + # + # Voltages + # + ######################################################################## + + # + # Processor Vcc + # + label in0 "VCORE" + set in0_min 0.2 + set in0_max 1.6 + + # + # +12 Volts + # + label in1 "+12V" + compute in1 16*@, @/16 + set in1_min 10.8 + set in1_max 13.2 + + # + # AVCC(?) - Not shown in BIOS or IDU; min/max taken from +3.3V + # + label in2 "AVCC" + set in2_min 3.1 + set in2_max 3.5 + + # + # +3.3 Volts + # + label in3 "+3.3V" + set in3_min 3.1 + set in3_max 3.5 + + # + # +5 Volts + # + label in4 "+5V" + compute in4 4*@, @/4 + set in4_min 4.7 + set in4_max 5.3 + + # + # Memory Vcc + # + label in5 "+1.5V" + set in5_min 1.4 + set in5_max 1.6 + + # + # PCH Vcc + # + label in6 "PCH" + set in6_min 0.6 + set in6_max 1.6 + + # + # +3.3 Volt Standby + # + label in7 "VSB" + set in7_min 3.0 + set in7_max 3.6 + + # + # VBAT(?) - Not shown in BIOS or IDU; min/max taken from old BIOS + # + label in8 "VBAT" + #set in8_min 2.7 + #set in8_max 3.3 + + ######################################################################## + # + # Fans + # + ######################################################################## + + ignore fan4 + + # + # Chassis Inlet Fan + # + label fan1 "FRONT" + set fan1_min 250 # from IDU (BIOS does not set) + + # + # Processor Fan + # + label fan2 "CPU" + set fan2_min 250 # from IDU (BIOS does not set) + + # + # Chassis Outlet Fan + # + label fan3 "REAR" + set fan3_min 250 # from IDU (BIOS does not set) + + ######################################################################## + # + # Temperatures + # + ######################################################################## + + ignore temp3 + ignore temp8 + + # + # Memory DIMM Temperature + # + label temp1 "DIMM" + set temp1_max 90 + set temp1_max_hyst 75 + + # + # VR Temperature + # + label temp2 "VR" + set temp2_max 90 + set temp2_max_hyst 75 + + # + # Processor Temperature + # + label temp6 "CPU" + set temp6_max 99 + set temp6_max_hyst 75 + + # + # PCH Temperature + # + label temp7 "PCH" + set temp7_max 114 + set temp7_max_hyst 75 diff --git a/configs/Jetway/NC92-330-LF.conf b/configs/Jetway/NC92-330-LF.conf new file mode 100644 index 0000000..d208764 --- /dev/null +++ b/configs/Jetway/NC92-330-LF.conf @@ -0,0 +1,75 @@ +# Configuration contributed by Maciej Å»enczykowski. +# Kernel modules used: f71882fg, coretemp. + + +# Jetway NC92-330-LF + +chip "f71862fg-*" + + label in0 "Vcc3V" + label in1 "Vcore" + label in2 " NB" + label in3 "+ 5V" + label in4 "+12V" + label in5 "5VSB" + label in6 "VDIMM" + label in7 "VSB3V" + label in8 "Vbat" + + label fan1 "CPUFAN" + label fan2 "SYSFAN1" + label fan3 "SYSFAN2" + + label temp1 "?CPU Temp" + label temp2 "?Sys Temp" + label temp3 "???? Temp" + +# According to datasheet, 3VCC/VSB/VBAT +# (ie. Vcc3V/VSB3V/Vbat, or in0/in7/in8) +# use internal R1=R2=150K Ohm resistors +# +# remember V_in_to_chip = V_real * R2 / (R1 + R2) +# (where V_real----R1---*----V_in_to_chip) [max 2.048V] +# ( | ) +# ( R2 ) +# ( | ) +# ( GND ) +# +# It would seem that VDIMM is the same... +# Hence those four are set to use "@*2, @/2" +# +# The values of 5.25 for +5V and 5VSB and 11 for +12V +# are from the datasheet as well (after juggling): +# +# VCORE R1=1K R2=inf VCORE -> *1 +# VRAM R1=10K R2=10K VIN2 -> *2 +# VCHIPSET R1=4.7K R2=10K VIN3 -> *1.47 +# VCC5V R1=20K R2=4.7 VIN4 -> *5.255319148 +# +12V R1=200K R2=20K VIN5 -> *11 +# VCC1.5V R1=10K R2=inf VIN6 -> *1 + + compute in0 @*2, @/2 + compute in1 @, @ + compute in2 @, @ + compute in3 @*5.255319148, @/5.255319148 + compute in4 @*11, @/11 + compute in5 @*5.255319148, @/5.255319148 + compute in6 @*2, @/2 + compute in7 @*2, @/2 + compute in8 @*2, @/2 + +# set temp1_type 2 + set temp1_max 85 + set temp1_max_hyst 81 + set temp1_crit 65 +# set temp1_crit_hyst 61 +# set temp2_type 2 + set temp2_max 85 + set temp2_max_hyst 81 + set temp2_crit 100 +# set temp2_crit_hyst 96 +# set temp3_type 2 + set temp3_max 70 + set temp3_max_hyst 68 + set temp3_crit 85 +# set temp3_crit_hyst 83 diff --git a/configs/Kontron/986LCD-M.conf b/configs/Kontron/986LCD-M.conf new file mode 100644 index 0000000..cf36bd6 --- /dev/null +++ b/configs/Kontron/986LCD-M.conf @@ -0,0 +1,48 @@ +# Voltage section for the Kontron 986LCD-M: + +chip "w83627thf-*" + +# Voltages + + label in0 "Vcore" + label in1 "+12V" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+1.5V" + label in7 "5VSB" + label in8 "Vbat" + + # External resistors + compute in1 @ * (1 + 10/3.57), @ / (1 + 10/3.57) + # Internal resistors + compute in3 @ * (1 + 34/51), @ / (1 + 34/51) + compute in7 @ * (1 + 34/51), @ / (1 + 34/51) + + set in1_min 12.0 * 0.95 + set in1_max 12.0 * 1.05 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5.0 * 0.95 + set in3_max 5.0 * 1.05 + set in4_min 1.5 * 0.95 + set in4_max 1.5 * 1.05 + set in7_min 5.0 * 0.90 + set in7_max 5.0 * 1.10 + set in8_min 3.0 * 0.90 + set in8_max 3.0 * 1.15 + +# Fans + + label fan1 "Sys Fan" + label fan2 "CPU Fan" + label fan3 "Aux Fan" + +# Temperatures + + label temp1 "M/B Temp" + label temp2 "CPU Temp" + # temp3 is an optional external sensor + + # Default limits for temp2 and temp3 are sane, but not for temp1 + set temp1_max 80 + set temp1_max_hyst 75 diff --git a/configs/MSI/945P-Neo2-F.conf b/configs/MSI/945P-Neo2-F.conf new file mode 100644 index 0000000..1fa26d0 --- /dev/null +++ b/configs/MSI/945P-Neo2-F.conf @@ -0,0 +1,56 @@ +# Winbond W83627EHF configuration contributed by Dmitry Pechnikov +# This is for an MSI 945P Neo2-F aka MS-7176. +chip "w83627ehf-*" "w83627dhg-*" + + label in0 "VCore" + label in1 "+12V" + label in2 "AVCC" + label in3 "3VCC" + label in6 "+5V" + label in7 "VSB" + label in8 "VBAT" + +# +12V is in1 and +5V is in6 as recommended by datasheet + compute in1 @*(1+(56/10)), @/(1+(56/10)) + compute in6 @*(1+(22/10)), @/(1+(22/10)) + + set in1_min 12.0*0.9 + set in1_max 12.0*1.1 + set in6_min 5.0*0.9 + set in6_max 5.0*1.1 + + set in2_min 3.3*0.9 + set in2_max 3.3*1.1 + set in3_min 3.3*0.9 + set in3_max 3.3*1.1 + set in7_min 3.3*0.9 + set in7_max 3.3*1.1 + set in8_min 3.3*0.9 + set in8_max 3.3*1.1 + + ignore in4 + ignore in5 + ignore in9 + +# Fans + label fan1 "Case Fan" + label fan2 "CPU Fan" + label fan3 "Aux Fan" + + ignore fan1 + ignore fan3 + ignore fan5 +# set fan1_min 1200 + set fan2_min 1000 + +# Temperatures + label temp1 "Sys Temp" + label temp2 "CPU Temp" + label temp3 "AUX Temp" + + set temp1_max 55 + set temp1_max_hyst 48 + set temp2_max 55 + set temp2_max_hyst 47 + set temp3_max 55 + set temp3_max_hyst 50 diff --git a/configs/MSI/975X-Platinum.conf b/configs/MSI/975X-Platinum.conf new file mode 100644 index 0000000..09b9711 --- /dev/null +++ b/configs/MSI/975X-Platinum.conf @@ -0,0 +1,63 @@ +# Configuration file for the MSI 975X Platinum (MS-7246), +# contributed by Leonardo Marín. + + +chip "w83627ehf-*" "w83627dhg-*" + + label in0 "VCore" # CPU Core Voltage + label in1 "VPCIEx" # PCI Express Voltage + label in2 "AVCC" + label in3 "3VCC" + label in6 "+ 5V" # +5V, or so i think + label in7 "3VSB" + label in8 "VBAT" + label in9 "+12V" # +12V, or so i think + +## +12V is in9 and +5V is in6 ## + compute in9 @*(1+(56/10)), @/(1+(56/10)) + compute in6 @*(1+(22/10)), @/(1+(22/10)) + + set in9_min 12.0*0.9 + set in9_max 12.0*1.1 + set in6_min 5.0*0.9 + set in6_max 5.0*1.1 + + set in0_min 0.9 + set in0_max 1.7 + set in1_min 1.4 + set in1_max 2.0 + set in2_min 3.3*0.9 + set in2_max 3.3*1.1 + set in3_min 3.3*0.9 + set in3_max 3.3*1.1 + set in7_min 3.3*0.9 + set in7_max 3.3*1.1 + set in8_min 3.0*0.9 + set in8_max 3.3*1.1 + + ignore in4 + ignore in5 + +## Temperatures ## + + label temp1 "Sys Temp" + label temp2 "CPU Temp" + label temp3 "Aux Temp" + + set temp1_max 55 + set temp1_max_hyst 48 + set temp2_max 55 + set temp2_max_hyst 47 + set temp3_max 55 + set temp3_max_hyst 50 + +## Fans ## + + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "NB Fan" + label fan4 "Sys Fan" + + set fan2_min 800 + + ignore fan5 diff --git a/configs/MSI/GF615M-P33.conf b/configs/MSI/GF615M-P33.conf new file mode 100644 index 0000000..7ee1aef --- /dev/null +++ b/configs/MSI/GF615M-P33.conf @@ -0,0 +1,60 @@ +# Contributed by John Smith. + + +# lm_sensors configuration file for the MSI GF615M-P33 rev 1.3 (MS-7597) +# 2011-07-14, Kid from Belgrade +# tweaked from config for MSI P35 Neo / MSI MS-7360 motherboard +# 2007-09-21, Andre Jagusch +# Comments welcome! + +chip "f71889ed-*" + +# Temperature + label temp1 "CPU" + label temp2 "System" + ignore temp3 + +# Fans + label fan1 "CPU" + label fan2 "System" + label fan3 "Misc" + +# sensors in2, in3, in6, in7 and in8 may be ignored since +# they are not shown in BIOS for MS-7597 +# in6 is always 0.00 +# Voltage + label in0 "+3.3V" + label in1 "Vcore" +# ignore in2 +# ignore in3 + label in2 "Vdimm" + label in3 "Vchip" + label in4 "+5V" + label in5 "+12V" + ignore in6 +# ignore in7 +# ignore in8 + label in7 "3VSB" + label in8 "Battery" + +# never change the in0, in7 and in8 compute, these are hardwired in the chip! +# +5V, +12V and +3.3V computes looking fine for MS-7597, nothing changed + compute in0 (@ * 2), (@ / 2) + compute in2 (@ * 2), (@ / 2) + compute in3 (@ * 2), (@ / 2) + compute in4 (@ * 5.25), (@ / 5.25) + compute in5 (@ * 11), (@ / 11) + compute in6 (@ * 6.585), (@ / 6.585) + compute in7 (@ * 2), (@ / 2) + compute in8 (@ * 2), (@ / 2) + + +# On Fintek, first sensor is below or near the CPU socket (how to determine this?) +# CPU temperature is also measurable by on-die sensor on K10 series. +# Now I have not found this anywhere and correction is correlated with Fintek, +# tweaked for Athlon II x2 250, may differ for others. +chip "k10temp-*" + + label temp1 "CPU K10 Temp" + + compute temp1 (@ + 5.5), (@ - 5.5) diff --git a/configs/MSI/IM-945GC.conf b/configs/MSI/IM-945GC.conf new file mode 100644 index 0000000..5bd7df1 --- /dev/null +++ b/configs/MSI/IM-945GC.conf @@ -0,0 +1,58 @@ +# Configuration file contributed by Bryan Guidroz. + + +chip "f71882fg-isa-0a10" + +# Ignore - Voltage +# The F71882FG uses an 8-bit, 8 mV LSB ADC for voltage monitoring. +# This means that it can measure up to 2.04 V directly. This is the value +# of in2, in3 and in6 on the MSI MS-9832, which means these inputs +# are saturated. This means these inputs are unused. + + ignore in2 + ignore in3 + ignore in6 + +# Ignore - Fans +# The MSI MS-9832 uses fan1 (CPU Fan) and fan2 (System Fan). +# This means other fans are unused. + + ignore fan3 + ignore fan4 + +# Ignore - Temps +# The MSI MS-9832 uses temp1 (CPU temp) and temp3 (System temp). +# This means temp2 is unused. + + ignore temp2 + +# Other - Voltages +# in0 (+3.3v), in7 (3VSB), and in8 (Vbat) are internally monitored voltages +# with internal dividers. This means the values are properly set and do not +# need to be defined in this configuration as they should be reported properly. + +# Voltages + label in1 "Vcore" + label in4 "+5V" + label in5 "+12V" + + compute in4 @*(1+200/47), @/(1+200/47) + compute in5 @*(1+200/20), @/(1+200/20) + + set in1_max 1.1625 * 1.05 + +# Fans + label fan1 "CPU Fan" + label fan2 "Sys Fan" + + set fan1_min 2100 + set fan2_min 1400 + +# Temperatures + label temp1 "CPU Temp" + label temp3 "Sys Temp" + + set temp1_max 60 + set temp1_max_hyst 58 + set temp3_max 50 + set temp3_max_hyst 48 diff --git a/configs/MSI/IM-945GSE-A.conf b/configs/MSI/IM-945GSE-A.conf new file mode 100644 index 0000000..51aac2d --- /dev/null +++ b/configs/MSI/IM-945GSE-A.conf @@ -0,0 +1,39 @@ +# lm_sensors configuration file for the MSI IM-945GSE-A motherboard +# Atom N270, Dual Gigabit Intel 82574L controllers, VGA, DVI +# 2009-07-01 Thomas Ettwein +# 2010-08-29 Leo Krueger + +chip "f71882fg-*" + +# Temperature + label temp1 "CPU" + label temp2 "Systemboard" + ignore temp3 + +# Fans + ignore fan1 # no connector on board + label fan2 "CPUFAN1" + ignore fan3 # no connector on board + ignore fan4 # no connector on board + + +# Voltage + label in0 "3.3V" + label in1 "Vcore" + label in2 "Vdimm" + label in3 "Vchip" + label in4 "+5V" + label in5 "12V" + label in6 "5VSB" + label in7 "3VSB" + label in8 "Battery" + +# never change the in0, in7 and in8 compute, these are hardwired in the chip! + compute in0 (@ * 2), (@ / 2) + compute in2 (@ * 2), (@ / 2) + compute in3 (@ * 2), (@ / 2) + compute in4 (@ * 5.25), (@ / 5.25) + compute in5 (@ * 11.0), (@ / 11.0) + compute in6 (@ * 5.25), (@ / 5.25) + compute in7 (@ * 2), (@ / 2) + compute in8 (@ * 2), (@ / 2) diff --git a/configs/MSI/MS-7302-K9A2GM-V.conf b/configs/MSI/MS-7302-K9A2GM-V.conf new file mode 100644 index 0000000..fb1d1a0 --- /dev/null +++ b/configs/MSI/MS-7302-K9A2GM-V.conf @@ -0,0 +1,22 @@ +# input routing and scaling read from board schematic + +chip "f71882fg-*" + label in1 "CPU Vcore" + label in2 "+12V" + label in3 "+5V" + ignore in4 + label in5 "+5VSB" + ignore in6 + + compute in2 (@ * 11.00), (@ / 11.00) + compute in3 ((@ * (47 + 10)) / 10), ((@ * 10) / (47 + 10)) + compute in5 ((@ * (47 + 10)) / 10), ((@ * 10) / (47 + 10)) + + label fan1 "CPU Fan" + ignore fan2 + label fan3 "SYS Fan" + ignore fan4 + + label temp1 "CPU Temperature" + ignore temp2 + label temp3 "System Temperature" diff --git a/configs/MSI/MS-7786-A55M-P33.conf b/configs/MSI/MS-7786-A55M-P33.conf new file mode 100644 index 0000000..d22ad51 --- /dev/null +++ b/configs/MSI/MS-7786-A55M-P33.conf @@ -0,0 +1,20 @@ +# input routing and scaling read from board schematic + +chip "f71868a-*" + label in1 "Vcore" + label in2 "VDDR" + label in3 "+5V" + label in4 "+12V" + label in5 "Vcc1P1" + ignore in6 + + compute in3 @ * (200 + 47) / 47, @ * 47 / (200 + 47) + compute in4 @ * 11, @ / 11 + + label fan1 "CPU FAN" + label fan2 "SYS FAN1" + ignore fan3 + + label temp1 "System DDR Temp" + label temp2 "System Temp" + label temp3 "System SIO Temp" diff --git a/configs/MSI/P35-Neo.conf b/configs/MSI/P35-Neo.conf new file mode 100644 index 0000000..72cb75a --- /dev/null +++ b/configs/MSI/P35-Neo.conf @@ -0,0 +1,37 @@ +# lm_sensors configuration file for the MSI P35 Neo / MSI MS-7360 motherboard +# 2007-09-21, Andre Jagusch +# Comments welcome! + +chip "f71882fg-*" + +# Temperature + label temp1 "CPU" + label temp2 "System" + ignore temp3 + +# Fans + label fan1 "CPU" + label fan2 "System" + label fan3 "Power" + label fan4 "Aux" + +# Voltage + label in0 "3.3V" + label in1 "Vcore" + label in2 "Vdimm" + label in3 "Vchip" + label in4 "+5V" + label in5 "12V" + label in6 "5VSB" + label in7 "3VSB" + label in8 "Battery" + +# never change the in0, in7 and in8 compute, these are hardwired in the chip! + compute in0 (@ * 2), (@ / 2) + compute in2 (@ * 2), (@ / 2) + compute in3 (@ * 2), (@ / 2) + compute in4 (@ * 5.25), (@ / 5.25) + compute in5 (@ * 11), (@ / 11) + compute in6 (@ * 6.585), (@ / 6.585) + compute in7 (@ * 2), (@ / 2) + compute in8 (@ * 2), (@ / 2) diff --git a/configs/MSI/P6N-SLI-FI.conf b/configs/MSI/P6N-SLI-FI.conf new file mode 100644 index 0000000..73e22f0 --- /dev/null +++ b/configs/MSI/P6N-SLI-FI.conf @@ -0,0 +1,58 @@ +# Sasha Alexandr - grapefruitgirl at linuxmail dot org +# Sept 2007 - lm_sensors 2.10.4 +# Platform: MS-7350-010 P6N-SLI-FI mfg-date: 0707 +# Chipset: nVidia nforce2 650i/430i SLI +# CPU: Intel CORE2 E2160 1.8 Ghz +# BIOS: AMIBIOS v2.3 +# +# Configuration for Fintek F71882FG Super-I/O device & coretemp driver for CORE2 CPU temps: + + chip "f71882fg-isa-0a00" + +# NOTE: Fans 1 and 3 are switched around (somewhere). + label fan1 "CPU Cooler" + label fan2 "SysFan2: Rear Case" + label fan3 "SysFan1: some device" + label fan4 "SysFan3: some device" + +# NOTE: Set statements for fans & volts give an 'Unknown Feature' error currently. This should be fixed sometime. +# The fans report exact same as BIOS; no computing needed. +# Header labeled 'Sysfan3' on board doesn't seem to report RPM. + + label temp1 "CPU Temp" + label temp2 "System Temp" + label temp3 "128 ignore" + +# NOTE: temp1 reports 5'C less than BIOS so I add 5'C to it. + compute temp1 (@ + 5), (@ - 5) + ignore temp3 + +# Voltages: + label in0 "3.3V in0" + label in1 "CPU V-Core in1" + label in2 "+5V StBy in2" + label in3 "V-Dimm in3" + label in4 "+5V in4" + label in5 "+12V in5" + label in6 "0.888 ignore" + label in7 "3.3 V StBy in7" + label in8 "3V Battery in8" + + compute in0 (@ * 2.00) ,(@ / 2.00) +# compute in1 (no computing necessary) + compute in2 (@ * 5.25) ,(@ / 5.25) + compute in3 (@ * 2.50) ,(@ / 2.50) +# NOTE: I add 0.005 to in4 so it reads EXACTLY as BIOS reads. + compute in4 (0.005 + @ * 5.25) ,(0.005 - @ / 5.25) + compute in5 (@ * 11.00),(@ / 11.00) + ignore in6 + compute in7 (@ * 2.00) ,(@ / 2.00) + compute in8 (@ * 2.00) ,(@ / 2.00) + +chip "coretemp-isa-0000" +label temp1 "Core 0 Temp" + +chip "coretemp-isa-0001" +label temp1 "Core 1 Temp" + +# EOF diff --git a/configs/MSI/P965-Platinum.conf b/configs/MSI/P965-Platinum.conf new file mode 100644 index 0000000..fd7b87d --- /dev/null +++ b/configs/MSI/P965-Platinum.conf @@ -0,0 +1,48 @@ +# Configuration file contributed by Olaf Mandel. + + +# configuration for the Fintek f71882fg as used on the MSI X58 Pro-E (MS-7522) +chip "f71882fg-*" + +# Temperature + label temp1 "CPU" + label temp2 "IOH" + label temp3 "System" + +# Fans + label fan1 "CPU" + label fan2 "System 1" # This is not confirmed + label fan3 "System 2" + ignore fan2 + ignore fan4 + +# Voltage + label in0 "3.3V" + label in1 "Vcore" + ignore in2 + ignore in3 + label in4 "5V" + label in5 "12V" + ignore in6 + label in7 "3VSB" + label in8 "Vbat" + compute in0 (@ * 2), (@ / 2) # Hardwired in chip, don't change + compute in4 (@ * 5.25), (@ / 5.25) # E24: (12 + 51) / 12 + compute in5 (@ * 11), (@ / 11) # E6: ( 1 + 10) / 1 + compute in7 (@ * 2), (@ / 2) # Hardwired in chip, don't change + compute in8 (@ * 2), (@ / 2) # Hardwired in chip, don't change + +# Thresholds + set in1_max 1.3 + set temp1_max 85 + set temp1_max_hyst 82 + set temp1_crit 100 + set temp1_crit_hyst 97 + set temp2_max 75 + set temp2_max_hyst 72 + set temp2_crit 85 + set temp2_crit_hyst 82 + set temp3_max 55 + set temp3_max_hyst 52 + set temp3_crit 65 + set temp3_crit_hyst 62 diff --git a/configs/MSI/X58-Pro-E.conf b/configs/MSI/X58-Pro-E.conf new file mode 100644 index 0000000..fd7b87d --- /dev/null +++ b/configs/MSI/X58-Pro-E.conf @@ -0,0 +1,48 @@ +# Configuration file contributed by Olaf Mandel. + + +# configuration for the Fintek f71882fg as used on the MSI X58 Pro-E (MS-7522) +chip "f71882fg-*" + +# Temperature + label temp1 "CPU" + label temp2 "IOH" + label temp3 "System" + +# Fans + label fan1 "CPU" + label fan2 "System 1" # This is not confirmed + label fan3 "System 2" + ignore fan2 + ignore fan4 + +# Voltage + label in0 "3.3V" + label in1 "Vcore" + ignore in2 + ignore in3 + label in4 "5V" + label in5 "12V" + ignore in6 + label in7 "3VSB" + label in8 "Vbat" + compute in0 (@ * 2), (@ / 2) # Hardwired in chip, don't change + compute in4 (@ * 5.25), (@ / 5.25) # E24: (12 + 51) / 12 + compute in5 (@ * 11), (@ / 11) # E6: ( 1 + 10) / 1 + compute in7 (@ * 2), (@ / 2) # Hardwired in chip, don't change + compute in8 (@ * 2), (@ / 2) # Hardwired in chip, don't change + +# Thresholds + set in1_max 1.3 + set temp1_max 85 + set temp1_max_hyst 82 + set temp1_crit 100 + set temp1_crit_hyst 97 + set temp2_max 75 + set temp2_max_hyst 72 + set temp2_crit 85 + set temp2_crit_hyst 82 + set temp3_max 55 + set temp3_max_hyst 52 + set temp3_crit 65 + set temp3_crit_hyst 62 diff --git a/configs/MSI/Z85-G45_Gaming.conf b/configs/MSI/Z85-G45_Gaming.conf new file mode 100644 index 0000000..fc699d5 --- /dev/null +++ b/configs/MSI/Z85-G45_Gaming.conf @@ -0,0 +1,83 @@ +# MSI Z85-G45 Gaming Motherboard +# 2018, contributed by Leigh Brown +# +# dmi: board_name: Z87-G45 GAMING (MS-7821) +# dmi: board_vendor: MSI +# dmi: bios_version: V1.4 +# cpu: Intel(R) Core(TM) i5-4670K CPU @ 3.40GHz +# driver: nct6775 + +chip "nct6779-isa-0a00" + label in0 "VCCIN" + compute in0 @*2, @/2 + set in0_min 1.4 + set in0_max 1.9 + + label in1 "+5V" + compute in1 @*5, @/5 + set in1_min 5 * 0.95 + set in1_max 5 * 1.05 + + #label in2 "AVCC" + #label in3 "+3.3V" + + label in4 "+12V" + compute in4 @*11, @/11 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + + label in5 "CPUSAV" + set in5_min 0.904 * 0.95 + set in5_max 0.904 * 1.05 + + label in6 "VPCH" + set in6_min 1.05 * 0.95 + set in6_max 1.05 * 1.05 + + #label in7 "3VSB" + #label in8 "Vbat" + + label in9 "VCCIOA" + set in9_min 0.97 + set in9_max 1.06 + + ignore in10 + + label in11 "iGPUV" + + label in12 "VCCIOD" + set in12_min 0.97 + set in12_max 1.06 + + label in13 "DRAMV" + compute in13 @*2, @/2 + set in13_min 1.30 + set in13_max 1.80 + + label in14 "Vcore" + set in14_min 0.4 + set in14_max 1.4 + + label fan2 "CPU Fan" + label fan3 "Chassis Fan 2" + label fan4 "Chassis Fan 1" + label fan1 "Chassis Fan 3" + ignore fan5 + + label temp1 "System Temp" + set temp1_max 60 + set temp1_max_hyst 55 + + label temp7 "CPU Core Temp" + + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore temp8 + ignore temp9 + ignore temp10 + + ignore intrusion0 + ignore intrusion1 diff --git a/configs/PCchips/M811.conf b/configs/PCchips/M811.conf new file mode 100644 index 0000000..18346bb --- /dev/null +++ b/configs/PCchips/M811.conf @@ -0,0 +1,97 @@ +# lm_sensors configuration file for the PCchips M811 motherboard + +# 2006-05-30, Hans de Goede + +# Comments welcome! + + + +chip "it87-*" + + + +# Voltage monitors as advised in the It8705 data sheet + + + + label in0 "VCore" + + label in1 "+2.5V" + + label in2 "+3.3V" + + label in8 "VBat" + + # 5, 12, -5, -12 and standby do not seem to be connected + + ignore in3 + + ignore in4 + + ignore in5 + + ignore in6 + + ignore in7 + + # The It8705 doesn't monitor vid + + ignore vid + + + + # in0 will depend on your processor VID value, set to voltage specified in + + # bios + + set in0_min 1.4 * 0.95 + + set in0_max 1.4 * 1.05 + + set in1_min 2.4 + + set in1_max 2.6 + + set in2_min 3.3 * 0.95 + + set in2_max 3.3 * 1.05 + + #the chip does not support in8 min/max + + + +# Temperature + + + + label temp2 "CPU Temp" + + set temp2_over 50 + + set temp2_low 15 + + label temp3 "PWM Temp?" + + set temp3_over 65 + + set temp3_low 15 + + # temp1 does not seem to be connected + + ignore temp1 + + + +# Fans + + label fan1 "CPU fan" + + label fan2 "SYS fan" + + set fan1_min 3000 + + # The system fan is not always connected + + set fan2_min 0 + + ignore fan3 diff --git a/configs/Sapphire/PureFusionMiniE350.conf b/configs/Sapphire/PureFusionMiniE350.conf new file mode 100644 index 0000000..cbcc70e --- /dev/null +++ b/configs/Sapphire/PureFusionMiniE350.conf @@ -0,0 +1,31 @@ +# Contributed by tux99. + + +chip "f71808e-*" + + label in0 "VCC +3.3V" + # E-350 Vcore range is ~ 0.5V-1.35V (lowest idle state to max load) + label in1 "CPU Vcore" + ignore in2 + label in3 "DDR3 VDIMM" + label in4 "FCH +1.1V" + label in5 "PCIe +1.8V" + label in7 "3VSB +3.3V" + label in8 "VBAT +3.0V" + + compute in0 @*2, @/2 + compute in3 (@ * 1.465), (@ / 1.465) + compute in7 @*2, @/2 + compute in8 @*2, @/2 + + label fan1 "CPU Fan" + label fan2 "SYS Fan" + + ignore fan3 + + label temp1 "SYS Temp1" + label temp2 "SYS Temp2" + +chip "k10temp-*" + + label temp1 "CPU Temp" diff --git a/configs/Shuttle/XPC-SG33G5M-Deluxe.conf b/configs/Shuttle/XPC-SG33G5M-Deluxe.conf new file mode 100644 index 0000000..ff354d3 --- /dev/null +++ b/configs/Shuttle/XPC-SG33G5M-Deluxe.conf @@ -0,0 +1,57 @@ +# lm_sensors 3 configuration file for the "Shuttle XPC SG33G5M Deluxe" +# 2008-09-26, Matthieu Crapet +# Comments welcome! + + +## +# Chip 'ITE IT8718F Super IO Sensors' (it87.ko) +## +chip "it8718-*" + +# +# Voltages (cpu0_vid, in0, ..., in8) +# +set in2_min 3.3 * 0.95 +set in2_max 3.3 * 1.05 +set in3_min 5 * 0.95 +set in3_max 5 * 1.05 +set in4_min 12 * 0.95 +set in4_max 12 * 1.05 +set in7_min 5 * 0.95 +set in7_max 5 * 1.05 + +label in0 "CPU voltage" +label in1 "Chipset voltage" +label in2 "+3.3V" +label in3 "+5V" +label in4 "+12V" +label in6 "DDR2 voltage" +label in7 "+5VSB" +label in8 "Battery voltage" + +ignore in5 +compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) +compute in4 ((30/10)+1)*@ , @/((30/10)+1) +compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# +# Fans (fan1, fan2, fan3) +# +set fan1_min 700 +label fan1 "System Fan" + +ignore fan2 +ignore fan3 + +# +# Temperature (temp1, temp2, temp3) +# +set temp1_max 60 +set temp1_min 15 +label temp1 "CPU Temp" + +set temp2_max 65 +set temp2_min 15 +label temp2 "M/B Temp" + +ignore temp3 diff --git a/configs/SuperMicro/C2SBE.conf b/configs/SuperMicro/C2SBE.conf new file mode 100644 index 0000000..fa609d1 --- /dev/null +++ b/configs/SuperMicro/C2SBE.conf @@ -0,0 +1,92 @@ +# Example configuration for the SuperMicro C2SBE. +# Contributed by Romain Dolbeau. + +# The C2SBA is similar to the C2SBE (only with video on-board). + + +# settings for the supermicro C2SBE +# Originally written by Romain Dolbeau +# Uses at your own risk ! +# +# Here's the info as supplied by Supermicro: +# +# Bus Type = ISAIO +# One W83627DHG +# +# Windbond W83627DHG, IndexReg=295, DataReg=296 +# ============================================================= +# Fan1/CPU Fan Speed, Bank 0, Offset 0x29 RPM = 1350000/8/Data +# Fan2 Fan Speed, Bank 5, Offset 0x53 RPM = 1350000/8/Data +# Fan3 Fan Speed, Bank 0, Offset 0x28 RPM = 1350000/8/Data +# Fan4 Fan Speed, Bank 0, Offset 0x3f RPM = 1350000/8/Data +# Fan5 Fan Speed, Bank 0, Offset 0x2a RPM = 1350000/8/Data +# CPU Voltage, Bank 0, Offset 0x20 Voltage = Data* 0.008 +# -12V Voltage, Bank 0, Offset 0x26 Voltage =((Data*0.008-2.048)/(10./242.))+2.048 +# +12V Voltage, Bank 0, Offset 0x21 Voltage = Data* 0.008/(10./160.) +# +3.3V Voltage, Bank 0, Offset 0x22 Voltage = Data* 0.016 +# DIMM Voltage, Bank 0, Offset 0x24 Voltage = Data* 0.008 +# +5V Voltage, Bank 0, Offset 0x25 Voltage = Data* 0.008/(10./40.) +# +3.3VSb Voltage, Bank 5, Offset 0x50 Voltage = Data* 0.016 +# Battery Voltage, Bank 5, Offset 0x51 Voltage = Data* 0.016 +# CPU Temperature, Bank 1, Offset 0x50 Temperature = Data +# System Temperature, Bank 0, Offset 0x27 Temperature = Data +# Chassis Intrusion, Bank 0, Offset 0x42, BitMask 0x10 1 = Bad, 0 = Good +# (Clear Bit: Bank 0, Offset 0x46, BitMask 0x80) + +chip "w83627dhg-*" +# Voltages ; note that in the table above, the .008 and .016 factors are +# already computed in the driver... + label in0 "VCore" + label in1 "+12V" + label in2 "+3.3V" + ignore in3 + label in4 "DIMM Voltage" + label in5 "+5V" + label in6 "-12V" + label in7 "+3.3VSB" + label in8 "VBAT" + +# CPU Voltage limits are probably CPU-dependant + compute in0 @, @ + set in0_min 1.0 + set in0_max 1.4 + compute in1 @*16, @/16 + set in1_min 12*0.95 + set in1_max 12*1.05 + compute in2 @, @ + set in2_min 3.3*0.95 + set in2_max 3.3*1.05 +# compute in3 @, @ +# DIMM Voltage limits ??? + compute in4 @, @ + set in4_min 1.8*0.95 + set in4_max 1.8*1.05 + compute in5 @*4, @/4 + set in5_min 5*0.95 + set in5_max 5*1.05 + compute in6 ((@-2.048)*24.2)+2.048, ((@-2.048)/24.2)+2.048 + set in6_min -12*1.05 + set in6_max -12*0.95 + compute in7 @, @ + set in7_min 3.3*0.95 + set in7_max 3.3*1.05 +# VBAT Voltage limits ??? + compute in8 @, @ + set in8_min 3*0.9 + set in8_max 3*1.1 + +# Fans ; default in the driver is fine +# you should ignore the unplugged ones + label fan1 "Fan 3" + label fan2 "Fan1/CPU Fan" + label fan3 "Fan 5" + label fan4 "Fan 4" + label fan5 "Fan 2" + +# Temperatures +# Min and Max are environment-dependant + label temp1 "System Temp" + set temp1_max 45 + label temp2 "CPU Temp" + set temp2_max 65 + ignore temp3 diff --git a/configs/SuperMicro/C7H61.conf b/configs/SuperMicro/C7H61.conf new file mode 100644 index 0000000..fc9eee4 --- /dev/null +++ b/configs/SuperMicro/C7H61.conf @@ -0,0 +1,73 @@ +# +# Libsensors configuration for SuperMicro C7H61-O and C7H61-L boards. +# +# C7H61-L has a single nct6776 sensor chip. +# C7H61-O has two sensor chips, nct6776 and nct6106. nct6106 is not used +# for temperature, fans or voltage sensing. Hardware monitoring for this +# chip is not enabled, and you should not enable it. +# BIOS allows one to set nct6776 parameters, such as voltage or PWM fan +# control and default strategy. +# + +chip "nct6776-isa-0a30" + + label in0 "Vcore" + label in1 "+12V" + label in2 "AVCC" + label in3 "+3.3V" + label in4 "VDIMM" + label in5 "+5V" + label in6 "VTT_CPU" + label in7 "3VSB" + label in8 "Vbat" + + compute in1 @*6.6, @/6.6 + compute in5 @*4, @/4 + + # min/max values are set by the BIOS + + ignore fan1 + label fan2 "System FAN4" + label fan3 "CPU Fan" + label fan4 "System FAN2" + label fan5 "System FAN3" + + ignore temp7 + ignore temp8 + ignore temp9 + ignore temp10 + + ignore intrusion1 + + +chip "nct6106-*" + + ignore in0 + ignore in1 + label in2 "AVCC" + label in3 "+3.3V" + ignore in4 + ignore in5 + ignore in6 + label in7 "Vbat" + ignore in8 + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 3.3 * 0.90 + set in3_max 3.3 * 1.10 + set in7_min 3.3 * 0.90 + set in7_max 3.3 * 1.10 + + ignore fan1 + ignore fan2 + ignore fan3 + + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp7 + ignore temp8 + ignore temp9 + + ignore intrusion0 diff --git a/configs/SuperMicro/C7X58.conf b/configs/SuperMicro/C7X58.conf new file mode 100644 index 0000000..029ce15 --- /dev/null +++ b/configs/SuperMicro/C7X58.conf @@ -0,0 +1,66 @@ +# Contributed by Henrique de Moraes Holschuh. + +# Also compatible with X8SAX. + + +# +# Libsensors configuration for SuperMicro C7X58 and X8SAX boards, revision 1.1 or 2.0 +# Scaling factors kindly provided by SuperMicro support. +# +# Board has two sensor chips, w83627dhg is not used for temperature, +# fans or voltage sensing. sensors-detect will suggest that you load the +# w83627ehf driver but you shouldn't. +# BIOS allows one to set w83795adg parameters, such as voltage or PWM fan +# control and default strategy. +# + +chip "w83795adg-*" + + label fan1 "CPU Fan" + + label in0 "CPU Core" + label in2 "DIMM" + label in3 "+5V" + label in4 "+12V" + label in5 "-12V" + label in11 "VTT" + label in12 "+3.3V" + label in13 "+3.3Vsb" + label in14 "Vbatt" + + # The BIOS does not set the correct limits for VTT, but it is wired. + # Default to broad limits used on Asus boards, feel free to refine for your CPU. + set in11_min 0.770 + set in11_max 1.538 + + label temp6 "System temperature" + label temp7 "CPU temperature" + + compute in3 @*4, @/4 + compute in4 @*6.62, @/6.62 + compute in5 (@-2.048)*24.2 + 2.048, (@-2.048)/24.2 + 2.048 + +chip "w83627dhg-*" + +# SuperIO chip used only for the FDC, UARTs and GPIO +# SENSORS ARE NOT WIRED +# Power Supply Failure, GP31(From W83627DHG-P) 1 = Good, 0 = Bad + + ignore fan1 + ignore fan2 + ignore fan3 + ignore fan4 + ignore fan5 + ignore temp1 + ignore temp2 + ignore temp3 + ignore in0 + ignore in1 + ignore in2 + ignore in3 + ignore in4 + ignore in5 + ignore in6 + ignore in7 + ignore in8 + ignore cpu0_vid diff --git a/configs/SuperMicro/DLE370.conf b/configs/SuperMicro/DLE370.conf new file mode 100644 index 0000000..d268194 --- /dev/null +++ b/configs/SuperMicro/DLE370.conf @@ -0,0 +1,55 @@ +# lm_sensors 3 configuration file for the Supermicro DLE370 motherboard +# 2007-09-26, Jean Delvare +# Comments welcome! + +chip "lm87-*" + +### Voltages + + label in1 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + + # All voltage inputs are scaled internally, so the driver itself + # takes care of it. + + set in1_min cpu0_vid - 0.08 + set in1_max cpu0_vid + 0.08 + set in2_min 3.3 * 0.95 + set in2_max 3.3 * 1.05 + set in3_min 5 * 0.95 + set in3_max 5 * 1.05 + set in4_min 12 * 0.95 + set in4_max 12 * 1.05 + +### Fans + + label fan1 "CPU0 Fan" + label fan2 "CPU1 Fan" + + set fan1_div 4 + set fan2_div 4 + + set fan1_min 1800 + set fan2_min 1800 + + # Unfortunately, the analog output appears not to be wired to anything + # so there is no way to control the fan speeds. + +### Temperatures + + label temp1 "Sys Temp" + label temp2 "CPU0 Temp" + label temp3 "CPU1 Temp" + + # The BIOS will set the temperature limits to reasonable values, so + # you can leave them as is. I tend to prefer more restrictive settings + # though. + + set temp1_min 5 + set temp1_max 48 + set temp2_min 5 + set temp2_max 56 + set temp3_min 5 + set temp3_max 56 diff --git a/configs/SuperMicro/H8DC8.conf b/configs/SuperMicro/H8DC8.conf new file mode 100644 index 0000000..e824133 --- /dev/null +++ b/configs/SuperMicro/H8DC8.conf @@ -0,0 +1,138 @@ +# Example configuration for the SuperMicro H8DC8. +# Contributed by Romain Dolbeau. + + +# settings for the supermicro H8DC8 +# here are the details supplied by the technical support: +##Bus Type = SMBus +##One WindBond W83627HF, One Analog Devices ADM1026 +## +##Analog Devices ADM1026, Slave Address=0x2c (0x58 in 8-Bit format) +##============================================================== +##Fan1 Fan Speed, Offset 0x38 RPM=1350000/8/Reading +##Fan2 Fan Speed, Offset 0x39 RPM=1350000/8/Reading +##Fan3 Fan Speed, Offset 0x3a RPM=1350000/8/Reading +##Fan4 Fan Speed, Offset 0x3b RPM=1350000/8/Reading +##Fan5 Fan Speed, Offset 0x3c RPM=1350000/8/Reading +##Fan6 Fan Speed, Offset 0x3d RPM=1350000/8/Reading +##Fan7 Fan Speed, Offset 0x3e RPM=1350000/8/Reading +##Fan8 Fan Speed, Offset 0x3f RPM=1350000/8/Reading +##CPU1 Core Voltage, Offset 0x2d Voltage=(Reading * 3)/256 +##CPU2 Core Voltage, Offset 0x37 Voltage=(Reading * 2.5)/256 +##+5VSB Voltage, offset 0x30 Voltage=(Reading * 6)/256 +##+1.5V Voltage, offset 0x32 Voltage=(Reading * 3)/256 +##+5V Voltage, offset 0x2c Voltage=(Reading * 6.66)/256 +##+12V Voltage, offset 0x2e Voltage=(Reading * 16)/256 +##-12V Voltage, offset 0x2f Voltage=((Reading* 18.5)/256)-16 +##DIMM Voltage, offset 0x33 Voltage=(Reading * 3)/256 +##Battery Voltage, Offset 0x26 +##Voltage=(((Reading-128)*2)/128)+2) +##System Temperature, Offset 0x1f C=Reading +##CPU1 Temperature, Offset 0x28 C=Reading +##CPU2 Temperature, Offset 0x29 C=Reading +##Chassis Intrusion, Offset 0x23, BitMask=40 +## +## +##Power Supply Failure (From W82627HF), GP12 +# +# Notes: +# 1) no section for the W82627HF yet. +# 2) the temperature min/max are ballpark estimate, +# you may need to fix them depening on your environment +# such as the setting of your air conditionner. +# 3) According to the support, in11 and in12 (both +3.3V +# lines) aren't hooked up, yet they supply proper readings +# (as specified by the manufacturer of the chip for those +# lines). +# You may want to disable them. +# +# Originally written by Romain Dolbeau +# Uses at your own risk ! + +chip "adm1026-i2c-*-2c" + + label fan0 "FAN0 Speed" + label fan1 "FAN1 Speed" + label fan2 "FAN2 Speed" + label fan3 "FAN3 Speed" + label fan4 "FAN4 Speed" + label fan5 "FAN5 Speed" + label fan6 "FAN6 Speed" + label fan7 "FAN7 Speed" + + set fan0_div 8 + set fan1_div 8 + set fan2_div 8 + set fan3_div 8 + set fan4_div 8 + set fan5_div 8 + set fan6_div 8 + set fan7_div 8 + + label in0 "+5VSB Voltage" + compute in0 @*2,@/2 + set in0_min 5*0.90 + set in0_max 5*1.1 + + ignore in1 + + label in2 "+1.5V Voltage" + set in2_min 1.5*0.95 + set in2_max 1.5*1.05 + + label in3 "DIMM Voltage" + set in3_min 2.5*0.95 + set in3_max 2.5*1.05 + + ignore in4 + ignore in5 + ignore in6 + + label in7 "CPU2 Core Voltage" + set in7_min 1.35*0.95 + set in7_max 1.35*1.05 + + ignore in8 + ignore in9 + + label in10 "Battery Voltage" + set in10_min 3*0.95 + set in10_max 3*1.05 + + # for in11 & in12, see comments above + #ignore in11 + #ignore in12 + + label in11 "3.3V Standby" + set in11_min 3.3*0.95 + set in11_max 3.3*1.05 + + label in12 "3.3V Main" + set in12_min 3.3*0.95 + set in12_max 3.3*1.05 + + label in13 "+5V Voltage" + set in13_min 5*0.95 + set in13_max 5*1.05 + + label in14 "CPU1 Core Voltage" + set in14_min 1.35*0.95 + set in14_max 1.35*1.05 + + label in15 "+12V Voltage" + set in15_min 12*0.95 + set in15_max 12*1.05 + + label in16 "-12V Voltage" + set in16_max -12*0.95 + set in16_min -12*1.05 + + label temp1 "System Temperature" + set temp1_min 18 + set temp1_max 40 + label temp2 "CPU1 Temperature" + set temp2_min 20 + set temp2_max 45 + label temp3 "CPU2 Temperature" + set temp3_min 20 + set temp3_max 45 diff --git a/configs/SuperMicro/H8QM3.conf b/configs/SuperMicro/H8QM3.conf new file mode 100644 index 0000000..dafec2e --- /dev/null +++ b/configs/SuperMicro/H8QM3.conf @@ -0,0 +1,30 @@ +# Sensors-detect will suggest loading the w83627hf driver, but don't, it's +# useless on this board. + + +chip "w83793-i2c-*-2f" + + # Voltages + label in0 "Vcore1" + label in1 "Vcore2" + ignore in2 + label in3 "Vcore4" + label in4 "Vcore3" + label in5 "+3.3V" + label in6 "+12V" + + compute in6 @*12, @/12 + + # Fans + label fan3 "CPU2 Fan" + label fan4 "CPU1 Fan" + label fan7 "CPU4 Fan" + label fan8 "CPU3 Fan" + + # Temperatures + label temp1 "CPU1 Temp" + label temp2 "CPU2 Temp" + label temp3 "CPU4 Temp" + label temp4 "CPU3 Temp" + label temp5 "Sys Temp" + # Not sure about temp6 diff --git a/configs/SuperMicro/PDSMi+.conf b/configs/SuperMicro/PDSMi+.conf new file mode 100644 index 0000000..f64c3cf --- /dev/null +++ b/configs/SuperMicro/PDSMi+.conf @@ -0,0 +1,82 @@ +# Example configuration for the SuperMicro PDSMi+. +# Contributed by Romain Dolbeau & Jean Delvare + + +# settings for the supermicro PDSMi+ +# +# Notes: +# 1) You need lm-sensors >= 2.10.2, otherwise you get an error about +# missing temp6. +# +# Originally written by Romain Dolbeau +# Uses at your own risk ! +chip "w83793-i2c-*-2f" + +# 0x10, CPU Core + label in0 "CPU Core" +# 0x11, unconnected according to support, 1.5V in BIOS ? + label in1 "+1.5V" + set in1_min 1.5*0.95 + set in1_max 1.5*1.05 +# 0x12, unconnected according to support, VTT=1.2V in BIOS ? + label in2 "VTT" + set in2_min 1.2*0.95 + set in2_max 1.2*1.05 +# 0x14, -12V + label in3 "-12V" +# From Supermicro support information... +# compute in3 (((@/8)*18500)/256)-16, (((@+16)*256)/18500)*8 +# ... but this from Jean Delvare works better in pratice + compute in3 (@ * 5.14) - 14.91, (@ + 14.91) / 5.14 + set in3_min -12*1.05 + set in3_max -12*0.95 +# 0x15, DIMM + label in4 "DIMM" +# 0x16, +3.3V + label in5 "+3.3V" + set in5_min 3.3*0.95 + set in5_max 3.3*1.05 +# 0x17, +12V + label in6 "+12V" + compute in6 @*12,@/12 + set in6_min 12*0.95 + set in6_max 12*1.05 +# Ox18, +5V + label in7 "+5V" + compute in7 @-0.15,@+0.15 + set in7_min 5*0.95 + set in7_max 5*1.05 +# 0x19, 5VSB + label in8 "5VSB" + compute in8 @-0.15,@+0.15 + set in8_min 5*0.95 + set in8_max 5*1.05 +# 0x1a, Battery Voltage + label in9 "VBAT" + + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + ignore temp4 +# System Temp used to live at temp5, but was moved to temp6 for some reason + ignore temp5 +# label temp5 "System Temp" +# ignore temp6 + label temp6 "System Temp" + +# 6 connected + label fan1 "fan1" + label fan2 "fan2" + label fan3 "fan3" + label fan4 "fan4" + label fan5 "fan5" +# apparently, fan6 is skipped and fan7 is used instead for CPU fan, +# at least that's how I understand Supermicro data. + ignore fan6 + label fan7 "CPU fan" + ignore fan8 + ignore fan9 + ignore fan10 + ignore fan12 + ignore fan12 +# you should ignore the last 3 or 4, in 1U rackmount system diff --git a/configs/SuperMicro/X6DH8-XG2.conf b/configs/SuperMicro/X6DH8-XG2.conf new file mode 100644 index 0000000..03c36bb --- /dev/null +++ b/configs/SuperMicro/X6DH8-XG2.conf @@ -0,0 +1,30 @@ +# Partial and untested configuration file for the SuperMicro X6DH8-XG2. +# Please report if you try it. + + +chip "pc87427-*" + + label fan7 "CPU1 Fan" + label fan8 "CPU2 Fan" + +chip "lm93-*" + + ignore fan1 + ignore fan2 + ignore fan3 + ignore fan4 + + label in1 "+12V" + label in7 "VCore1" + label in8 "VCore2" + label in9 "+3.3V" + label in10 "+5V" + ignore in11 + label in15 "-12V" + + compute in1 @ * ((13.7/1.15)+1), @ / ((13.7/1.15)+1) + compute in15 @ * 5.1138 - 13.5771, (@ + 13.5771) / 5.1138 + + label temp1 "CPU1 Temp" + label temp2 "CPU2 Temp" + label temp3 "Sys Temp" diff --git a/configs/SuperMicro/X7DB8.conf b/configs/SuperMicro/X7DB8.conf new file mode 100644 index 0000000..782ba97 --- /dev/null +++ b/configs/SuperMicro/X7DB8.conf @@ -0,0 +1,121 @@ +# Originally contributed by Gary E. Miller, cleaned up by Jean Delvare. + + +# /etc/sensors.d/X7DB8 +# settings for the supermicro X7DB8 +# originally written by Gary E. Miller +# use at your own risk ! +# Date: 30 May 2012 + +# Here's the info as supplied by Supermicro: +# +# Bus Type = SMBus +# One W83793G +# +# Windbond W83793G, Slave Address=0x2f (0x5E in 8-Bit format) +# ============================================================= +# Fan1 Fan Speed, Offset 0x23, 0x24 RPM = 1350000/Data +# Fan2 Fan Speed, Offset 0x25, 0x26 RPM = 1350000/Data +# Fan3 Fan Speed, Offset 0x27, 0x28 RPM = 1350000/Data +# Fan4 Fan Speed, Offset 0x29, 0x2a RPM = 1350000/Data +# Fan5 Fan Speed, Offset 0x2b, 0x2c RPM = 1350000/Data +# Fan6 Fan Speed, Offset 0x2d, 0x2e RPM = 1350000/Data +# Fan7/CPU1 Fan Speed, Offset 0x2f, 0x30 RPM = 1350000/Data +# Fan8/CPU2 Fan Speed, Offset 0x31, 0x32 RPM = 1350000/Data +# CPU1 Core Voltage, Offset 0x10 Voltage = Data* 0.008 +# CPU2 Core Voltage, Offset 0x11 Voltage = Data* 0.008 +# -12V Voltage, Offset 0x14 Voltage = ((Data*0.016)- (2.048*(232./260.)))/(1-(232./260.)) +# +1.5V Voltage, Offset 0x15 Voltage = Data* 0.016 +# +3.3V Voltage, Offset 0x16 Voltage = Data* 0.016 +# +12V Voltage, Offset 0x17 Voltage = Data* 0.008/ (10./120.) +# +5V Voltage, Offset 0x18 Voltage = Data* 0.024 +# 5Vsb Voltage, Offset 0x19 Voltage = Data* 0.024 +# Battery Voltage, Offset 0x1a Voltage = Data* 0.016 +# CPU1 CoreA (PECI Agent1) Temperature, Offset 0x1c Temperature = Data +# CPU1 CoreB (PECI Agent2) Temperature, Offset 0x1d Temperature = Data +# CPU2 CoreA (PECI Agent3) Temperature, Offset 0x1e Temperature = Data +# CPU2 CoreB (PECI Agent4) Temperature, Offset 0x1f Temperature = Data +# System Temperature, Offset 0x20 Temperature = Data +# Chassis Intrusion, Offset 0x44, BitMask 0x40 1 = Bad, 0 = Good +# +# +# Windbond W83627HF +# ============================================================= +# Power Supply Failure, GP11(From W83627HF) 1 = Good, 0 = Bad +# + +chip "w83627hf-isa-0290" + # no driver access to GP11, so I turned off everything. + ignore in0 + ignore in1 + ignore in2 + ignore in3 + ignore in4 + ignore in5 + ignore in6 + ignore in7 + ignore in8 + ignore cpu0_vid + ignore fan1 + ignore fan2 + ignore fan3 + ignore temp1 + ignore temp2 + ignore temp3 + + + +bus "i2c-0" "SMBus I801 adapter at 1100" + +chip "w83793-i2c-0-2f" + + label fan7 "CPU1 Fan" + label fan8 "CPU2 Fan" + +# Voltages ; note that in the table above, the .008, .016, and .024 factors are +# already computed in the driver... + label in0 "Vcore1" + label in1 "Vcore2" + ignore in2 + label in3 "-12V" + label in4 "+1.5V" + label in5 "+3.3V" + label in6 "+12V" + label in7 "+5V" + label in8 "5Vsb" + label in9 "Vbat" + + label temp1 "CPU1 CoreA" + label temp2 "CPU1 CoreB" + label temp3 "CPU2 CoreA" + label temp4 "CPU2 CoreB" + label temp5 "M/B Temp" + + compute in3 (@ - (2.048*(232/260)))/(1-(232/260)), (@*(1-(232/260)))+(2.048*(232/260)) + compute in6 @ * 12 , @ / 12 + + + # CPUs + set in0_min 0.82 + set in0_max 1.35 + set in1_min 0.82 + set in1_max 1.35 + + # -12V, 10% + set in3_max -12.0 * 0.90 + set in3_min -12.0 * 1.10 + # +3.3V, 5% + set in5_min 3.3 * 0.95 + set in5_max 3.3 * 1.05 + # +12V, 5% + set in6_min 12.0 * 0.95 + set in6_max 12.0 * 1.05 + # +5V, 5% + set in7_min 5.0 * 0.95 + set in7_max 5.0 * 1.05 + # 5Vsb, 10% + set in8_min 5.0 * 0.90 + set in8_max 5.0 * 1.10 + # Vbat, 10% + set in9_min 3.0 * 0.90 + set in9_max 3.0 * 1.10 diff --git a/configs/SuperMicro/X7DBE.conf b/configs/SuperMicro/X7DBE.conf new file mode 100644 index 0000000..2e970ca --- /dev/null +++ b/configs/SuperMicro/X7DBE.conf @@ -0,0 +1,65 @@ +# settings for the SuperMicro X7DBE +# +# Notes: +# 1) You need lm-sensors >= 2.10.2, otherwise you get an error about +# missing temp6. +# +# Originally written by Romain Dolbeau +# Use at your own risk! + +chip "w83793-i2c-*-2f" + +# 0x10, CPU Core 1 + label in0 "CPU Core 1" +# 0x11, CPU Core 2 + label in1 "CPU Core 2" +# 0x12 VTT=1.2V in BIOS ? + label in2 "VTT" + set in2_min 1.2*0.95 + set in2_max 1.2*1.05 +# 0x14, -12V + label in3 "-12V" + compute in3 (((@/8)*18500)/256)-16, (((@+16)*256)/18500)*8 + set in3_min -12*1.05 + set in3_max -12*0.95 +# 0x15, DIMM + label in4 "P1V5" +# 0x16, +3.3V + label in5 "+3.3V" + set in5_min 3.3*0.95 + set in5_max 3.3*1.05 +# 0x17, +12V + label in6 "+12V" + compute in6 @*12,@/12 + set in6_min 12*0.95 + set in6_max 12*1.05 +# Ox18, +5V + label in7 "+5V" + set in7_min 5*0.95 + set in7_max 5*1.05 +# 0x19, 5VSB + label in8 "5VSB" + set in8_min 5*0.95 + set in8_max 5*1.05 +# 0x1a, Battery Voltage + label in9 "VBAT" + + label temp1 "CPU1 Temp" + label temp2 "CPU2 Temp" + ignore temp3 + ignore temp4 + label temp5 "System Temp" + ignore temp6 + + label fan1 "fan1" + label fan2 "fan2" + label fan3 "fan3" + label fan4 "fan4" + ignore fan5 + ignore fan6 + label fan7 "CPU1 fan" + label fan8 "CPU2 fan" + ignore fan9 + ignore fan10 + ignore fan11 + ignore fan12 diff --git a/configs/SuperMicro/X7SBU.conf b/configs/SuperMicro/X7SBU.conf new file mode 100644 index 0000000..58e3697 --- /dev/null +++ b/configs/SuperMicro/X7SBU.conf @@ -0,0 +1,108 @@ +# Example configuration for the SuperMicro X7SBU. Contributed by Joe Ogulin. + +# Monitoring hardware on this board: Winbond W83793G on ICH9 SMBus (driver +# w83793) and integrated sensors in the CPU (driver coretemp). A few voltages +# also available from the Winbond W83627HF Super-I/O chip. + + +# settings for the supermicro X7SBU +# +chip "w83793-*" + +# 0x10, CPU Core + label in0 "CPU Core" +# 0x11, unconnected according to support, 1.5V in BIOS ? + label in1 "+1.25V" + set in1_min 1.25*0.95 + set in1_max 1.25*1.05 +# 0x12, unconnected according to support, VTT=1.2V in BIOS ? + label in2 "VTT" +# 0x14, -12V + label in3 "-12V" +# From Supermicro support information... +# compute in3 (((@/8)*18500)/256)-16, (((@+16)*256)/18500)*8 +# ... but this from Jean Delvare works better in pratice + compute in3 (@ * 5.14) - 14.91, (@ + 14.91) / 5.14 + set in3_min -12*1.05 + set in3_max -12*0.95 +# 0x15, DIMM + label in4 "DIMM" +# 0x16, +3.3V + label in5 "+3.3V" + set in5_min 3.3*0.95 + set in5_max 3.3*1.05 +# 0x17, +12V + label in6 "+12V" + compute in6 @*12,@/12 + set in6_min 12*0.95 + set in6_max 12*1.05 +# Ox18, +5V + label in7 "+5V" + compute in7 @-0.15,@+0.15 + set in7_min 5*0.95 + set in7_max 5*1.05 +# 0x19, 5VSB + label in8 "5VSB" + compute in8 @-0.15,@+0.15 + set in8_min 5*0.95 + set in8_max 5*1.05 +# 0x1a, Battery Voltage + label in9 "VBAT" + + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + ignore temp4 + label temp5 "Sys Temp" + ignore temp6 + +# 3 connected +# note that these fan labels are for a 1U rackmount and are given their +# positions based on where they are when you look at it from the front +# towards the back +# +# relabel them as necessary to however you have them set up + label fan1 "Right Fan" + label fan2 "Mid-right Fan" + label fan3 "Middle Fan" + ignore fan4 + ignore fan5 + ignore fan6 + ignore fan7 + ignore fan8 + ignore fan9 + ignore fan10 + ignore fan12 + ignore fan12 + # Override CPU temperature threshold + set temp1_max 80 + set temp1_max_hyst 70 + + set temp5_max 60 + set temp5_max_hyst 55 + +# NOTE: nearly everything on this chip is not used you can turn on alarms, if +# you have the appropriate setup for it and want to have chassis intrusion +# detection turned on + +chip "w83627hf-*" + + ignore in0 + ignore in1 + ignore in2 + label in3 "+5.0V" + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + set in3_min 5*0.95 + set in3_max 5*1.05 + ignore in4 + ignore in5 + ignore in6 + ignore in7 + ignore in8 + ignore fan1 + ignore fan2 + ignore fan3 + ignore alarms + ignore temp1 + ignore temp2 + ignore temp3 diff --git a/configs/SuperMicro/X7SBi.conf b/configs/SuperMicro/X7SBi.conf new file mode 100644 index 0000000..e82f3d6 --- /dev/null +++ b/configs/SuperMicro/X7SBi.conf @@ -0,0 +1,108 @@ +# Example configuration for the SuperMicro X7SBi. Contributed by Joe Ogulin. + +# Monitoring hardware on this board: Winbond W83793G on ICH9 SMBus (driver +# w83793) and integrated sensors in the CPU (driver coretemp). A few voltages +# also available from the Winbond W83627HF Super-I/O chip. + + +# settings for the supermicro X7SBi +# +chip "w83793-*" + +# 0x10, CPU Core + label in0 "CPU Core" +# 0x11, unconnected according to support, 1.5V in BIOS ? + label in1 "+1.5V" + set in1_min 1.5*0.95 + set in1_max 1.5*1.05 +# 0x12, unconnected according to support, VTT=1.2V in BIOS ? + label in2 "VTT" + set in2_min 1.2*0.95 + set in2_max 1.2*1.05 +# 0x14, -12V + label in3 "-12V" +# From Supermicro support information... +# compute in3 (((@/8)*18500)/256)-16, (((@+16)*256)/18500)*8 +# ... but this from Jean Delvare works better in pratice + compute in3 (@ * 5.14) - 14.91, (@ + 14.91) / 5.14 + set in3_min -12*1.05 + set in3_max -12*0.95 +# 0x15, DIMM + label in4 "DIMM" +# 0x16, +3.3V + label in5 "+3.3V" + set in5_min 3.3*0.95 + set in5_max 3.3*1.05 +# 0x17, +12V + label in6 "+12V" + compute in6 @*12,@/12 + set in6_min 12*0.95 + set in6_max 12*1.05 +# Ox18, +5V + label in7 "+5V" + compute in7 @-0.15,@+0.15 + set in7_min 5*0.95 + set in7_max 5*1.05 +# 0x19, 5VSB + label in8 "5VSB" + compute in8 @-0.15,@+0.15 + set in8_min 5*0.95 + set in8_max 5*1.05 +# 0x1a, Battery Voltage + label in9 "VBAT" + + label temp1 "CPU Temp" + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + label temp6 "Sys Temp" + +# 3 connected +# note that these fan labels are for a 1U rackmount and are given their +# positions based on where they are when you look at it from the front +# towards the back +# +# relabel them as necessary to however you have them set up + label fan1 "Right Fan" + ignore fan2 + ignore fan3 + ignore fan4 + label fan5 "Mid-right Fan" + ignore fan6 + label fan7 "Middle Fan" + ignore fan8 + ignore fan9 + ignore fan10 + ignore fan12 + ignore fan12 + # Override CPU temperature threshold + set temp1_max 80 + set temp1_max_hyst 70 + + set temp6_max 60 + set temp6_max_hyst 55 + +# NOTE: nearly everything on this chip is not used you can turn on alarms, if +# you have the appropriate setup for it and want to have chassis intrusion +# detection turned on + +chip "w83627hf-*" + + ignore in0 + ignore in1 + ignore in2 + label in3 "+5.0V" + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + ignore in4 + ignore in5 + ignore in6 + ignore in7 + ignore in8 + ignore fan1 + ignore fan2 + ignore fan3 + ignore alarms + ignore temp1 + ignore temp2 + ignore temp3 diff --git a/configs/SuperMicro/X7SLA.conf b/configs/SuperMicro/X7SLA.conf new file mode 100644 index 0000000..b8d81cf --- /dev/null +++ b/configs/SuperMicro/X7SLA.conf @@ -0,0 +1,39 @@ +# Contributed by Jeff Rickman, fixes by Jean Delvare. + + +chip "w83627dhg-*" + + label in0 "Vcore" + label in1 "+12V" + label in2 "+3.3V" + label in3 "Vcc" + label in4 "Vdimm" + label in5 "+5V" + label in6 "+1.5V" + label in7 "3VSB" + label in8 "Vbat" + + label fan1 "Back Fan" + label fan2 "P/S Fan" + label fan5 "Front Fan" + label fan4 "MCH Fan" + + label temp1 "M/B Temp" + label temp2 "CPU Temp" + + ignore fan3 + ignore cpu0_vid + ignore temp3 + + # Scaling factor for +12V needs confirmation + compute in1 @*6.63, @/6.63 + compute in5 @*4, @/4 + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 3.3 * 0.90 + set in3_max 3.3 * 1.10 + set in7_min 3.3 * 0.90 + set in7_max 3.3 * 1.10 + set in8_min 3.0 * 0.90 + set in8_max 3.0 * 1.10 diff --git a/configs/SuperMicro/X7SPA.conf b/configs/SuperMicro/X7SPA.conf new file mode 100644 index 0000000..08a4478 --- /dev/null +++ b/configs/SuperMicro/X7SPA.conf @@ -0,0 +1,32 @@ +# Configuration file contributed by Scott Shanafelt. + + +chip "w83627dhg-*" + + label in0 "Vcore" + label in1 "+1.05V" + label in2 "AVCC" + label in3 "3VCC" + set in3_min 3.3 * 0.90 + set in3_max 3.3 * 1.10 + label in4 "Vdimm" + label in5 "+5V" + compute in5 @*4, @/4 + label in6 "+12V" + compute in6 @*16, @/16 + set in6_min 12 * 0.90 + set in6_max 12 * 1.10 + label in7 "3VSB" + label in8 "Vbat" + + ignore fan1 + label fan2 "CPU Fan" + ignore fan3 + label fan4 "Case Fan" + ignore fan5 + + label temp1 "MB Temp" + label temp2 "CPU Temp" + label temp3 "Case Temp" + + ignore cpu0_vid diff --git a/configs/SuperMicro/X8DTN.conf b/configs/SuperMicro/X8DTN.conf new file mode 100644 index 0000000..ee05234 --- /dev/null +++ b/configs/SuperMicro/X8DTN.conf @@ -0,0 +1,100 @@ +# /etc/sensors.d/X8DTN +# settings for the supermicro X8DTN +# originally written by Gary E. Miller +# use at your own risk ! +# Date: 25 May 2012 + +# Here's the info as supplied by Supermicro: + +# +# Bus Type = ISAIO/SMBus +# One W83795AG +# +# Windbond W83795AG, Slave Address=0x2f (0x5E in 8-Bit format) +# ============================================================= +# Fan1 Fan Speed, Offset 0x2e RPM = 84375/Data +# Fan2 Fan Speed, Offset 0x2f RPM = 84375/Data +# Fan3 Fan Speed, Offset 0x30 RPM = 84375/Data +# Fan4 Fan Speed, Offset 0x31 RPM = 84375/Data +# Fan5 Fan Speed, Offset 0x32 RPM = 84375/Data +# Fan6 Fan Speed, Offset 0x33 RPM = 84375/Data +# Fan7 Fan Speed, Offset 0x34 RPM = 84375/Data +# Fan8 Fan Speed, Offset 0x35 RPM = 84375/Data +# CPU1 Voltage, Offset 0x10 Voltage = Data* 0.008 +# CPU2 Voltage, Offset 0x11 Voltage = Data* 0.008 +# +1.5V Voltage, Offset 0x12 Voltage = Data* 0.008 +# +5V Voltage, Offset 0x13 Voltage = Data* 0.008 * (40/10) +# +12V Voltage, Offset 0x14 Voltage = Data* 0.008/ (10./66.2) +# +5VSB Voltage, Offset 0x15 Voltage = Data* 0.008 * (40/10) +# +3.3V Voltage, Offset 0x1c Voltage = Data* 0.024 +# +3.3VSB Voltage, Offset 0x1d Voltage = Data* 0.024 +# Battery Voltage, Offset 0x1e Voltage = Data* 0.024 +# CPU1 Temperature, Offset 0x27 Temperature = Data +# CPU2 Temperature, Offset 0x26 Temperature = Data +# System Temperature, Offset 0x1f Temperature = Data +# Chassis Intrusion, Bank 0, Offset 0x46, BitMask 0x40 1 = Bad, 0 = Good +# (Clear Bit: Bank 0, Offset 0x4d, BitMask 0x80) +# +# +# Power Supply Failure, GP11(From W83627HF) 1 = Good, 0 = Bad + +chip "w83627hf-isa-0a00" + # I'm not sure which is GP11, so I turned off everything. + ignore in0 + ignore in1 + ignore in2 + ignore in3 + ignore in4 + ignore in5 + ignore in6 + ignore in7 + ignore in8 + ignore cpu0_vid + ignore fan1 + ignore fan2 + ignore fan3 + ignore temp1 + ignore temp2 + ignore temp3 + +bus "i2c-0" "SMBus I801 adapter at 0400" + +chip "w83795adg-i2c-0-2f" + +# Voltages ; note that in the table above, the .008 and .024 factors are +# already computed in the driver... + + label in0 "CPU1" + label in1 "CPU2" + label in2 "+1.5V" + label in3 "+5V" + label in4 "+12V" + label in5 "5VSB" + label in12 "+3.3V" + label in13 "3VSB" + label in14 "Vbat" + + compute in3 @*4, @/4 + compute in4 @*6.62, @/6.62 + compute in5 @*4, @/4 + + label temp5 "mobo" + label temp7 "CPU2" + label temp8 "CPU1" + + ignore in6 + ignore in7 + ignore in11 + ignore temp3 + ignore temp4 + + set in0_min 0.82 + set in0_max 1.35 + set in1_min 0.82 + set in1_max 1.35 + set in12_min 3.3 * 0.90 + set in12_max 3.3 * 1.05 + set in13_min 3.3 * 0.95 + set in13_max 3.3 * 1.10 + set in14_min 3.0 * 0.90 + set in14_max 3.3 * 1.10 diff --git a/configs/SuperMicro/X9SRA.conf b/configs/SuperMicro/X9SRA.conf new file mode 100644 index 0000000..04d8c89 --- /dev/null +++ b/configs/SuperMicro/X9SRA.conf @@ -0,0 +1,56 @@ +# Configuration file contributed by Eric Wedel. + + +# Supermicro X9SRA motherboard lm-sensors configuration. +# Voltage inputs & scaling per Supermicro support. Other +# inputs from BIOS screen and observation. + +chip "nct6776-*" + +### Voltages + +label in0 "Vcore" + +label in1 "+12V" +compute in1 @ * (66.2/10), @ / (66.2/10) + +label in2 "AVcc" + +label in3 "+3.3V" + +label in4 "Vdimm" + +label in5 "+5V" +compute in5 @ * 4, @ / 4 + +label in6 "Vtt" + +label in7 "+3.3Vsb" + +label in8 "Vbatt" + +### Temperatures + +# not sure about temp1 / temp2 assignments + +label temp1 "System temperature" +label temp2 "Peripheral temperature" + +ignore temp3 + +# PECI agent 0: +label temp7 "CPU temperature" + +label temp8 "PCH temperature" + +ignore temp9 +ignore temp10 + +## fans: gratuitous renumbering between Supermicro & lm-sensors. +## Use display labels which match X9SRA fan connector labels. + +label fan1 "fanA" +label fan2 "fan1" +label fan3 "CPU Fan" +label fan4 "fan3" +label fan5 "Exhaust Fan" diff --git a/configs/Tyan/S2466-4M.conf b/configs/Tyan/S2466-4M.conf new file mode 100644 index 0000000..2690790 --- /dev/null +++ b/configs/Tyan/S2466-4M.conf @@ -0,0 +1,109 @@ +# Sensors configuration file used by 'libsensors' for Tyan S2466-4M +# +# Edited by: kevin schlichter 05.16.03 +# Update 07.30.03:kevin schlichter: add vid support +# Update 2009-Apr-01 Adam Thompson : radically +# updated for lm_sensors 3.0.2 & Linux kernel 2.6.27 (aka Ubuntu 8.10) +# +# Note that in the 2.6 series of kernels, with lm_sensors 3.0.2, it is +# no longer necessary to jump through force_subclient= and ignore_* hoops +# when loading the w83782d module; its default behaviour is sufficient +# to support itself correctly (and it finds the 3 subclients without any +# additional prompting). This does NOT allow access to the other chip, +# a W83627HF, over I2C, but this second chip is mapped into the ISA I/O +# space anyway, and loading the "w83627hf" module without any options +# locates it and accesses it perfectly fine. See also notes below about +# the inadvisability of overusing the I2C bus on this motherboard anyway. +# This has only been tested on MY board, which is the -4M variant, with +# BIOS 4.06. Depending on your BIOS version, you may or may not want to +# use the "init=0" module options INSTEAD OF setting various mins & maxes +# below, particularly temperature-wise. YMMV. +# -Adam Thompson, 2009-Apr-01 +##### + +# set min/max limits to 5% for the critical voltages +# set min/max limits to 10% for the non-critical voltages +# set min/max limits to 20% for the battery voltage + + +chip "w83782d-*" + ignore in0 + ignore in1 + label in2 "AGP V" + set in2_min 3.3*0.95 + set in2_max 3.3*1.05 + label in3 " +5 V" + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + set in3_min 5.0*0.95 + set in3_max 5.0*1.05 + label in4 "DDR V" + ignore in5 + ignore in7 + label in6 "3 VSB" + set in6_max 3.0*1.05 + set in6_min 3.0*0.95 + label in8 "Bat V" + set in8_min 3.3*0.80 + set in8_max 3.3*1.20 + ignore vid + label fan1 "Chassis Fan 2" + label fan2 "Chassis Fan 1" + label fan3 "PSU Fan" + label temp1 "VRM2 Temp" + label temp2 "CPU1 Temp" + label temp3 "CPU2 Temp" +# set temp1_type 2 +# set temp1_max 40 +# set temp1_max_hyst 60 +# set temp2_type 2 +# set temp2_max 70 +# set temp2_max_hyst 80 +# set temp3_type 2 +# set temp3_max 70 +# set temp3_max_hyst 80 + +# lm_sensors ticket#1795 (http://www.lm-sensors.org/ticket/1795) also +# strongly suggests using the ISA bus where possible to avoid overloading +# the SMBus on Tyan motherboards. +# Accessing this via ISA inb/outb also avoids the need altogether to use +# force_subclient= options when loading the w83782d module. + +chip "w83627hf-*" + label in0 "VCore1" + set in0_min cpu0_vid*0.95 + set in0_max cpu0_vid*1.05 + label in1 "VCore2" + set in1_min cpu0_vid*0.95 + set in1_max cpu0_vid*1.05 + label in2 "+3.3 V" + set in2_min 3.3*0.95 + set in2_max 3.3*1.05 + ignore in3 + label in4 " +12 V" + compute in4 ((3.8/1)+1)*@ , @/((3.8/1)+1) + set in4_max 12*0.90 + set in4_min 12*1.10 + label in5 " -12 V" + compute in5 (5.14*@)-14.91 , (@+14.91)/5.14 + set in5_max -12*0.90 + set in5_min -12*1.10 + ignore in6 + ignore in7 + ignore in8 + ignore vid + label temp1 "VRM1 Temp" + label temp2 "AGP Temp" + label temp3 "DDR Temp" + label fan1 "CPU1 Fan" + label fan2 "CPU2 Fan" + ignore fan3 +# set temp1_type 2 +# set temp1_max 40 +# set temp1_max_hyst 37 +# set temp2_type 2 +# set temp2_max 52 +# set temp2_max_hyst 47 +# set temp3_type 2 +# set temp3_max 52 +# set temp3_max_hyst 47 + set beep_enable 0 diff --git a/configs/VIA/EPIA-M920.conf b/configs/VIA/EPIA-M920.conf new file mode 100644 index 0000000..69f2846 --- /dev/null +++ b/configs/VIA/EPIA-M920.conf @@ -0,0 +1,30 @@ +# Configuration file reportedly provided to users by VIA themselves. + + +chip "f71869-*" + + label in0 "+3.3V" + label in1 "+Vcore" + label in4 "Vdimm" + label in3 "+3.3V" + label in2 "+5V" + label in6 "+12V" + label in7 "3VSB" + label in8 "Vbat" + label fan1 "CPU Fan Speed" + label fan2 "System Fan Speed" + label temp1 "CPU Temperature" + label temp2 "System Temperature" + + compute in0 @*2 , @/2 + compute in2 @*2.5 , @/2.5 + compute in3 @*2 , @/2 + compute in4 @*1.47 , @/1.47 + compute in6 @*11 , @/11 + compute in7 @*2 , @/2 + compute in8 @*2 , @/2 + + ignore in5 + ignore fan3 + ignore fan4 + ignore temp3 diff --git a/configs/Zotac/H55-ITX.conf b/configs/Zotac/H55-ITX.conf new file mode 100644 index 0000000..15a7bc7 --- /dev/null +++ b/configs/Zotac/H55-ITX.conf @@ -0,0 +1,48 @@ +# Configuration contributed by Jean Delvare. + + +chip "w83667hg-isa-0a10" + + # Voltages + + label in0 "Vcore" + label in1 "Vtt" + label in2 "AVCC" + label in3 "+3.3V" + label in4 "PCH" + label in5 "IGD" + label in7 "3VSB" + label in8 "Vbat" + + set in1_min 1.1 * 0.95 + set in1_max 1.1 * 1.05 + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 3.3 * 0.90 + set in3_max 3.3 * 1.10 + set in4_min 1.1 * 0.95 + set in4_max 1.1 * 1.05 + set in7_min 3.3 * 0.90 + set in7_max 3.3 * 1.10 + set in8_min 3.0 * 0.90 + set in8_max 3.0 * 1.10 + + # Fans + + # I don't know which fan headers exist and which don't. + #ignore fan1 + label fan2 "CPU Fan" + #ignore fan3 + #ignore fan4 + #ignore fan5 + + set fan2_min 800 + + # Temperatures + + label temp1 "M/B Temp" + label temp2 "CPU Temp" + ignore temp3 + + set temp1_max 55 + set temp1_max_hyst 52 diff --git a/configs/Zotac/ZBOX-ID18 b/configs/Zotac/ZBOX-ID18 new file mode 100644 index 0000000..abad6af --- /dev/null +++ b/configs/Zotac/ZBOX-ID18 @@ -0,0 +1,36 @@ +# Zotac Zbox ID18 Celeron 1007U @ 1,5 GHz, ITX format +# J. Schwender +# dmi: ZBOX-ID18 +# driver: coretemp +# driver: nct6775, 8 mV / LSB, 0…2.048 V +chip "nct6776-isa-0a30" + label in1 "RAM" + set in1_min 0.5 + set in1_max 2.0 # limiits depend on the RAM type in use + + label in4 "+12 V" + set in4_min 12*0.95 + set in4_max 12*1.05 + compute in4 11.5*@,@/11.5 # guess 1.05 V + + label in6 "+5 V" + set in6_min 5*0.95 + set in6_max 5*1.05 + compute in6 7.4*@,@/7.4 # guess 0.69 + + ignore in5 # shows always zero + + ignore fan1 # ZBox id18 has no other fan + label fan2 "CPU fan" # verified + + ignore intrusion0 + ignore intrusion1 + ignore beep_enable + + set temp1_max 90 + set temp1_max_hyst 30 + ignore temp2 # shows alwasy 123.5° + label temp7 "CPU socket" + ignore temp8 # PCH_CHIP_TEMP shows 0 + ignore temp9 # PCH_CPU_TEMP shows 0 + ignore temp10 # PCH_MCH_TEMP shows 0 diff --git a/configs/Zotac/ZBOX-ID18.conf b/configs/Zotac/ZBOX-ID18.conf new file mode 100644 index 0000000..abad6af --- /dev/null +++ b/configs/Zotac/ZBOX-ID18.conf @@ -0,0 +1,36 @@ +# Zotac Zbox ID18 Celeron 1007U @ 1,5 GHz, ITX format +# J. Schwender +# dmi: ZBOX-ID18 +# driver: coretemp +# driver: nct6775, 8 mV / LSB, 0…2.048 V +chip "nct6776-isa-0a30" + label in1 "RAM" + set in1_min 0.5 + set in1_max 2.0 # limiits depend on the RAM type in use + + label in4 "+12 V" + set in4_min 12*0.95 + set in4_max 12*1.05 + compute in4 11.5*@,@/11.5 # guess 1.05 V + + label in6 "+5 V" + set in6_min 5*0.95 + set in6_max 5*1.05 + compute in6 7.4*@,@/7.4 # guess 0.69 + + ignore in5 # shows always zero + + ignore fan1 # ZBox id18 has no other fan + label fan2 "CPU fan" # verified + + ignore intrusion0 + ignore intrusion1 + ignore beep_enable + + set temp1_max 90 + set temp1_max_hyst 30 + ignore temp2 # shows alwasy 123.5° + label temp7 "CPU socket" + ignore temp8 # PCH_CHIP_TEMP shows 0 + ignore temp9 # PCH_CPU_TEMP shows 0 + ignore temp10 # PCH_MCH_TEMP shows 0 diff --git a/configs/Zotac/ZBox-HD-ID11.conf b/configs/Zotac/ZBox-HD-ID11.conf new file mode 100644 index 0000000..6697283 --- /dev/null +++ b/configs/Zotac/ZBox-HD-ID11.conf @@ -0,0 +1,59 @@ +# Contributed by Piotr Maksymiuk. + + +##/etc/sensors.d/zbox-hd-id-11 + +chip "w83667hg-isa-0a10" + + # Voltages + + label in0 "Vcore" + label in1 "RAM" + label in2 "AVCC" + label in3 "+3.3V" + label in4 "Chipset" + label in5 "+1.5V" + label in6 "3VSB" + + set in0_min 1.1 * 0.90 + set in0_max 1.1 * 1.10 + set in1_min 1.9 * 0.90 + set in1_max 1.9 * 1.10 + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 3.3 * 0.90 + set in3_max 3.3 * 1.10 + set in4_min 1.1 * 0.90 + set in4_max 1.1 * 1.10 + set in5_min 1.5 * 0.90 + set in5_max 1.5 * 1.10 + + # Fans + + # Only fan2 is used in this barebone. + ignore fan1 + label fan2 "Case Fan" + ignore fan3 + ignore fan4 + ignore fan5 + + set fan2_min 800 + + # Temperatures + + #unfortunately i'm not sure if temp3 is ram + label temp1 "M/B Temp" + label temp2 "CPU Temp" + label temp3 "RAM Temp" + + #this always returns a 0 reading + ignore cpu0_vid + + set temp1_max 50 + set temp1_max_hyst 40 + + set temp2_max 75 + set temp2_max_hyst 60 + + set temp3_max 35 + set temp3_max_hyst 30 diff --git a/doc/developers/applications b/doc/developers/applications new file mode 100644 index 0000000..c39840d --- /dev/null +++ b/doc/developers/applications @@ -0,0 +1,69 @@ +How to write applications which use the hwmon drivers +===================================================== + +You have several choices in accessing sensor devices using the hwmon drivers. +This document will briefly describe these methods, their advantages and +disadvantages, and provide examples. + +From lowest-level to the highest-level, the access methods are: + + 1. sysfs access + 2. libsensors library + 3. sensors program + + +Details: + +1. sysfs access +--------------- + Hwmon drivers create subdirectories in the sysfs filesystem (usually /sys) + which can be accessed directly by applications. + Naming and content standards for the entries in these subdirectories + are documented in the file Documentation/hwmon/sysfs-interface in the 2.6 + kernel source tree. sysfs is the lowest-level access to sensor values. + + Note that most drivers provide only raw sensor readings via /sys; + many readings must be scaled or adjusted, and these adjustments + must often be changed by the user. An application using /sys must + generally provide adjustment facilities and the requirements + of the adjustments can be quite complex. For this reason, this + approach isn't recommended. Instead, consider the libsensors library, + which offers a higher-level interface on top of sysfs (see below.) + + Still, this method may work well for shell and perl scripts written to + access a specific device. + + For an example of a program using /sys accesses, see gkrellm (though + recent versions use libsensors instead.) See also lib/sysfs.c. + +2. libsensors library +--------------------- + The libsensors library provides standardized access to all chip drivers. + It also provides a translation layer with settings in /etc/sensors.conf + so that your application sees adjusted (scaled) values using settings + provided by the user. Other facilities are sensor labelling, limit setting, + and ignoring individual sensors. This is the recommended way to access + the sensor chips. + + The library API is documented in the libsensors(3) manual page. The + configuration file format is documented in the sensors.conf(5) manual + page. + + Note that since version 3.2.0, libsensors falls under the LGPL, not the + GPL as it used to. In more human language, that means it is now ALLOWED + to link any application to the library, even to the shared version, + regardless of the application's license. + + For examples of programs using libsensors accesses, see prog/sensors and + prog/sensord. + +3. sensors program +------------------ + The 'sensors' program is a text-based application that uses libsensors. + The output is fairly standardized; therefore this output could be + used by other applications. + One simple method is 'sensors|grep ALARM'. + Note though that there is no guarantee that the output format won't change + in the future, so be careful. We might improve the command-line interface + of 'sensors' someday to make it more convenient for external programs to + use it as a back-end. diff --git a/doc/developers/lm_sensors.lsm b/doc/developers/lm_sensors.lsm new file mode 100644 index 0000000..fd9495a --- /dev/null +++ b/doc/developers/lm_sensors.lsm @@ -0,0 +1,18 @@ +Begin4 +Title: lm_sensors +Version: 3.4.0 +Entered-date: 2015-06-25 +Description: Hardware health monitoring package for Linux. It consists of + a library to allow applications to read sensors data more + easily, and of an example program to pretty print this data. + Also included is a fan speed control script. + http://www.lm-sensors.org/ +Keywords: sensors health hardware-monitoring fan-speed +Author: jdelvare@suse.de (Jean Delvare) +Maintained-by: jdelvare@suse.de (Jean Delvare) +Primary-site: http://dl.lm-sensors.org/lm-sensors/releases/ + lm_sensors-3.4.0.tar.bz2 + lm_sensors-3.4.0.tar.bz2.sig +Alternate-site: ftp://ftp.netroedge.com/pub/lm-sensors/ +Copying-policy: GPL/LGPL +End diff --git a/doc/developers/makefiles b/doc/developers/makefiles new file mode 100644 index 0000000..29d3795 --- /dev/null +++ b/doc/developers/makefiles @@ -0,0 +1,54 @@ +The Makefiles in this package are rather advanced. They are partially based +on the article "Recursive Make considered Harmful", written by Peter Miller: + http://miller.emu.id.au/pmiller/books/rmch/ + +There is one big Makefile in the root of this package. It includes many +other files; one for each directory in which source code is found. These +included files are called 'Module.mk'. + +There are several interesting targets defined through this Makefile: + * all + Create everything in all directories. + * install + Install everything from all directories. + * uninstall + Uninstall everything. + * clean + Remove anything which can be regenerated from all directories. A call + of 'make clean' (without any other targets) will ignore any .d files; + this is useful when they are out of date (and prevent the calling of + any other target). + +The best way to understand the Module.mk subfiles is to examine one of them, +for example lib/Module.mk. They are not too difficult to understand. + +There are several variables which can be set in the main Makefile. You can +also specify them on the command-line; this overrules any definitions +within the Makefile. For example: 'make all WARN=1' will enable all warnings. +Examine main Makefile to see which ones are available. The most important +ones for developers: + * WARN + Set to 1 to enable many compiler warnings. + * DEBUG + Set to 1 to enable any debugging code. Note that debugging code should + only output more information, and never make the code mis-behave. + +Several files are generated by Makefiles: + * .rd + Dependency files for executables. Automatically generated. + * .ad + Dependency files for static libraries. Automatically generated. + * .ld + Dependency files for shared libraries. Automatically generated. + * .ro + Object files for executables. They will be linked together to create + the executable. + * .ao + Object files for static libraries + * .lo + Object files for shared libraries +The reason for using different extensions is to make the Makefile much +simpler. + +There are lots of comments within the main Makefile. Please read them if +you want to know more. diff --git a/doc/developers/release_checklist b/doc/developers/release_checklist new file mode 100644 index 0000000..9ea1ddf --- /dev/null +++ b/doc/developers/release_checklist @@ -0,0 +1,41 @@ +CHECKLIST FOR NEW RELEASES +========================== + +Release steps: +- Check out lm-sensors +- Update if necessary, the version number of libsensors + (edit lib/Module.mk and change LIBMAINVER and/or LIBMINORVER) + Remember: update main number when interface changes, minor if new + functionality is added, and patch if only bugs are fixed. +- Update the CHANGES file (set version and release date) +- Update doc/developers/lm_sensors.lsm (Version, Entered-date and Primary-site) +- Update doc/libsensors-API.txt and SENSORS_API_VERSION in lib/sensors.h +- Update version.h +- Commit +- Tag the release using SVN: + svn copy http://lm-sensors.org/svn/lm-sensors/trunk http://lm-sensors.org/svn/lm-sensors/tags/V3-x-x -m "3.x.x release" + +- Move to a temporary directory and get a copy of the freshly tagged code: + svn export http://lm-sensors.org/svn/lm-sensors/tags/V3-x-x lm_sensors-3.x.x +- Tar it up: + tar -jcf lm_sensors-3.x.x.tar.bz2 lm_sensors-3.x.x +- Sign it: + gpg -b lm_sensors-3.x.x.tar.bz2 +- Post it: + scp lm_sensors-3.x.x.tar.bz2{,.sig} devel.atrpms.net:/srv/lm-sensors.org/dl/lm-sensors/releases +- Set correct permissions: + ssh devel.atrpms.net chmod 664 '/srv/lm-sensors.org/dl/lm-sensors/releases/lm_sensors-3.x.x.tar.bz2{,.sig}' + +After release, remember to: +- Update the Download page on lm-sensors.org, then add a news item +- Announce on the lm-sensors mailing list +- Add "+SVN" to version.h and commit +- Mark the corresponding release milestone as complete using trac-admin + e.g. 'trac-admin /srv/lm-sensors.org/trac milestone completed 3.x.x now' +- Create a new version for the bug tracking system using trac-admin + e.g. 'trac-admin /srv/lm-sensors.org/trac version add 3.x.x now' +- Create a new release milestone using trac-admin + e.g. 'trac-admin /srv/lm-sensors.org/trac milestone add 3.x.x+1 2012-05-10' +- Send lm_sensors.lsm to the LSM by mailing it to lsm@qqx.org with the + subject `add' (no quotes) +- Copy to mirrors diff --git a/doc/developers/smbus_company_id b/doc/developers/smbus_company_id new file mode 100644 index 0000000..375a47e --- /dev/null +++ b/doc/developers/smbus_company_id @@ -0,0 +1,41 @@ +COMPANY ID LIST +--------------- + +Many SMBus chips have a company ID at location 0x3E or 0xFE. + +Here is a partial list. +This may help identify a chip after doing a 'i2cdump [bus] [address]'. + +0x01 National Semiconductor +0x12C3 Asus (at 0x4F) +0x1934 Fintek (at 0x5D-0x5E) +0x23 Analog Devices (old products) or Fintek +0x41 Analog Devices (new products) +0x49 TI +0x4D Maxim +0x54 On Semi +0x5C SMSC +0x5D SMSC +0x55 SMSC +0x5CA3 Winbond (at 0x4F) +0x61 Andigilog +0x90 ITE (at 0x58) +0xA1 Philips +0xA3 Winbond (at 0x4F) +0xC3 Asus (at 0x4F) +0xDA Dallas + +[A-Z]{3} at 0x00-0x02: Fujitsu-Siemens + + +Jedec JC 42.4 compliant temperature sensors provide the manufacturer ID +in 16-bit register 0x06. Known manufacturer IDs are as follows. + +0x001F Atmel +0x004D Maxim +0x0054 Microchip +0x00B3 IDT +0x104A ST Microelectronics +0x1131 NXP (Philips) +0x11D4 Analog Devices +0x1B09 ON Semiconductor diff --git a/doc/donations b/doc/donations new file mode 100644 index 0000000..92eea57 --- /dev/null +++ b/doc/donations @@ -0,0 +1,132 @@ +The lm_sensors team gratefully acknowledges the following donations. + +Drivers are very difficult to develop without actual hardware. +Generally, the work goes quickly once we have the hardware. + +Evaluation boards are fine. Real computer hardware is much better though, +because it lets us do real-world testing over a longer period of time. +In many cases, the way a chipset is integrated in systems must be taken +into account in the driver, and evaluation boards don't help much there. +Donation of usable computer hardware also supports the project in general, +so hardware which isn't directly related to the development of a hardware +monitoring driver, but can be used to build test systems, is welcome too. + +If you would like to make a donation, please contact us. See +http://www.lm-sensors.org/wiki/AuthorsAndContributors. Thanks! + + +Donations are listed in chronological order. Note that the person mentioned +is the one who holds the device now, which is not necessarily the one to whom +the donation was sent in the first place. + + +Donation from Donation and subsequent development work Date & Person +------------- ---------------------------------------- ------------- + +TI i810 motherboard w/ 366 Celeron 1999-07 + Drivers developed: i801, i810, w83627hf ?? + +AMD various sensor evaluation boards 2000 + Drivers developed: various ?? + +SiS SiS 540/630 motherboard w/ 5595 2000-01 + Drivers developed: sis5595 improvements Phil + +Cendio Systems Asus P3B-F w/ AS99127F 2000-05 + Drivers developed: as99127f improvements MDS + +Atipa SuperMicro 370DLE w/ Serverworks, LM87 2000-09 + Drivers developed: serverworks support added trash + to i2c-piix4; lm87 testing and improvements + +Fujitsu Complete system for general project support 2001-11 +Siemens (broken) Phil +Computers + +HardData Ltd. Tyan 2466 w/ 1G Duron; W83627HF and W83782D 2002-05 + Drivers developed: Tyan 2466 initialization; MDS + DDR recognition + +Intel SMBus 2.0 system 2002-06 + Drivers developed: SMBus 2.0 support in MDS + i2c-core and i2c-i801; ADM1025 improvements; + 82801 improvements; smsc47m1 driver + +VIA 8231 and two 8233 motherboards 2002-06 + Drivers developed: VT8231 support in via686a; MDS + vt1211; VT8233A and VT8231 support in + i2c-viapro + +HP IPMI system 2002-10 + Drivers developed: bmcsensors, i2c-ipmi MDS + +Analog Devices ADM1032 evaluation board 2003-10 + Drivers developed: ADM1032 support in lm90; Jean Delvare + lm90 ported to Linux 2.6 + +National LM83 evaluation board 2003-12 +Semiconductor Drivers developed: lm83 testing and Jean Delvare + improvements; lm83 ported to Linux 2.6 + +Analog Devices ADM1025 evaluation board 2004-01 + Drivers developed: adm1025 testing and Jean Delvare + improvements; adm1025 ported to Linux 2.6 + +Analog Devices ADT7467/8 evaluation board 2004-01 + Drivers developed: nothing yet Jean Delvare + +Analog Devices ADM1031 evaluation board 2004-04 + Drivers developed: adm1031 for Linux 2.4 and Jean Delvare + 2.6 + (broken) + +Wincor Nixdorf Seagate Barracuda 7200.7 160GB harddisk drive 2004-10 + trash + +Aweta Intel Server system 2005-09 + Drivers developed: PC87431 (IPMI SMB) MDS + +Barracuda Jetway K8M8MS, Sempron 2600+, 256 MB RAM 2005-10 +Networks Drivers developed: f71805f Jean Delvare + +Winbond Celeron CPU, 512MB RAM 2006-03 + W83792D watchdog and VID support Rudolf Marek + +ASUSTeK ASUS P5MT-S 2006-03 + Platform for W83792D related development Rudolf Marek + +Winbond Asus P4P800-VM 2006-08 + This board has a Winbond W83627THF hardware Jean Delvare + monitoring chip. + +Winbond Asus P4P800-X, Pentium 4 2.8 GHz, 512 MB RAM 2006-08 + This board has an (hidden) Intel 82801EB Jean Delvare + (ICH5) SMBus with SPD EEPROMs connected, and + a Winbond W83627THF hardware monitoring chip. + +Observit Intel D865GSA, Celeron D-352, 2007-06 + 128 MB RAM trash + Resulted in: backport of the w83627ehf driver + to Linux 2.4, improvements to the Linux 2.6 + w83627ehf driver. + +Observit Intel D865GBF, Celeron 2.4 GHz, 512 MB RAM 2007-06 + Resulted in: improvements to the lm85 driver. Jean Delvare + +Nuvoton 2 x Asus P5QL Pro, 1 GB RAM, 2009-07 + Pentium D-945, video card (dead) Jean Delvare + This board has an ATK0110 ACPI device backed + by a Winbond W83667HG. + +ASUSTeK ASUS Z8NA-D6, 2 x Xeon E5520, 2 x 1 GB RAM 2010-04 + This board has a Winbond W83795ADG, SMBus is Jean Delvare + multiplexed with GPIOs. + Drivers developed: w83795 + +lleo19 Intel DH57JG with i3-540 CPU, 4GB RAM, chassis, 2011-01 + and power supply. Guenter Roeck + Used to add support for NCT6775F (W83677HG-I) + to w83627ehf driver. + +AMD Asus EAH6450 Silent video card 2011-12 + Jean Delvare diff --git a/doc/fan-divisors b/doc/fan-divisors new file mode 100644 index 0000000..978f5a3 --- /dev/null +++ b/doc/fan-divisors @@ -0,0 +1,132 @@ +Fan reading problems and solutions +---------------------------------- + +If you aren't getting the expected readings on your fans, +try the following: + +- Do you get a fan reading in the BIOS or using a different OS? + If not, you may not have a fan with a tachometer output. + Look and see. Fans with tachometer outputs have at least 3 wires. + Fans with only 2 wires cannot, in general, report their speed. + +- If your monitoring chip supports fan divisors, try experimenting + with the fan divisor settings. + + +Does my monitoring chip use fan divisors? +----------------------------------------- + + Recent monitoring chips tend to store fan speed values on 12 or even + 16 bits, so divisors are no longer required. In that case, you won't + see "div" values in the output of sensors, and nothing needs to be + configured: + + CPU1 Fan: 2160 RPM (min = 800 RPM) + CPU2 Fan: 0 RPM (min = 799 RPM) ALARM + Front3 Fan: 0 RPM (min = 0 RPM) + Front4 Fan: 779 RPM (min = 600 RPM) + + If your "sensors" output looks like the above, stop reading here, + the explanations below do not apply to your case. + + Older chips stored the fan speed values on 8 bits, which wasn't + sufficient to cover the full range from very slow fans to very + fast fans with good accuracy. This is where fan divisors came + into play: + + Case Fan: 0 RPM (min = 998 RPM, div = 8) ALARM + CPU Fan: 2500 RPM (min = 1500 RPM, div = 4) + + If your "sensors" output looks like the above, read below. + + As a notable exception, the w83627ehf driver exposes fan divisor + values, but they are adjusted automatically by the driver, so you + shouldn't have to care. + + +Fan Divisor Settings +-------------------- + +Fan Divisor Minimum RPM Maximum RPM +----------- ----------- ----------- + 1 5314 1350000 + 2 2657 675000 default on most chips + 4 1328 337500 + 8 664 168750 + 16 332 84375 not supported on most chips + 32 166 42187 "" + 64 83 21093 "" +128 41 10546 "" + +Pick a divisor so that the nominal RPM is about 50% +above the minimum. This is a good compromise between +margin and accuracy. Note that most chips only support +fan divisors of 1, 2, 4, and 8. + +If you have a 0 RPM reading some or all of the time, +increase the divisor until you get good readings. + +If you have a nominal reading less than 1.25 times the +minimum, increase the divisor to give you margin +so that you will not get spurious alarms. + +If you have a nominal reading more than 3 times the +minimum, decrease the divisor to provide better +accuracy. + + +How to change fan divisors +-------------------------- + +Put an entry "set fanN_div X" in the appropriate section of +/etc/sensors3.conf and run 'sensors -s' +(N is the number of the fan, and X is the divisor you want). + + +Further details +--------------- + +Fan divisors are quite confusing. + +Sensor chips count fan speed by using the fan signal +to gate an 8-bit counter driven by a 22.5 kHz clock. +So the _higher_ the counter value, the _slower_ the fan, +and vice versa. + +The term 'fan divisor' is a misnomer because it doesn't divide +the fan signal, it divides the 22.5 kHz clock. +Thus you _increase_ the divisor if you have a slow fan. + +The drivers account for the 'fan divisor' in their calculation +of RPM. So changing the fan divisor will NOT change the +nominal RPM reading, it will only affect the minimum and maximum +readings and the accuracy of the readings. + +The actual formula is RPM = (60 * 22500) / (count * divisor) + +The readings are most accurate when the fan speed is low +(i.e., close to the minimum possible RPM reading). +As fan speed gets closer to the maximum possible RPM reading, +the reading becomes quite inaccurate. Fortunately, most computer +fans do not approach 1,000,000 RPM ! + + +Fan readings 2X too high +------------------------ + +This is rare, but can happen. This is typically caused by a fan which +outputs 4 pulses by revolution, instead of the standard 2. + +As we learned above, you can _not_ fix this by changing +the fan divisor. You must add entries into the appropriate +section of /etc/sensors3.conf: + + compute fanN @/2, 2*@ + +(N is the number of the fan) + + + +------------------ +Copyright (c) 2000-2004 Mark D. Studebaker +Copyright (c) 2006-2012 Jean Delvare diff --git a/doc/fancontrol.txt b/doc/fancontrol.txt new file mode 100644 index 0000000..40e290f --- /dev/null +++ b/doc/fancontrol.txt @@ -0,0 +1,133 @@ + +fancontrol - automated software based fan speed regulation + + +Introduction + +fancontrol is a shellscript for use with lm_sensors. It reads its +configuration from a file, then calculates fan speeds from temperatures and +sets the corresponding pwm outputs to the computed values. It is included in +lm_sensors since version 2.8.0. For easy configuration, there's a script +named pwmconfig which lets you interactively write your configuration file for +fancontrol. Alternatively you can write this file yourself using the +information from the configuration section of this document. + +Please be careful when using the fan control features of your mainboard, in +addition to the risk of burning your CPU, at higher temperatures there will be +a higher wearout of your other hardware components, too. So if you plan to use +these components in 50 years, _maybe_ you shouldn't use fancontrol/your +hardware at all. Also please keep in mind most fans aren't designed to be +powered by a PWMed voltage, for more detailed information on this I recommend +this appnote: http://www.maxim-ic.com/appnotes.cfm/appnote_number/707 +In practice it doesn't seem to be a major issue, the fans will get slightly +warmer, just be sure to have a temperature alarm and/or shutdown call, in case +some fan fails, because you probably won't hear it anymore ;) + +Configuration + +Since most of you are going to use the pwmconfig script, the config +file syntax will be discussed last. First I'm going to describe the various +variables available for changing fancontrol's behaviour: + +INTERVAL + This variable defines at which interval in seconds the main loop of + fancontrol will be executed + +FCTEMPS + Maps pwm outputs to temperature sensors so fancontrol knows which + temperature sensors should be used for calculation of new values for + the corresponding pwm outputs. + +FCFANS + FCFANS records the association between a pwm and a fan. + Then fancontrol can check the fan speed and restart it if it + stops unexpectedly. + +MINTEMP + The temperature below which the fan gets switched to minimum speed. + +MAXTEMP + The temperature over which the fan gets switched to maximum speed. + +MINSTART + Sets the minimum speed at which the fan begins spinning. You should + use a safe value to be sure it works, even when the fan gets old. + +MINSTOP + The minimum speed at which the fan still spins. Use a safe value here, + too. + +MINPWM + The PWM value to use when the temperature is below MINTEMP. + Typically, this will be either 0 if it is OK for the fan to plain + stop, or the same value as MINSTOP if you don't want the fan to + ever stop. + If this value isn't defined, it defaults to 0 (stopped fan). + +MAXPWM + The PWM value to use when the temperature is over MAXTEMP. + If this value isn't defined, it defaults to 255 (full speed). + +A graph might help you understand how the different values relate +to each other: + + PWM ^ + 255 + + | + | + | ,-------------- MAXPWM + | ,'. + | ,' . + | ,' . + | ,' . + | ,' . + | ,' . + | MINSTOP .' . + | | . + | | . + | | . + MINPWM |---------------' . + | . . + | . . + | . . + 0 +---------------+-------------+----------------> + MINTEMP MAXTEMP t (degree C) + +The configuration file format is a bit strange: + +VARIABLE=chip/pwmdev=value chip/pwmdev2=value2 [...] +VARIABLE2=[...] + +Each variable has its own line. The variable name is followed by an equal sign +and the device=value pairs. These consist of the path to the pwm output for +which the value is valid, equal sign followed by the value and are separated +by a blank. Path can be absolute or relative (from /sys/bus/i2c/devices or +/sys/class/hwmon depending on the kernel version). + +Example: + +MINTEMP=hwmon0/device/pwm1=40 hwmon0/device/pwm2=54 + +You have to play with the temperature values a bit to get happy. For initial +setup I recommend using the pwmconfig script. Small changes can be made by +editing the config file directly following the rules above. + + +The algorithm + +fancontrol first reads its configuration, writes it to arrays and loops its +main function. This function gets the temperatures and fanspeeds from +kernel driver files and calculates new speeds depending on temperature +changes, but only if the temp is between MINTEMP and MAXTEMP. After that, the +new values are written to the pwm outputs. The pwm value increases +linearly with rising temperature. + + +Planned features + +rc-scripts for some gnu/linux-distributions +smoother regulation (temp interpolation) +gui for configuration + +If you have other wishes or want to contribute something, please let me know: +marius.reiner${AT}hdev.de diff --git a/doc/git b/doc/git new file mode 100644 index 0000000..1c433d2 --- /dev/null +++ b/doc/git @@ -0,0 +1,22 @@ +Git Repository + +Anonymous access to our git repository is available. This means +that users can have direct access to up-to-the-minute code. + +Driver development for kernel version 3 is taking place directly in the kernel +using git. The git repository is only used for user-space tools. + +We presume that you have git installed on your machine. To check out a +working copy of the code for this project use the following command: + +git clone https://github.com/groeck/lm-sensors.git + +To update the code, do a git pull from within the lm-sensors directory. +Please read the README and INSTALL files of your working copy for how +to build the code. Also read the related files in the 'doc' directory +for info regarding the different bus and chip drivers. Lastly, you can use +the regular git commands on the files (like git log [filename]) to see the +comments made by the developers as changes were made. + +If you're not familiar with the use of we recommend the excellent +online git documentation at https://git-scm.com/doc. diff --git a/doc/libsensors-API.txt b/doc/libsensors-API.txt new file mode 100644 index 0000000..0b7e4d8 --- /dev/null +++ b/doc/libsensors-API.txt @@ -0,0 +1,109 @@ +libsensors API history +====================== + +SENSORS_API_VERSION tracks the evolutions made to the libsensors API +over time. This document summarizes these evolutions so that application +authors can quickly figure out how to test for the availability of a +given new feature. + +0x440 lm-sensors 3.4.0 +* Defined SENSORS_FEATURE_MAX + enum sensors_feature_type SENSORS_FEATURE_MAX +* Added support for temp min and temp critical min hysteresis + enum sensors_subfeature_type SENSORS_SUBFEATURE_TEMP_MIN_HYST + enum sensors_subfeature_type SENSORS_SUBFEATURE_TEMP_LCRIT_HYST + +0x432 lm-sensors 3.3.2 to 3.3.5 +* Added support for new sysfs attributes + enum sensors_subfeature_type SENSORS_SUBFEATURE_IN_AVERAGE + enum sensors_subfeature_type SENSORS_SUBFEATURE_IN_LOWEST + enum sensors_subfeature_type SENSORS_SUBFEATURE_IN_HIGHEST + enum sensors_subfeature_type SENSORS_SUBFEATURE_TEMP_LOWEST + enum sensors_subfeature_type SENSORS_SUBFEATURE_TEMP_HIGHEST + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_AVERAGE + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_LOWEST + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_HIGHEST + enum sensors_subfeature_type SENSORS_SUBFEATURE_FAN_MAX + enum sensors_subfeature_type SENSORS_SUBFEATURE_FAN_MIN_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_FAN_MAX_ALARM + +0x431 lm-sensors 3.3.0 to 3.3.1 +* Added support for intrusion detection + enum sensors_feature_type SENSORS_FEATURE_INTRUSION + enum sensors_subfeature_type SENSORS_SUBFEATURE_INTRUSION_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_INTRUSION_BEEP +* Added support for various new sysfs attributes + enum sensors_subfeature_type SENSORS_SUBFEATURE_IN_LCRIT + enum sensors_subfeature_type SENSORS_SUBFEATURE_IN_CRIT + enum sensors_subfeature_type SENSORS_SUBFEATURE_IN_LCRIT_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_IN_CRIT_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_TEMP_LCRIT + enum sensors_subfeature_type SENSORS_SUBFEATURE_TEMP_EMERGENCY + enum sensors_subfeature_type SENSORS_SUBFEATURE_TEMP_EMERGENCY_HYST + enum sensors_subfeature_type SENSORS_SUBFEATURE_TEMP_LCRIT_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_TEMP_EMERGENCY_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_CAP + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_CAP_HYST + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_MAX + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_CRIT + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_CAP_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_MAX_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_CRIT_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_LCRIT + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_CRIT + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_LCRIT_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_CRIT_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_FAN_PULSES +* Added support for humidity sensors + enum sensors_feature_type SENSORS_FEATURE_HUMIDITY + enum sensors_subfeature_type SENSORS_SUBFEATURE_HUMIDITY_INPUT + +0x430 lm-sensors 3.2.0 +* License changed from GPL to LGPL + +0x421 lm-sensors 3.1.2 +* Added bus type "hid": + #define SENSORS_BUS_TYPE_HID + +0x420 lm-sensors 3.1.1 +* Added a method to free the memory allocated by sensors_parse_chip_name() + void sensors_free_chip_name(sensors_chip_name *chip); + +0x410 lm-sensors 3.1.0 +* Added bus type "acpi": + #define SENSORS_BUS_TYPE_ACPI +* Added support for instantaneous power sensors + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_INPUT + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_INPUT_LOWEST +* Added support for current sensors + enum sensors_feature_type SENSORS_FEATURE_CURR + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_INPUT + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_MIN + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_MAX + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_MIN_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_MAX_ALARM + enum sensors_subfeature_type SENSORS_SUBFEATURE_CURR_BEEP +* Added error value for excessive recursion depth + #define SENSORS_ERR_RECURSION 11 +* Added parse error reporting function including the configuration file + name + extern void (*sensors_parse_error_wfn) (const char *err, + const char *filename, int lineno); + +0x401 lm-sensors 3.0.2 to 3.0.3 +* Added bus type "virtual": + #define SENSORS_BUS_TYPE_VIRTUAL +* Added support for power and energy sensors + enum sensors_feature_type SENSORS_FEATURE_POWER + enum sensors_feature_type SENSORS_FEATURE_ENERGY + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_AVERAGE + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST + enum sensors_subfeature_type SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL + enum sensors_subfeature_type SENSORS_SUBFEATURE_ENERGY_INPUT + +0x400 lm-sensors 3.0.0 to 3.0.1 +* Initial API. diff --git a/doc/progs b/doc/progs new file mode 100644 index 0000000..e9e997a --- /dev/null +++ b/doc/progs @@ -0,0 +1,67 @@ +This is a list of additional programs, that may or may not be installed by +`make install', and that can be found in the `prog' directory of +this package. + +These programs are generally small utilities used for debugging, +and installation of the lm_sensors package, and for demonstrating +the use of the drivers and libraries in this package. +For more elaborate programs (for example, GUI sensor displays), +see https://github.com/groeck/lm-sensors/ + http://sensors-applet.sourceforge.net/ + https://01.org/powertop/ + https://wpitchoune.net/psensor/ + https://amanusk.github.io/s-tui/ + +* prog/daemon/healthd.sh (written in bash, not installed) + An example of a very simple hardware health monitoring daemon. + +* prog/detect/sensors-detect (written in Perl, installed by 'make install') + This program tries to detect the available SMBus adapters and the chips + connected to them, as well as Super-I/O and misc chips. It also generates + modprobe lines and module options. This program is stand-alone (can be + run without installing lm-sensors) and interactive. + +* prog/dump/isadump (written in C, installed by 'make install') + This program dumps the registers of ISA or Super-I/O chips. + Usual syntax: + isadump 0x295 0x296 + isadump -k 0x55 0x2e 0x2f + +* prog/hotplug/unhide_ICH_SMBus (shell script, not installed) + It unhides the ICH Intel SMBus for kernel 2.6.5 and later. + +* prog/init/lm_sensors.init (shell script, not installed) + A SysV init script to be installed in /etc/rc.d/init.d/ + It inserts the bus and chip modules. + +* prog/init/sensord.init (shell script, not installed) + A SysV init script to be installed in /etc/rc.d/init.d/ + It inserts the bus and chip modules and starts the sensord daemon. + +* prog/pwm/pwmconfig (shell script, installed by 'make install') + Formerly pwmtest, tests the pwm (pulse width modulation) outputs of sensors + for their effect on the fans and helps to setup the configfile for fancontrol. + +* prog/pwm/fancontrol (shell script, installed by 'make install') + Controls fanspeeds responding to changes on temperature sensors. + Configuration through pwmconfig. + +* prog/rrd/sens_update_rrd (written in bash, not installed) + This script gathers sensors data and adds it to a round robin database + (RRD). RRD is then used to display the graphed data in web pages. + See prog/rrd/README for more information. + +* prog/sensord/sensord (written in C, installed by `make install-prog-sensord') + This daemon can be used to periodically log sensor readings from + the sensors hardware to syslog, and to alert (using syslog level ALERT) + when a sensor alarm is signalled; for example, if a fan fails, a temperature + limit is exceeded, etc. + +* prog/sensors/sensors (written in C, installed by `make install') + This pretty-prints the information provided by the modules. It is a normal + console application, using stdout. It is essential, because + unlike the raw sysfs files, it takes your configuration file into account. + +* prog/tellerstats/gather.sh, tellerstats.sh (written in bash, not installed) + These scripts gather sensors data and graph the data for web pages. + See prog/tellerstats/README for more information. diff --git a/doc/temperature-sensors b/doc/temperature-sensors new file mode 100644 index 0000000..2eccb98 --- /dev/null +++ b/doc/temperature-sensors @@ -0,0 +1,107 @@ +Thermistors and Transistors as Temperature Sensors +-------------------------------------------------- +Temperature measuring chips that use external sensors +generally are designed to use either thermistors or +transistors. Check the driver documentation in doc/chips +or the actual data sheets to determine which. + +Exceptions are the Winbond W83782D and W83783S which can use either. +These chips default to termistors but can be configured to use +Pentium II / Celeron diodes or 3904 transistors. + +Thermistors are about 10 times more sensitive than +diodes or transistors at room temperature. + + +Thermistors +----------- +(summarized from http://www.thermometrics.com/htmldocs/ntcapp.htm - + most thermistor companies don't have much on their web sites but + Thermometrics has a comprehensive guide) + +NTC (negative temperature coefficient) thermistors decrease their +resistance with an increase in temperature. +They commonly have a parameter B (beta), units are K (kelvin). +B is the "material constant" of the thermistor and +is a measure of the change of resistance with respect to temperature. +It is the slope of the line graphing (ln R) vs. (1/T). + +B values for three common termistor materials are +approximately 3400K, 3900K, and 4300K. + +The other measure of thermistors is the temperature coefficient 'a' (alpha). +This is the percentage change in resistance for a given change +in temperature. This varies with temperature. + +T = temp in Kelvin (C + 273) + +A = (dR/dT) / R + +A = - B / T**2 + +So by the last equation, a thermistor with a Beta of 3900 will change +resistance about 4.4% for 1 degree change at 25C (298K). +For a beta of 3435 as recommended in the +Winbond W83782D data sheet the change is 3.8%. + +For thermistors, resistance (= voltage for a constant current) +is exponentially related to temperature. + +PTC (positive temperature coefficient) thermistors increase +in resistance with an increase in temperature. They are not +commonly used for accurate temperature sensing. + + +Transistors / Diodes +-------------------- +To use a transistor as a sensor, hook the base of an NPN transistor +(such as the 3904) to the collector. + +This is from Richard Dorf, "Electrical Engineering Handbook". + +For a diode, the voltage Vd = Vt ln(Id/Is). +Vt = kT/q where k = Boltzman's constant 1.38 e-23; + q = elementary charge 1.6 e-19; + T = temp in kelvin. + Is is reverse saturation current. + +(more math and Greek letters I don't understand completely) + +dVd/dT works out to, at room temperature, about 2.1 mV/degree +or a temperature coefficient of about 0.32%/degree. + +For diodes, voltage is linear with temperature. + + + +Winbond W83782D and W83783S +--------------------------- +These chips default to thermistors with Beta = 3435. +Each sensor on the chip can be individually set to be +a diode, transistor, or thermistor. +If the temperature reading changes much less than expected, +the sensor type probably needs to be changed to a diode. +See doc/chips/w83781d for details. + + +Summary +------- +Thermistors are about 10 times more sensitive than +diodes or transistors at room temperature. + +Thermistors change resistance exponentially with respect to temperature. +Diodes and transistors change voltage linearly with respect to temperature. + +Sensors built into chips (including Pentium II / Celeron processors) +are always diodes/transistors because that's what's on a chip +already - transistors. + +External, discrete sensors can be either diodes/transistors or +thermistors. Generally, sensor chips are designed to be connected +to one or the other and cannot be configured. The Winbond +W83782D/W83783S chips are exceptions, they can be +configured for either. + + +------------------ +Copyright (c) 1999, 2001 Mark D. Studebaker diff --git a/doc/vid b/doc/vid new file mode 100644 index 0000000..26d9fba --- /dev/null +++ b/doc/vid @@ -0,0 +1,58 @@ +VID pin settings +-------------------- + +The VID (Voltage Identification) pins on sensor chips +are used to read the CPU Core voltage setting. + +The VID setting can be controlled by jumpers on the board, +or, in newer motherboards, by settings in the BIOS. +On these newer boards, the BIOS programs some device's +pins which in turn controls a DC-DC Converter to set its +output to a certain voltage. These pins are also connected to +the sensor chip so that the VID setting can be read back +by applications. + +There are between 4 and 8 VID pins (the more recent the CPU, the more +numerous the VID pins.) The VID codes are defined by Intel in documents +titled "VRM X.X DC-DC Converter Design Guidelines". +(VRM = Voltage Regulator Module), or +"Voltage Regulator-Down (VRD) X.X Design Guide". +These documents are available at http://developer.intel.com. +There are equivalent documents for AMD processors (look for a table +named "VID Code Voltages" in processor specifications.) + +There are several different VRM document versions. +The common versions are as follows: + +Document Version Voltage Range Increment Processors +---------------- ------------- --------- ---------- +"2.4" 0.8 - 1.55 0.025V AMD Opteron 24x + +8.2 (8.1, 8.3) 1.30 - 2.05V 0.05V PII, PIII, Celeron + 2.1 - 3.5V 0.10V + +8.4 1.30 - 2.05V 0.05V PIII, Celeron + 4 pins only + +8.5 1.050 - 1.825V 0.05V PIII-S Tualatin + +9.0, (9.1) 1.100 - 1.850V 0.025V P4, AMD Socket A + +10.0 0.8375 - 1.6000 0.0125V Desktop Socket 478 + + +"2.4" is not an actual document version but simply a way to identify +AMD Opteron 24x processors. +Note that versions 8.1 - 8.4 are compatible. + +Since Linux 2.6.9, the correct VRM version is selected automatically +based on the CPU brand and model. Thus you shouldn't have to care about +it. If you are using a brand new CPU and even the latest kernel complains +("Unknown VRM version of your CPU"), this means that the kernel must be +taught about this new CPU model. Please report to us in this case. + +Remember, the VID pins on the sensor chips are inputs only. +You cannot use them to manipulate the actual processor core voltage. + +------------------ +Copyright (c) 2002-2004 Mark D. Studebaker diff --git a/etc/Module.mk b/etc/Module.mk new file mode 100644 index 0000000..6a27392 --- /dev/null +++ b/etc/Module.mk @@ -0,0 +1,44 @@ +# Module.mk - Makefile for a Linux module for reading sensor data. +# Copyright (c) 1998, 1999 Frodo Looijaard +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. + +# Note: Don't confuse ETC_DIR (the directory in which this file resides) +# with ETCDIR (the system directory in which configuration files will be +# installed; typically /etc). +ETC_DIR := etc + +install-etc: + $(MKDIR) $(DESTDIR)$(ETCDIR) $(DESTDIR)$(ETCDIR)/sensors.d + if [ ! -e $(DESTDIR)$(ETCDIR)/sensors3.conf ] ; then \ + $(INSTALL) -m 644 $(ETC_DIR)/sensors.conf.default $(DESTDIR)$(ETCDIR)/sensors3.conf ; \ + fi + $(MKDIR) $(DESTDIR)$(BINDIR) + $(INSTALL) -m 755 $(ETC_DIR)/sensors-conf-convert $(DESTDIR)$(BINDIR) + if [ -e $(DESTDIR)$(ETCDIR)/modprobe.d/lm_sensors \ + -a ! -e $(DESTDIR)$(ETCDIR)/modprobe.d/lm_sensors.conf ] ; then \ + $(MV) $(DESTDIR)$(ETCDIR)/modprobe.d/lm_sensors $(DESTDIR)$(ETCDIR)/modprobe.d/lm_sensors.conf ; \ + fi + $(MKDIR) $(DESTDIR)$(MANDIR)/man8 + $(INSTALL) -m 644 $(ETC_DIR)/sensors-conf-convert.8 $(DESTDIR)$(MANDIR)/man8 + +user_install :: install-etc + +uninstall-etc: + $(RM) $(DESTDIR)$(BINDIR)/sensors-conf-convert + $(RM) $(DESTDIR)$(MANDIR)/man8/sensors-conf-convert.8 + +user_uninstall :: uninstall-etc diff --git a/etc/sensors-conf-convert b/etc/sensors-conf-convert new file mode 100755 index 0000000..8e8a03e --- /dev/null +++ b/etc/sensors-conf-convert @@ -0,0 +1,482 @@ +#!/usr/bin/perl -w -pi.old + +# Convert a sensors.conf file from the old (Linux 2.4, lm-sensors 2) +# symbol names to the new (Linux 2.6 or 3, lm-sensors 3) symbol names. +# +# Copyright (C) 2007, 2011 Jean Delvare +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +# Implemented conversions: +# * The "algorithm name" part of bus statements is removed. +# * Bus statements for the ISA bus are removed. +# * Chip names containing dashes are removed. +# * Label, ignore, set and compute statements referencing features +# which are not part of the new interface are removed. +# * Label, ignore, set and compute statements referencing features +# which have been renamed are updated. This includes both general +# feature name changes and chip-specific feature name changes. +# +# Note that we have to look at the commented out lines too, so that +# the user doesn't have a bad surprise when uncommenting them. + +use strict; +use vars qw($debug $chip %trans @delete %chip_trans %chip_delete); + +BEGIN +{ + $debug = 0; + + %trans = ( + qr/\bvid\b/ => sub { "cpu0_vid" }, + qr/\bremote_temp\b/ => sub { "temp2" }, + qr/\bremote_temp_hyst\b/ => sub { "temp2_max_hyst" }, + qr/\bremote_temp_low\b/ => sub { "temp2_min" }, + qr/\bremote_temp_over\b/ => sub { "temp2_max" }, + qr/\btemp\b/ => sub { "temp1" }, + qr/\btemp_hyst\b/ => sub { "temp1_max_hyst" }, + qr/\btemp_low\b/ => sub { "temp1_min" }, + qr/\btemp_over\b/ => sub { "temp1_max" }, + qr/\btemp_high\b/ => sub { "temp1_max" }, + qr/\btemp_crit\b/ => sub { "temp1_crit" }, + + qr/\bvin(\d+)_max\b/ => sub { "in$1_max" }, + qr/\bvin(\d+)_min\b/ => sub { "in$1_min" }, + qr/\bvin(\d+)\b/ => sub { "in$1" }, + qr/\btemp(\d+)_over\b/ => sub { "temp$1_max" }, + qr/\btemp(\d+)_hyst\b/ => sub { "temp$1_max_hyst" }, + qr/\btemp(\d+)_high\b/ => sub { "temp$1_max" }, + qr/\btemp(\d+)_low\b/ => sub { "temp$1_min" }, + qr/\bsensor(\d+)\b/ => sub { "temp$1_type" }, + ); + + @delete = ( + qr/\balarms\b/, + qr/\bbeeps\b/, + qr/\bpwm\d*\b/, + qr/\bpwm\d+_enable\b/, + qr/\b(in|temp|fan)\d+_(state|status)\b/, + qr/\banalog_out\b/, + qr/\balarms_(in|temp|fan)\b/, + ); + + %chip_trans = ( + "gl518sm" => { + qr/\bvdd\b/ => sub { "in0" }, + qr/\bvdd_min\b/ => sub { "in0_min" }, + qr/\bvdd_max\b/ => sub { "in0_max" }, + }, + "gl520sm" => { + qr/\bvdd\b/ => sub { "in0" }, + qr/\bvdd_min\b/ => sub { "in0_min" }, + qr/\bvdd_max\b/ => sub { "in0_max" }, + }, + "lm80" => { + qr/\btemp_hot_hyst\b/ => sub { "temp1_max_hyst" }, + qr/\btemp_hot_max\b/ => sub { "temp1_max" }, + qr/\btemp_os_hyst\b/ => sub { "temp1_crit_hyst" }, + qr/\btemp_os_max\b/ => sub { "temp1_crit" }, + }, + "lm83" => { + qr/\btcrit\b/ => sub { "temp3_crit" }, + }, + "lm90" => { + qr/\btcrit(\d)\b/ => sub { "temp$1_crit" }, + qr/\bhyst(\d)\b/ => sub { "temp$1_crit_hyst" }, + }, + "adm1032" => { + qr/\btcrit(\d)\b/ => sub { "temp$1_crit" }, + qr/\bhyst(\d)\b/ => sub { "temp$1_crit_hyst" }, + }, + "lm86" => { + qr/\btcrit(\d)\b/ => sub { "temp$1_crit" }, + qr/\bhyst(\d)\b/ => sub { "temp$1_crit_hyst" }, + }, + "lm99" => { + qr/\btcrit(\d)\b/ => sub { "temp$1_crit" }, + qr/\bhyst(\d)\b/ => sub { "temp$1_crit_hyst" }, + }, + "adt7461" => { + qr/\btcrit(\d)\b/ => sub { "temp$1_crit" }, + qr/\bhyst(\d)\b/ => sub { "temp$1_crit_hyst" }, + }, + "max6657" => { + qr/\btcrit(\d)\b/ => sub { "temp$1_crit" }, + qr/\bhyst(\d)\b/ => sub { "temp$1_crit_hyst" }, + }, + "max6680" => { + qr/\btcrit(\d)\b/ => sub { "temp$1_crit" }, + qr/\bhyst(\d)\b/ => sub { "temp$1_crit_hyst" }, + }, + "lm93" => { + qr/\bvid([12])\b/ => sub { "cpu".($1-1)."_vid" }, + }, + "adm9240" => { + qr/"2\.5V(|_min|_max)"/ => sub { "in0$1" }, + qr/\bVccp1(|_min|_max)\b/ => sub { "in1$1" }, + qr/"3\.3V(|_min|_max)"/ => sub { "in2$1" }, + qr/"5V(|_min|_max)"/ => sub { "in3$1" }, + qr/"12V(|_min|_max)"/ => sub { "in4$1" }, + qr/\bVccp2(|_min|_max)\b/ => sub { "in5$1" }, + }, + "lm81" => { + qr/"2\.5V(|_min|_max)"/ => sub { "in0$1" }, + qr/\bVccp1(|_min|_max)\b/ => sub { "in1$1" }, + qr/"3\.3V(|_min|_max)"/ => sub { "in2$1" }, + qr/"5V(|_min|_max)"/ => sub { "in3$1" }, + qr/"12V(|_min|_max)"/ => sub { "in4$1" }, + qr/\bVccp2(|_min|_max)\b/ => sub { "in5$1" }, + }, + "ds1780" => { + qr/"2\.5V(|_min|_max)"/ => sub { "in0$1" }, + qr/\bVccp1(|_min|_max)\b/ => sub { "in1$1" }, + qr/"3\.3V(|_min|_max)"/ => sub { "in2$1" }, + qr/"5V(|_min|_max)"/ => sub { "in3$1" }, + qr/"12V(|_min|_max)"/ => sub { "in4$1" }, + qr/\bVccp2(|_min|_max)\b/ => sub { "in5$1" }, + }, + "adm1024" => { + qr/"2\.5V(|_min|_max)"/ => sub { "in0$1" }, + qr/\bVccp1(|_min|_max)\b/ => sub { "in1$1" }, + qr/"3\.3V(|_min|_max)"/ => sub { "in2$1" }, + qr/"5V(|_min|_max)"/ => sub { "in3$1" }, + qr/"12V(|_min|_max)"/ => sub { "in4$1" }, + qr/\bVccp2(|_min|_max)\b/ => sub { "in5$1" }, + qr/\btemp_hyst\b/ => sub { "temp1_min" }, + qr/\btemp(\d)\b/ => sub { "temp".($1+1) }, + qr/\btemp(\d)_hyst\b/ => sub { "temp".($1+1)."_min" }, + qr/\btemp(\d)_over\b/ => sub { "temp".($1+1)."_max" }, + }, + "maxilife" => { + qr/\bvid(\d)(|_min|_max)\b/ => sub { "in".($1-1).$2 }, + }, + "thmc50" => { + qr/\btemp_hyst\b/ => sub { "temp1_min" }, + qr/\bremote_temp_hyst\b/ => sub { "temp2_min" }, + qr/\bremote_temp2\b/ => sub { "temp3" }, + qr/\bremote_temp2_hyst\b/ => sub { "temp3_min" }, + qr/\bremote_temp2_over\b/ => sub { "temp3_max" }, + }, + "adm1022" => { + qr/\btemp_hyst\b/ => sub { "temp1_min" }, + qr/\bremote_temp_hyst\b/ => sub { "temp2_min" }, + qr/\bremote_temp2\b/ => sub { "temp3" }, + qr/\bremote_temp2_hyst\b/ => sub { "temp3_min" }, + qr/\bremote_temp2_over\b/ => sub { "temp3_max" }, + }, + "adm1026" => { + qr/\bfan(\d)(|_div|_min)\b/ => sub { "fan".($1+1).$2 }, + qr/\btemp(\d)_therm\b/ => sub { "temp$1_crit" }, + }, + "via686a" => { + qr/"2\.0V"/ => sub { "in0" }, + qr/"2\.5V"/ => sub { "in1" }, + qr/"3\.3V"/ => sub { "in2" }, + qr/"5\.0V"/ => sub { "in3" }, + qr/"12V"/ => sub { "in4" }, + }, + "lm87" => { + qr/"2\.5V(|_min|_max)"/ => sub { "in0$1" }, + qr/\bVccp1(|_min|_max)\b/ => sub { "in1$1" }, + qr/"3\.3V(|_min|_max)"/ => sub { "in2$1" }, + qr/"5V(|_min|_max)"/ => sub { "in3$1" }, + qr/"12V(|_min|_max)"/ => sub { "in4$1" }, + qr/\bVccp2(|_min|_max)\b/ => sub { "in5$1" }, + qr/\bAIN1(|_min|_max)\b/ => sub { "in6$1" }, + qr/\bAIN2(|_min|_max)\b/ => sub { "in7$1" }, + qr/\bCPU_Temp\b/ => sub { "temp2" }, + }, + "fscpos" => { + qr/\bvolt12\b/ => sub { "in0" }, + qr/\bvolt5\b/ => sub { "in1" }, + qr/\bvoltbatt\b/ => sub { "in2" }, + }, + "fscscy" => { + qr/\bvolt12\b/ => sub { "in0" }, + qr/\bvolt5\b/ => sub { "in1" }, + qr/\bvoltbatt\b/ => sub { "in2" }, + }, + "pcf8591" => { + qr/\bch(\d)\b/ => sub { "in$1" }, + }, + "smsc47m192" => { + qr/\btemp(\d)_input_fault\b/ => sub { "temp$1_fault" }, + }, + "lm92" => { + qr/\btemp_hyst\b/ => sub { "temp1_crit_hyst" }, + }, + "max1619" => { + qr/\btemp2_hyst\b/ => sub { "temp2_crit_hyst" }, + }, + "lm78" => { + qr/\bin([56])_(min|max)\b/ => sub { "in$1_".($2 eq "max" ? "min" : "max") }, + }, + "lm79" => { + qr/\bin([56])_(min|max)\b/ => sub { "in$1_".($2 eq "max" ? "min" : "max") }, + }, + "w83781d" => { + qr/\bin([56])_(min|max)\b/ => sub { "in$1_".($2 eq "max" ? "min" : "max") }, + }, + "as99127f" => { + qr/\bin([56])_(min|max)\b/ => sub { "in$1_".($2 eq "max" ? "min" : "max") }, + }, + ); + + %chip_delete = ( + "adm1021" => [ + qr/\bdie_code\b/, + ], + "lm84" => [ + qr/\bdie_code\b/, + ], + "gl523" => [ + qr/\bdie_code\b/, + ], + "thmc10" => [ + qr/\bdie_code\b/, + ], + "gl518sm" => [ + qr/\bfan1_off\b/, + qr/\bfan1_off_pin\b/, + qr/\biterate\b/, + ], + "gl520sm" => [ + qr/\bfan1_off\b/, + qr/\btwo_temps\b/, + ], + "w83792d" => [ + qr/\bchassis\b/, + ], + "w83793" => [ + qr/\bchassis\b/, + ], + "maxilife" => [ + qr/\bpll(|_min|_max)\b/, + ], + "thmc50" => [ + qr/\banalog output\b/, + qr/\binterrupts\b/, + qr/\binterrupt mask\b/, + qr/\bdie_code\b/, + ], + "adm1022" => [ + qr/\banalog output\b/, + qr/\binterrupts\b/, + qr/\binterrupt mask\b/, + qr/\bdie_code\b/, + ], + "adm1026" => [ + qr/\balarm_mask\b/, + qr/\bgpio\b/, + qr/\bgpio_mask\b/, + qr/\bafc_pwm\b/, + qr/\bafc_analog_out\b/, + qr/\btemp\d_tmin\b/, + ], + "lm85" => [ + qr/\bpwm\d_(spinup|min|freq|min_ctl|zone|spinup_ctl)\b/, + qr/\bzone\d_(limit|hyst|range|critical|smooth)\b/, + qr/\bfan\d_(tach_mode|ppr)\b/, + ], + "lm85b" => [ + qr/\bpwm\d_(spinup|min|freq|min_ctl|zone|spinup_ctl)\b/, + qr/\bzone\d_(limit|hyst|range|critical|smooth)\b/, + qr/\bfan\d_(tach_mode|ppr)\b/, + ], + "lm85c" => [ + qr/\bpwm\d_(spinup|min|freq|min_ctl|zone|spinup_ctl)\b/, + qr/\bzone\d_(limit|hyst|range|critical|smooth)\b/, + qr/\bfan\d_(tach_mode|ppr)\b/, + ], + "emc6d100" => [ + qr/\bpwm\d_(spinup|min|freq|min_ctl|zone|spinup_ctl)\b/, + qr/\bzone\d_(limit|hyst|range|critical|smooth)\b/, + qr/\bfan\d_(tach_mode|ppr)\b/, + ], + "emc6d102" => [ + qr/\bpwm\d_(spinup|min|freq|min_ctl|zone|spinup_ctl)\b/, + qr/\bzone\d_(limit|hyst|range|critical|smooth)\b/, + qr/\bfan\d_(tach_mode|ppr)\b/, + ], + "adm1027" => [ + qr/\bpwm\d_(spinup|min|freq|min_ctl|zone|spinup_ctl)\b/, + qr/\bzone\d_(limit|hyst|range|critical|smooth)\b/, + qr/\bfan\d_(tach_mode|ppr)\b/, + ], + "adt7473" => [ + qr/\bpwm\d_(spinup|min|freq|min_ctl|zone|spinup_ctl)\b/, + qr/\bzone\d_(limit|hyst|range|critical|smooth)\b/, + qr/\bfan\d_(tach_mode|ppr)\b/, + ], + "fscpos" => [ + qr/\brev\b/, + qr/\bevent\b/, + qr/\bcontrol\b/, + qr/\bfan\d_ripple\b/, + qr/\bwdog_(preset|state|control)\b/, + ], + "fscscy" => [ + qr/\brev\b/, + qr/\bevent\b/, + qr/\bcontrol\b/, + qr/\btemp\d_lim\b/, + qr/\bfan\d_ripple\b/, + qr/\bwdog_(preset|state|control)\b/, + ], + "fscher" => [ + qr/\brev\b/, + qr/\bevent\b/, + qr/\bcontrol\b/, + qr/\bfan\d_ripple\b/, + qr/\bwdog_(preset|state|control)\b/, + ], + "pcf8591" => [ + qr/\bain_conf\b/, + qr/\baout_enable\b/, + qr/\baout\b/, + ], + "vt1211" => [ + qr/\bconfig\b/, + ], + "vt8231" => [ + qr/\bconfig\b/, + ], + "max6650" => [ + qr/\bspeed\b/, + ], + "max6651" => [ + qr/\bspeed\b/, + ], + "applesmc" => [ + qr/\bfan\d_(max|safe)\b/, + ], + ); + + if (defined $ARGV[0] && ($ARGV[0] eq '-h' || $ARGV[0] eq '--help')) { + print "Convert sensors.conf from lm-sensors 2 format to lm-sensors 3 format\n", + "Typical usage: sensors-conf-convert < /etc/sensors.conf > /etc/sensors3.conf\n"; + exit 0; + } +} + +if ($. == 1) { + print "# Converted by sensors-conf-convert on ".localtime()."\n"; +} + +sub substitute_line($$) +{ + my ($chip, $line) = @_; + + # First the chip-specific ones + if ($chip && exists $chip_trans{$chip}) { + foreach my $t (keys %{$chip_trans{$chip}}) { + $line =~ s/$t/$chip_trans{$chip}->{$t}->()/ge; + } + } + + # Then the general substitutions + foreach my $t (keys %trans) { + # Kudos to the nice folks in #perl on freenode :) + $line =~ s/$t/$trans{$t}->()/ge; + } + + return $line; +} + +sub delete_line($) +{ + my $feature = shift; + + # First the general deletions + foreach my $t (@delete) { + return 1 if $feature =~ m/$t/; + } + + # Then the chip-specific ones + if ($chip && exists $chip_delete{$chip}) { + foreach my $t (@{$chip_delete{$chip}}) { + return 1 if $feature =~ m/$t/; + } + } + + return 0; +} + +if (m/^# Converted by sensors-conf-convert/) { + print STDERR "WARNING: Converting an already converted file!\n"; + print STDERR " Result will be incorrect for some chip types.\n"; +} + +# Bus statements +if (m/^([\s#]*bus\s+"?i2c-\d+"?\s+"([^"]+)")\s+"[^"]*"/) { + print STDERR "Processing bus statement: $2\n" if $debug; + + if ($2 eq "ISA main adapter") { + $_ = ''; # Drop entirely + } else { + $_ = "$1\n"; # Drop algorithm name + } +} + +# Chip statements +elsif (m/^[\s#]*chip\s+"([\w\d*-]+)"/) { + # We only remember the first chip name, assuming that all chips + # in a given "chip" statement need the same specific processing + $chip = $1; + $chip =~ s/-.*//; + undef $chip if $chip eq "*"; + + # Remove dashes from chip names, as this is no longer allowed + s/(\s+"lm78-)j-/$1/g; + s/(\s+"maxilife-)(cg|co|as|nba)-/$1/g; + # Simplify possible duplicates + s/("lm78-\*")(\s+"lm78-\*")+/$1/g; + s/("maxilife-\*")(\s+"maxilife-\*")+/$1/g; + + # "*" is no longer a valid chip name + s/"\*"/"\*-\*"/g; + + print STDERR "Processing chip section: $chip\n" if $chip and $debug; +} + +# Drop references to lm78-j +elsif (m/^\s*#+.*lm78-?j/i) { + s/(lm78), lm78-?j/$1/gi; + s/(lm78)-?j/$1/gi; +} + +# Drop references to vrm +elsif (m/^[\s#]*set\s+vrm\s/i + || m/^\s*#+\s*adjust this if your vid is wrong/i + || m/^\s*#+\s*Also, one should set vrm prior to using vid in any formula/) { + $_ = ''; +} + +# Drop references to pwm +elsif (m/^\s*#+\s*PWM Output/i) { + $_ = ''; +} + +# Feature name substitution +elsif (m/^[\s#]*(?:label|ignore|set|compute)\s+(\S+)\s/) { + if (delete_line($1)) { + # Delete references to features that are now gone + $_ = ''; + } else { + # Substitute feature names + $_ = substitute_line($chip, $_); + } +} diff --git a/etc/sensors-conf-convert.8 b/etc/sensors-conf-convert.8 new file mode 100644 index 0000000..34f672e --- /dev/null +++ b/etc/sensors-conf-convert.8 @@ -0,0 +1,27 @@ +.TH SENSORS-CONF-CONVERT 8 "August 2013" "lm-sensors 3" +.SH NAME +sensors-conf-convert \- sensors configuration conversion + +.SH SYNOPSIS +.B sensors-conf-convert +< +.I /etc/sensors.conf +> +.I /etc/sensors3.conf + +.SH DESCRIPTION +The purpose of the +.B sensors-conf-convert +tool is to convert +.I sensors.conf +from the lm_sensors version 2 format to the lm_sensors +version 3 format. +.P +The old configuration file is read from the standard input and the +new one is written to the standard output. + +.SH SEE ALSO +sensors(1), libsensors(3) + +.SH AUTHOR +Jean Delvare diff --git a/etc/sensors.conf.default b/etc/sensors.conf.default new file mode 100644 index 0000000..e9e1441 --- /dev/null +++ b/etc/sensors.conf.default @@ -0,0 +1,535 @@ +# libsensors configuration file +# ----------------------------- +# +# This default configuration file only includes statements which do not +# differ from one mainboard to the next. Only label, compute and set +# statements for internal voltage and temperature sensors are included. +# +# In general, local changes should not be added to this file, but rather +# placed in custom configuration files located in /etc/sensors.d. This +# approach makes further updates much easier. +# +# Such custom configuration files for specific mainboards can be found in +# "configs" directory of lm-sensors package. +# +# Please contribute back a configuration of your board so other users with +# the same hardware won't need to recreate it again and again. + +chip "lm78-*" "lm79-*" "lm80-*" "lm96080-*" + + label temp1 "M/B Temp" + + +chip "w83792d-*" + + label in0 "VcoreA" + label in1 "VcoreB" + label in6 "+5V" + label in7 "5VSB" + label in8 "Vbat" + + set in6_min 5.0 * 0.90 + set in6_max 5.0 * 1.10 + set in7_min 5.0 * 0.90 + set in7_max 5.0 * 1.10 + set in8_min 3.0 * 0.90 + set in8_max 3.0 * 1.10 + + +chip "w83793-*" + + label in0 "VcoreA" + label in1 "VcoreB" + label in7 "+5V" + label in8 "5VSB" + label in9 "Vbat" + + set in7_min 5.0 * 0.90 + set in7_max 5.0 * 1.10 + set in8_min 5.0 * 0.90 + set in8_max 5.0 * 1.10 + set in9_min 3.0 * 0.90 + set in9_max 3.0 * 1.10 + + +chip "w83795g-*" "w83795adg-*" + + label in12 "+3.3V" + label in13 "3VSB" + label in14 "Vbat" + + set in12_min 3.3 * 0.90 + set in12_max 3.3 * 1.10 + set in13_min 3.3 * 0.90 + set in13_max 3.3 * 1.10 + set in14_min 3.0 * 0.90 + set in14_max 3.3 * 1.10 + + +chip "via686a-*" + + label in0 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + set in4_min 12.0 * 0.90 + set in4_max 12.0 * 1.10 + + +chip "adm1025-*" "ne1619-*" + + label in1 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "VCC" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + set in5_min 3.3 * 0.90 + set in5_max 3.3 * 1.10 +# Depending on how your chip is hardwired, you may or may not have +# +12V readings. +# set in4_min 12.0 * 0.90 +# set in4_max 12.0 * 1.10 + + label temp1 "CPU Temp" + label temp2 "M/B Temp" + + +chip "lm87-*" "adm1024-*" + + label in1 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + set in4_min 12.0 * 0.90 + set in4_max 12.0 * 1.10 + + label temp1 "M/B Temp" + label temp2 "CPU Temp" + + +chip "it87-*" "it8712-*" "it8716-*" "it8718-*" "it8720-*" + + label in8 "Vbat" + + +chip "fscpos-*" "fscher-*" +#FSC "Hermes" + + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + + label temp1 "CPU Temp" + label temp2 "M/B Temp" + label temp3 "Aux Temp" + + +chip "fscscy-*" +#FSC "Scylla" + + label in0 "+12V" + label in1 "+5V" + label in2 "+3.3V" + + label temp1 "CPU0 Temp" + label temp2 "CPU1 Temp" + label temp3 "M/B Temp" + label temp4 "Aux Temp" + + +chip "fschds-*" +# Fujitsu Technology Solutions, "Hades"-Chip + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Super I/O Temp" + label temp3 "System Temp" + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "System FAN2" + label fan4 "System FAN3" + label fan5 "System FAN4" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + +chip "fscsyl-*" +# Fujitsu Technology Solutions, "Syleus"-Chip + +# Temperatures + label temp1 "CPU Temp" + label temp4 "Super I/O Temp" + label temp5 "Northbridge Temp" + +# Fans + label fan1 "CPU Fan" + label fan2 "System FAN2" + label fan3 "System FAN3" + label fan4 "System FAN4" + label fan7 "PSU Fan" + +# Voltages + label in0 "+12V" + label in1 "+5V" + label in2 "Vbat" + label in3 "+3.3V" + label in5 "+3.3V-Aux" + +chip "vt1211-*" + + label in5 "+3.3V" + + label temp2 "SIO Temp" + + +chip "vt8231-*" + + label in5 "+3.3V" + + +chip "smsc47m192-*" + + label in1 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "VCC" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + set in4_min 12.0 * 0.90 + set in4_max 12.0 * 1.10 + set in5_min 3.3 * 0.90 + set in5_max 3.3 * 1.10 + + label temp1 "SIO Temp" + + +chip "lm85-*" "lm85b-*" "lm85c-*" "adm1027-*" "adt7463-*" "adt7468-*" \ + "emc6d100-*" "emc6d102-*" "emc6d103-*" "emc6d103s-*" + + label in1 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 +# Depending on how your chip is hardwired, you may or may not have +# +12V readings. +# set in4_min 12.0 * 0.90 +# set in4_max 12.0 * 1.10 + + label temp2 "M/B Temp" + + +chip "emc6w201-*" + + label in2 "+3.3V" + label in3 "+5V" + + label temp6 "M/B Temp" + + +chip "pc87365-*" "pc87366-*" + +# Voltage inputs + + label in7 "3VSB" + label in8 "VDD" + label in9 "Vbat" + label in10 "AVDD" + + compute in7 @*2, @/2 + compute in8 @*2, @/2 + compute in10 @*2, @/2 + +# These are the operating conditions as recommended by National +# Semiconductor + set in7_min 3.0 + set in7_max 3.6 + set in8_min 3.0 + set in8_max 3.6 + set in10_min 3.0 + set in10_max 3.6 +# Depending on the hardware setup, the battery voltage may or may not +# be monitored. +# set in9_min 2.4 +# set in9_max 3.6 + + label temp3 "SIO Temp" + + set temp3_min 0 + set temp3_max 70 + set temp3_crit 85 + + +chip "adm1030-*" "adm1031-*" + + label temp1 "M/B Temp" + + +chip "w83627thf-*" + + label in3 "+5V" + label in7 "5VSB" + label in8 "Vbat" + + # Internal resistors + compute in3 @ * (1 + 34/51), @ / (1 + 34/51) + compute in7 @ * (1 + 34/51), @ / (1 + 34/51) + + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + set in7_min 5.0 * 0.90 + set in7_max 5.0 * 1.10 +# The battery voltage may or may not be monitored. +# set in8_min 3.0 * 0.90 +# set in8_max 3.0 * 1.10 + + +chip "w83627ehf-*" "w83627dhg-*" "w83667hg-*" "nct6775-*" "nct6776-*" "nct6779-*" "nct6791-*" "nct6795-*" + + label in0 "Vcore" + label in2 "AVCC" + label in3 "+3.3V" + label in7 "3VSB" + label in8 "Vbat" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 3.3 * 0.90 + set in3_max 3.3 * 1.10 + set in7_min 3.3 * 0.90 + set in7_max 3.3 * 1.10 + set in8_min 3.0 * 0.90 + set in8_max 3.3 * 1.10 + + +chip "w83627uhg-*" + + label in2 "AVCC" + label in3 "+5V" + label in7 "5VSB" + label in8 "Vbat" + + set in2_min 5.0 * 0.90 + set in2_max 5.0 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + set in7_min 5.0 * 0.90 + set in7_max 5.0 * 1.10 + set in8_min 3.0 * 0.90 + set in8_max 3.3 * 1.10 + + +chip "f71805f-*" + + label in0 "+3.3V" + + set in0_min 3.3 * 0.90 + set in0_max 3.3 * 1.10 + + +chip "f71872f-*" + + label in0 "+3.3V" + label in9 "Vbat" + label in10 "3VSB" + + set in0_min 3.3 * 0.90 + set in0_max 3.3 * 1.10 + set in9_min 3.0 * 0.90 + set in9_max 3.0 * 1.10 + set in10_min 3.3 * 0.90 + set in10_max 3.3 * 1.10 + + +chip "k8temp-*" + + label temp1 "Core0 Temp" + label temp2 "Core0 Temp" + label temp3 "Core1 Temp" + label temp4 "Core1 Temp" + + +chip "dme1737-*" + + label in0 "5VSB" + label in1 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "3VSB" + label in6 "Vbat" + + label temp2 "SIO Temp" + + set in0_min 5.0 * 0.90 + set in0_max 5.0 * 1.10 + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + set in4_min 12.0 * 0.90 + set in4_max 12.0 * 1.10 + set in5_min 3.3 * 0.90 + set in5_max 3.3 * 1.10 + set in6_min 3.0 * 0.90 + set in6_max 3.0 * 1.10 + + +chip "sch311x-*" + + label in1 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "3VSB" + label in6 "Vbat" + + label temp2 "SIO Temp" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 + set in4_min 12.0 * 0.90 + set in4_max 12.0 * 1.10 + set in5_min 3.3 * 0.90 + set in5_max 3.3 * 1.10 + set in6_min 3.0 * 0.90 + set in6_max 3.0 * 1.10 + + +chip "sch5027-*" + + label in0 "5VSB" + label in1 "Vcore" + label in2 "+3.3V" + label in5 "3VSB" + label in6 "Vbat" + + label temp2 "SIO Temp" + + set in0_min 5.0 * 0.90 + set in0_max 5.0 * 1.10 + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in5_min 3.3 * 0.90 + set in5_max 3.3 * 1.10 + set in6_min 3.0 * 0.90 + set in6_max 3.0 * 1.10 + + +chip "sch5127-*" + + label in2 "+3.3V" + label in5 "3VSB" + label in6 "Vbat" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in5_min 3.3 * 0.90 + set in5_max 3.3 * 1.10 + set in6_min 3.0 * 0.90 + set in6_max 3.0 * 1.10 + + +chip "f71808e-*" "f71808a-*" "f71862fg-*" "f71869-*" "f71869a-*" "f71882fg-*" \ + "f71889fg-*" "f71889ed-*" "f71889a-*" + + label in0 "+3.3V" + label in7 "3VSB" + label in8 "Vbat" + + compute in0 @*2, @/2 + compute in7 @*2, @/2 + compute in8 @*2, @/2 + + +chip "f71858fg-*" "f8000-*" + + label in0 "+3.3V" + label in1 "3VSB" + label in2 "Vbat" + + compute in0 @*2, @/2 + compute in1 @*2, @/2 + compute in2 @*2, @/2 + + +chip "f71868a-*" + + label in0 "+3.3V" + label in7 "3VSB" + label in8 "Vbat" + label in9 "5VSB" + + compute in0 @*2, @/2 + compute in7 @*2, @/2 + compute in8 @*2, @/2 + compute in9 @*3, @/3 + + +chip "f81865f-*" + + label in0 "+3.3V" + label in5 "3VSB" + label in6 "Vbat" + + compute in0 @*2, @/2 + compute in5 @*2, @/2 + compute in6 @*2, @/2 + + +chip "adt7473-*" "adt7475-*" + + label in2 "+3.3V" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + + label temp2 "Board Temp" + + +chip "adt7476-*" "adt7490-*" + + label in1 "Vcore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + + set in2_min 3.3 * 0.90 + set in2_max 3.3 * 1.10 + set in3_min 5.0 * 0.90 + set in3_max 5.0 * 1.10 +# Depending on how your ADT7476 is hardwired, you may or may not have +# +12V readings. +# set in4_min 12.0 * 0.90 +# set in4_max 12.0 * 1.10 + + label temp2 "M/B Temp" diff --git a/etc/sensors.conf.eg b/etc/sensors.conf.eg new file mode 100644 index 0000000..1bd3935 --- /dev/null +++ b/etc/sensors.conf.eg @@ -0,0 +1,2174 @@ +# libsensors configuration file +# ----------------------------- +# NOTE: +# All the set statements from this file are commented out by default. +# The reason is that the proper limits are highly system-dependent, +# and writing improper limits may have all sorts of weird effects, +# from beeping to CPU throttling to instant reboot. If you want to +# actually set the limits, remove the comment marks, then run "sensors -s". +# +# This is a legacy example file. In general, configurations for new boards +# should be placed in custom configuration files located in /etc/sensors.d. + +chip "lm78-*" "lm79-*" "w83781d-*" + +# These are as advised in the LM78 and LM79 data sheets, and used on almost +# any mainboard we have seen. + + label in0 "VCore 1" + label in1 "VCore 2" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "-12V" + label in6 "-5V" + +# For positive voltages (in3, in4), two resistors are used, with the following +# formula (R1,R2: resistor values, Vs: read voltage, Vin: pin voltage) +# R1 = R2 * (Vs/Vin - 1) +# For negative voltages (in5, in6) two resistors are used, with the following +# formula (Rin,Rf: resistor values, Vs: read voltage, Vin: pin voltage) +# Rin = (Vs * Rf) / Vin +# +# Here are the official LM78 and LM79 data sheet values. +# Vs R1,Rin R2,Rf Vin +# in3 +5.0 6.8 10 +2.98 +# in4 +12.0 30 10 +3.00 +# in5 -12.0 240 60 +3.00 +# in6 -5.0 100 60 +3.00 +# +# These would lead to these declarations: +# compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) +# compute in4 ((30/10)+1)*@ , @/((30/10)+1) +# compute in5 -(240/60)*@ , -@/(240/60) +# compute in6 -(100/60)*@ , -@/(100/60) +# +# On almost any mainboard we have seen, the Winbond compute values lead to +# much better results, though. +# +# Vs R1,Rin R2,Rf Vin +# in4 +12.0 28 10 +3.15 +# in5 -12.0 210 60.4 +3.45 +# in6 -5.0 90.9 60.4 +3.33 +# +# These leads to these declarations: + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((28/10)+1)*@ , @/((28/10)+1) + compute in5 -(210/60.4)*@ , -@/(210/60.4) + compute in6 -(90.9/60.4)*@ , -@/(90.9/60.4) + +# Here, we assume the VID readings are valid, and we use a max. 5% deviation + +# set in0_min cpu0_vid*0.95 +# set in0_max cpu0_vid*1.05 +# set in1_min cpu0_vid*0.95 +# set in1_max cpu0_vid*1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12 * 0.95 +# set in4_max 12 * 1.05 +# set in5_min -12 * 0.95 +# set in5_max -12 * 1.05 +# set in6_min -5 * 0.95 +# set in6_max -5 * 1.05 + +# Examples for lm78, lm79 temperature limits +# set temp1_max 40 +# set temp1_max_hyst 37 + +# Examples for w83781d temperature limits +# set temp1_max 40 +# set temp1_max_hyst 37 +# set temp2_max 52 +# set temp2_max_hyst 47 +# set temp3_max 52 +# set temp3_max_hyst 47 + +# Examples of fan low speed limits +# set fan1_min 3000 +# set fan2_min 3000 +# set fan3_min 3000 + +# Ignore fans you don't actually have +# ignore fan1 +# ignore fan2 +# ignore fan3 + +# In case a lm78 is used together with a lm75, the lm78 temp sensor will +# generally show the M/B temperature while the lm75 temp sensor will show +# the CPU temperature. +# label temp1 "M/B Temp" + +# Uncomment the following line to enable beeps for all alarms on this chip +# set beep_enable 1 + + + +chip "lm75-*" + +# Most boards don't need scaling. Following is for the Asus TX97-E. +# compute temp1 @*2.0, @/2.0 + +# Examples for temperature limits +# set temp1_max 70 +# set temp1_max_hyst 65 + +# In case a lm75 is used together with a lm78, the lm78 temp sensor will +# generally show the M/B temperature while the lm75 temp sensor will show +# the CPU temperature. +# label temp1 "CPU Temp" + + +chip "sis5595-*" + + label in0 "VCore 1" + label in1 "VCore 2" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((28/10)+1)*@ , @/((28/10)+1) + +# set in0_min 2.0 * 0.95 +# set in0_max 2.0 * 1.05 +# set in1_min 2.0 * 0.95 +# set in1_max 2.0 * 1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12 * 0.95 +# set in4_max 12 * 1.05 + +# +# SiS5595 temperature calculation +# The driver currently includes a calculation due to the wide +# variation in thermistor types on SiS5595 motherboards. +# The driver currently has a calculation of t = (.83x + 52.12). +# One user reports the correct formula of t = (.345x - 12). +# So you want to put a compute line in sensors.conf that has +# the inverse of the driver formula, and put your formula on top of it. +# The inverse of the driver formula is x = (1.20t - 62.77) +# So the final formula is newt = (.345(1.20t - 62.77)) - 12). +# Put this in the sensors.conf file as +# compute temp1 ((.345 * ((1.20 * @) - 62.77)) - 12), ... +# where ... is the inverse function I leave to you. +# +# Look in your 'Vendor.ini' file to see which one is present +# on your motherboard. Look for the line like: +# [Temp1] +# ThermistorType = NTC-10KC15-1608-1P +# Fix up a 'compute' line to match your thermistor type. +# Warning. You still don't have enough information to do this. +# ThermistorType = NTC-10KC15-1608-1P (10K at 25C; Beta = 3435) +# compute temp1 ((X * ((1.20 * @) - 62.77)) - Y), ... +# ThermistorType = NTC-103KC15-1608-1P (??) +# compute temp1 ((X * ((1.20 * @) - 62.77)) - Y), ... +# ThermistorType = NTC-103AT-2 (10K at 25C; Beta = 3435) +# compute temp1 ((X * ((1.20 * @) - 62.77)) - Y), ... +# ThermistorType = NTC-103JT (10K at 25C; Beta = 3435) +# compute temp1 ((X * ((1.20 * @) - 62.77)) - Y), ... + +# examples for sis5595 temperature limits; +# set temp1_max 40 +# set temp1_max_hyst 37 + + +chip "w83782d-*" "w83627hf-*" + +# Same as above for w83781d except that in5 and in6 are computed differently. +# Rather than an internal inverting op amp, the 82d/83s use standard positive +# inputs and the negative voltages are level shifted by a 3.6V reference. +# The math is convoluted, so we hope that your motherboard +# uses the recommended resistor values. + + label in0 "VCore 1" + label in1 "VCore 2" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "-12V" + label in6 "-5V" + label in7 "V5SB" + label in8 "VBat" + +# Abit BP6 motherboard has a few differences. VCore1 and VCore2 are the core +# voltages of the two processors. Vtt is memory bus termination resistors +# voltage. +# label in1 "Vtt" +# label in8 "VCore2" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((28/10)+1)*@ , @/((28/10)+1) + compute in5 (5.14 * @) - 14.91 , (@ + 14.91) / 5.14 + compute in6 (3.14 * @) - 7.71 , (@ + 7.71) / 3.14 + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# set limits to 5% for the critical voltages +# set limits to 10% for the non-critical voltages +# set limits to 20% for the battery voltage + +# set in0_min cpu0_vid*0.95 +# set in0_max cpu0_vid*1.05 +# set in1_min cpu0_vid*0.95 +# set in1_max cpu0_vid*1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12 * 0.90 +# set in4_max 12 * 1.10 +# set in5_max -12 * 0.90 +# set in5_min -12 * 1.10 +# set in6_max -5 * 0.95 +# set in6_min -5 * 1.05 +# set in7_min 5 * 0.95 +# set in7_max 5 * 1.05 +# set in8_min 3.0 * 0.80 +# set in8_max 3.0 * 1.20 + +# set up sensor types (thermistor is default) +# 1 = PII/Celeron Diode; 2 = 3904 transistor; +# 3435 = thermistor with Beta = 3435 +# If temperature changes very little, try 1 or 2. +# set temp1_type 1 +# set temp2_type 2 +# set temp3_type 3435 + +# examples for temperature limits +# set temp1_max 40 +# set temp1_max_hyst 37 +# set temp2_max 52 +# set temp2_max_hyst 47 +# set temp3_max 52 +# set temp3_max_hyst 47 + + +chip "w83783s-*" + +# Same as above for w83781d except that in5 and in6 are computed differently. +# Rather than an internal inverting op amp, the 82d/83s use standard positive +# inputs and the negative voltages are level shifted by a 3.6V reference. +# The math is convoluted, so we hope that your motherboard +# uses the recommended resistor values. + + label in0 "VCore 1" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "-12V" + label in6 "-5V" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((28/10)+1)*@ , @/((28/10)+1) + compute in5 (5.14 * @) - 14.91 , (@ + 14.91) / 5.14 + compute in6 (3.14 * @) - 7.71 , (@ + 7.71) / 3.14 + +# set limits to 5% for the critical voltages +# set limits to 10% for the non-critical voltages +# set limits to 20% for the battery voltage + +# set in0_min cpu0_vid*0.95 +# set in0_max cpu0_vid*1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12 * 0.90 +# set in4_max 12 * 1.10 +# set in5_max -12 * 0.90 +# set in5_min -12 * 1.10 +# set in6_max -5 * 0.95 +# set in6_min -5 * 1.05 + +# set up sensor types (thermistor is default) +# 1 = PII/Celeron Diode; 2 = 3904 transistor; +# 3435 = thermistor with Beta = 3435 +# If temperature changes very little, try 1 or 2. +# set temp1_type 1 +# set temp2_type 2 + +# examples for temperature limits +# set temp1_max 40 +# set temp1_max_hyst 37 +# set temp2_max 52 +# set temp2_max_hyst 47 + + +chip "w83697hf-*" + +# Same as above for w83781d except that in5 and in6 are computed differently. +# Rather than an internal inverting op amp, the 82d/83s use standard positive +# inputs and the negative voltages are level shifted by a 3.6V reference. +# The math is convoluted, so we hope that your motherboard +# uses the recommended resistor values. + +# no in1 on this chip. + + label in0 "VCore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "-12V" + label in6 "-5V" + label in7 "V5SB" + label in8 "VBat" + +# Tyan Trinity S2495 KT400 has a few differences. Thanks to Eric Schumann +# for proving this information. Same is true for Epox 8K3A and 8KHA+. +# Thanks to Thomas Schorpp for additional feedback. +# label in2 "VAgp" +# label in5 "+3.3V" # aka. Vio +# label in6 "Vdimm" +# label in7 "VBat" +# label in8 "V5SB" +# +# You'll also want to comment out the in5 and in6 compute lines right below, +# and rename compute in7 to compute in8. + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((28/10)+1)*@ , @/((28/10)+1) + compute in5 (5.14 * @) - 14.91 , (@ + 14.91) / 5.14 + compute in6 (3.14 * @) - 7.71 , (@ + 7.71) / 3.14 + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# 697HF does not have VID inputs so you MUST set your core +# voltage limits below. Currently set for 1.8V core. +# vvv + +# set in0_min 1.8 * 0.95 +# set in0_max 1.8 * 1.05 + +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12 * 0.90 +# set in4_max 12 * 1.10 +# set in5_max -12 * 0.90 +# set in5_min -12 * 1.10 +# set in6_max -5 * 0.95 +# set in6_min -5 * 1.05 +# set in7_min 5 * 0.95 +# set in7_max 5 * 1.05 +# set in8_min 3.0 * 0.80 +# set in8_max 3.0 * 1.20 + +# And for Tyan Trinity S2495 KT400 and Epox 8K3A and 8KHA+: +# set in2_min 1.5 * 0.95 +# set in2_max 1.5 * 1.05 +# set in5_min 3.3 * 0.95 +# set in5_max 3.3 * 1.05 +# set in6_min 2.5 * 0.95 # 2.6 on Epox +# set in6_max 2.5 * 1.05 # 2.6 on Epox +# set in7_min 3.0 * 0.90 +# set in7_max 3.0 * 1.10 +# set in8_min 5 * 0.90 +# set in8_max 5 * 1.10 + +# set up sensor types (thermistor is default) +# 1 = PII/Celeron Diode; 2 = 3904 transistor; +# 3435 = thermistor with Beta = 3435 +# If temperature changes very little, try 1 or 2. +# set temp1_type 1 +# set temp2_type 2 +# set temp3_type 3435 + +# examples for temperature limits +# set temp1_max 40 +# set temp1_max_hyst 37 +# set temp2_max 52 +# set temp2_max_hyst 47 + + +chip "w83627thf-*" "w83637hf-*" + +# Rather than an internal inverting op amp, the 627thf uses standard positive +# inputs and the negative voltages are level shifted by a 3.6V reference +# (same as 82d/83s). +# The math is convoluted, so we hope that your motherboard +# uses the recommended resistor values. +# Note that in1 (+12V) is the usual in4, and in4 (-12V) is the usual in5. +# Data sheet is obviously wrong for in4, the usual formula should work. +# No in5 nor in6. + + label in0 "VCore" + label in1 "+12V" + label in2 "+3.3V" + label in3 "+5V" + label in4 "-12V" + label in7 "V5SB" + label in8 "VBat" + +# Mori Hiroyuki reported to need this (P4P800) +# compute in0 @/2, @*2 + + compute in1 ((28/10)+1)*@, @/((28/10)+1) + compute in3 ((34/51)+1)*@, @/((34/51)+1) + compute in4 (5.14*@)-14.91, (@+14.91)/5.14 + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# set limits to 5% for the critical voltages +# set limits to 10% for the non-critical voltages +# set limits to 20% for the battery voltage +# if your vid is wrong, you'll need to adjust in0_min and in0_max + +# set in0_min cpu0_vid * 0.95 +# set in0_max cpu0_vid * 1.05 +# set in1_min 12 * 0.90 +# set in1_max 12 * 1.10 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min -12 * 1.10 +# set in4_max -12 * 0.90 +# set in7_min 5 * 0.95 +# set in7_max 5 * 1.05 +# set in8_min 3.0 * 0.80 +# set in8_max 3.0 * 1.20 + +# set up sensor types (thermistor is default) +# 1 = PII/Celeron Diode; 2 = 3904 transistor; +# 3435 = thermistor with Beta = 3435 +# If temperature changes very little, try 1 or 2. +# set temp1_type 1 +# set temp2_type 2 +# set temp3_type 3435 + + label temp1 "M/B Temp" + label temp2 "CPU Temp" +# ignore temp3 + +# examples for temperature limits +# set temp1_max 40 +# set temp1_max_hyst 37 +# set temp2_max 52 +# set temp2_max_hyst 47 +# set temp3_max 52 +# set temp3_max_hyst 47 + +# ignore fan1 + label fan2 "CPU Fan" +# ignore fan3 + + +# Here are configurations for Winbond W83792AD/D chip. +chip "w83792d-*" + + label in0 "VCoreA" + label in1 "VCoreB" + label in6 "5VCC" + label in7 "5VSB" + label in8 "VBAT" + +# set in0_min 1.4 +# set in0_max 1.6 +# set in1_min 1.4 +# set in1_max 1.6 +# set in2_min 3.2 +# set in2_max 3.4 +# set in3_min 3.1 +# set in3_max 3.3 +# set in4_min 1.4 +# set in4_max 1.5 +# set in5_min 2.6 +# set in5_max 2.65 +# set in6_min 5 * 0.95 +# set in6_max 5 * 1.05 +# set in7_min 5 * 0.95 +# set in7_max 5 * 1.05 +# set in8_min 3 * 0.95 +# set in8_max 3 * 1.05 + +# fan1 adjustments examples + +# set fan1_div 4 +# set fan1_min 1500 + +# temp2 limits examples + +# set temp2_max 42 +# set temp2_max_hyst 37 + +# ignore examples + +# ignore fan7 +# ignore temp3 + + +# Here are configurations for Winbond W83793 chip. +chip "w83793-*" + + label in0 "VCoreA" + label in1 "VCoreB" + label in2 "Vtt" + label in5 "+3.3V" + label in6 "+12V" + label in7 "+5V" + label in8 "5VSB" + label in9 "VBAT" + + compute in6 12*@ , @/12 + + label temp1 "CPU1 Temp" + label temp2 "CPU2 Temp" + +# fan1 adjustments examples + +# set fan1_min 1500 + +# temp2 limits examples + +# set temp2_max 45 +# set temp2_max_hyst 40 + +# ignore examples + +# ignore fan7 +# ignore temp3 + + +chip "as99127f-*" + +# Asus won't release a datasheet so this is guesswork. +# Thanks to Guntram Blohm, Jack, Ed Harrison, Artur Gawryszczak, +# Victor G. Marimon and others for their feedback. + +# Dual power plane + label in0 "VCore 1" + label in1 "VCore 2" +# Single power plane (A7V133, A7M266, CUV4X) +# label in0 "VCore" +# ignore in1 + + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" +# These last two may not make sense on all motherboards. + label in5 "-12V" + label in6 "-5V" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((28/10)+1)*@ , @/((28/10)+1) +# AS99127F rev.1 (same as w83781d) + compute in5 -(240/60.4)*@ , -@/(240/60.4) + compute in6 -(90.9/60.4)*@ , -@/(90.9/60.4) +# AS99127F rev.2 (same as w83782d) +# compute in5 (5.14 * @) - 14.91 , (@ + 14.91) / 5.14 +# compute in6 (3.14 * @) - 7.71 , (@ + 7.71) / 3.14 + +# Depending on your motherboard, you may have to use any of two formulae +# for temp2. Quoting Artur Gawryszczak (edited to reflect subsequent fixes +# to the driver): +# "I guess, that the formula "(@*15/43)+25, (@-25)*43/15" is correct +# for those Asus motherboards, which get CPU temperature from internal +# thermal diode (Pentium Coppermine, and above), while no formula is needed +# for Athlon/Duron boards, which use a thermistor in the socket." +# An alternative formula was then found and reported by Victor G. Marimon. + +# Asus A7V133, Asus A7M266 +# No compute line is needed +# Asus CUV4X, Asus A7V8X +# compute temp2 (@*15/43)+25, (@-25)*43/15 +# Asus CUSL2, Asus CUV266-DLS, Asus TUSL2-C +# compute temp2 (@*30/43)+25, (@-25)*43/30 + +# See comments above if temp3 looks bad. What works for temp2 is likely +# to work for temp3 for dual-CPU boards, such as the CUV4X-D. + +# Most Asus boards have temperatures settled like that: + label temp1 "M/B Temp" + label temp2 "CPU Temp" +# However, some boards have them swapped (A7N8X Deluxe rev.2, +# A7N8X-E Deluxe rev.2, CUV4X): +# label temp1 "CPU Temp" +# label temp2 "M/B Temp" + +# Most boards have no temp3 by default, except for dual-CPU boards. +# label temp3 "CPU 2 Temp" +# ignore temp3 + +# set limits to 5% for the critical voltages +# set limits to 10% for the non-critical voltages +# set limits to 20% for the battery voltage + +# set in0_min cpu0_vid*0.95 +# set in0_max cpu0_vid*1.05 +# set in1_min cpu0_vid*0.95 +# set in1_max cpu0_vid*1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12 * 0.90 +# set in4_max 12 * 1.10 +# set in5_min -12 * 0.90 +# set in5_max -12 * 1.10 +# set in6_min -5 * 0.95 +# set in6_max -5 * 1.05 + +# examples for temperature limits +# set temp1_max 40 +# set temp1_max_hyst 37 +# set temp2_max 52 +# set temp2_max_hyst 47 +# set temp3_max 52 +# set temp3_max_hyst 47 + + +chip "gl518sm-*" + +# IMPORTANT: in0, in1, and in2 values (+5, +3, and +12) CANNOT be read +# +# Factors and labels taken from GL518SM datasheet, they seem to give +# reasonable values with EISCA connected Fan78 + + label in0 "+5V" + label in1 "+3.3V" + label in2 "+12V" + label in3 "Vcore" + +# in2 depends on external resistors (4,7k and 15k assumed here) +# in1 and in3 require no scaling + + compute in2 (197/47)*@ , @/(197/47) + +# set in0_min 4.8 +# set in0_max 5.2 +# set in1_min 3.20 +# set in1_max 3.40 +# set in2_min 11.0 +# set in2_max 13.0 +# set in3_min 2.10 +# set in3_max 2.30 +# set fan2_min 0 + + +chip "gl520sm-*" + +# Factors and labels taken from GL520SM datasheet + +# The GL520SM has two application modes. In mode 1 it has two thermistor +# inputs, in mode 2 it has only one and an extra (negative) voltage input. +# The mode is supposed to be set properly by your BIOS so you should not +# need to change it. Note that you have either temp2 or in4, not both. + + label in0 "+5V" + label in1 "+3.3V" + label in2 "+12V" + label in3 "Vcore" + label in4 "-12V" + +# in1 and in3 require no scaling +# in2 depends on external resistors (4,7k and 15k assumed) + +# in4 = ((R1+R2)/R2)*@ - (R1/R2)*vdd +# +# -12 --| R1 |---t---| R2 |-- +5 +# | +# vin4 +# + + compute in2 (197/47)*@ , @/(197/47) + compute in4 (5*@)-(4*in0_input) , (@+4*in0_input)/5 + +# set in0_min 4.8 +# set in0_max 5.2 +# set in1_min 3.20 +# set in1_max 3.40 +# set in2_min 11.0 +# set in2_max 13.0 +# set in3_min 2.10 +# set in3_max 2.30 + + +chip "lm80-*" + +# The values below should be correct if you own a qdi BX (brilliant1) +# mainboard. Many thanks go to Peter T. Breuer for helping us figure +# out how to handle the LM80. + +# For positive voltages (in0..in4), two resistors are used, with the following +# formula (R1,R2: resistor values, Vs: read voltage, Vin: pin voltage) +# R1 = R2 * (Vs/Vin - 1) +# For negative voltages (in5, in6) two resistors are used, with the following +# formula (R3,R4: resistor values, Vs: read voltage, Vin: pin voltage, +# V5: +5V) +# R3 = R4 * (Vs - Vin) / (Vin - V5) + +# Here are the official LM80 data sheet values. +# Vs R1,R3 R2,R4 Vin +# +2.5V 23.7 75 +1.9 +# +3.3V 22.1 30 +1.9 +# +5.0 24 14.7 +1.9 +# +12.0 160 30.1 +1.9 +# -12.0 160 35.7 +1.9 +# -5.0 36 16.2 +1.9 + +# Now curiously enough, VCore is connected with (unknown) resistors, which +# translate a +2.8V to +1.9V. So we use that in the computations below. + + label in0 "+5V" + label in1 "VTT" + label in2 "+3.3V" + label in3 "+Vcore" + label in4 "+12V" + label in5 "-12V" + label in6 "-5V" + + compute in0 (24/14.7 + 1) * @ , @ / (24/14.7 + 1) + compute in2 (22.1/30 + 1) * @ , @ / (22.1/30 + 1) + compute in3 (2.8/1.9) * @, @ * 1.9/2.8 + compute in4 (160/30.1 + 1) * @, @ / (160/30.1 + 1) + compute in5 (160/35.7)*(@ - in0_input) + @, (@ + in0_input * 160/35.7)/ (1 + 160/35.7) + compute in6 (36/16.2)*(@ - in0_input) + @, (@ + in0_input * 36/16.2) / (1 + 36/16.2) + +# set in0_min 5 * 0.95 +# set in0_max 5 * 1.05 +# What is your VTT? It is probably not this value... +# set in1_min 2*0.95 +# set in1_max 2*1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# What is your VCore? It is probably not this value... +# set in3_min 1.9 * 0.95 +# set in3_max 1.9 * 1.05 +# set in4_min 12 * 0.95 +# set in4_max 12 * 1.05 +# set in5_min -12 * 1.05 +# set in5_max -12 * 0.95 +# set in6_min -5 * 1.05 +# set in6_max -5 * 0.95 + +# All 4 of these limits apply to the single temperature sensor. +# "crit" may or may not do anything on your motherboard but it should +# be set higher than the "max" thresholds. +# set temp1_max 52 +# set temp1_max_hyst 45 +# set temp1_crit 62 +# set temp1_crit_hyst 57 + + +chip "via686a-*" + +# VIA is very specific about the voltage sensor inputs, and our labels +# reflect what they say. Unfortunately, they are not at all specific about +# how to convert any of the register values to real units. Fortunately, +# Jonathan Yew and Alex van Kaam came through with some data for temp +# conversion and formulae for voltage conversion. However, the conversions +# should be regarded as our best guess - YMMV. + +# On the Tyan S1598, the 2.5V sensor reads 0 and is not displayed in the BIOS. +# Linas Vepstas reports that this sensor shows nothing of +# interest on the Abit KA7 (Athlon), and is also not displayed in the BIOS. +# Likewise, Johannes Drechsel-Burkhard reports that this +# sensor is unavailable in the BIOS of his MSI K7T Pro (Thunderbird). So, +# if you have one of these boards you may want to uncomment the 'ignore in1' +# line below. + + label in0 "CPU core" + label in1 "+2.5V" + #ignore in1 + label in2 "I/O" + label in3 "+5V" + label in4 "+12V" + + label fan1 "CPU Fan" + label fan2 "P/S Fan" + +# VIA suggests that temp3 is an internal temp sensor for the 686a. However, +# on the Tyan S1598 as well as the Abit KA7 (Athalon), the absolute values +# of the readings from that sensor are not valid. The readings do seem to +# correlate with temp changes, but the conversion factor may be quite +# different from temp1 & temp2 (as noted above, VIA has not provided +# conversion info). So, you may wish to 'ignore temp3'. + +# Johannes Drechsel-Burkhard notes that on his MSI K7T Pro, +# temp1 is the CPU temp and temp2 is the SYS temp. Hugo van der Merwe notes +# the same for his Gigabyte GA-7DXC, Olivier Martin for his Gigabyte +# GA-7ZM and Patrick Thomson for his Chaintech CT-5ATA. +# Thomas Anglmaier notes: on Epox EP-7kxa temp2 is CPU and temp1 is SYS. + + label temp1 "SYS Temp" + label temp2 "CPU Temp" + label temp3 "SBr Temp" + #ignore temp3 + +# Set your CPU core limits here if the BIOS did not. + + #set in0_min 1.70 * 0.95 + #set in0_max 1.70 * 1.05 + +# Other voltage values are standard so we can enforce the limits. + +# set in1_min 2.5 * 0.95 +# set in1_max 2.5 * 1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5 * 0.9 +# set in3_max 5 * 1.1 +# set in4_min 12 * 0.9 +# set in4_max 12 * 1.1 + +# Set your temp limits here. Remember, 'tempX_max' is the temp at which an +# alarm is triggered, and 'tempX_max_hyst' is the temp at which an alarm turns off. +# Setting tempX_max_hyst to a few degrees below the corresponding tempX_max +# prevents an oscillation between alarm on and off states. This kind of +# oscillation is known as hyteresis, thus the name. (You typically get the +# most serious and troublesome hysteresis when a sensor triggers something to +# reduce the temp, thus creating a negative feedback loop. Even without that, +# we would still get some oscillation when the temp hovers around the limit +# due to noise.) + +# set temp1_max 45 +# set temp1_max_hyst 40 +# set temp2_max 60 +# set temp2_max_hyst 55 +# set temp3_max 65 +# set temp3_max_hyst 60 + +# You could set your fan limits too, but the defaults should be fine. + + #set fan1_min 5000 + #set fan2_min 5000 + + +chip "adm1025-*" "ne1619-*" + +# The ADM1025 has integrated scaling resistors, rather +# than external resistors common to most sensor devices. +# These apply to the 6 voltage inputs in0-in5 (+2.5V, VCore, +# +3.3V, +5V, +12V, VCC). As the scaling is fixed inside +# the chip for these inputs, it is fairly certain that the +# motherboard connections match these labels, and that the +# driver computations are correct. Therefore they do not need to +# be overridden here. + + label in0 "+2.5V" + label in1 "VCore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "VCC" + +# Tolerate a 5% deviance for CPU power-supply +# set in1_min cpu0_vid * 0.95 +# set in1_max cpu0_vid * 1.05 +# Tolerate a 10% deviance for other voltages +# set in0_min 2.5 * 0.90 +# set in0_max 2.5 * 1.10 +# set in2_min 3.3 * 0.90 +# set in2_max 3.3 * 1.10 +# set in3_min 5.0 * 0.90 +# set in3_max 5.0 * 1.10 +# set in4_min 12 * 0.90 +# set in4_max 12 * 1.10 +# set in5_min 3.3 * 0.90 +# set in5_max 3.3 * 1.10 + +# Depending on how your chipset is hardwired, you may or may not have +# +12V readings (will show as 0.0V if you don't have it). +# ignore in4 + +# VCC is the power-supply voltage of the ADM1025 chipset, generally +# redundant with +3.3V so you may want to hide it. +# ignore in5 + +# Temperatures + label temp1 "CPU Temp" + label temp2 "M/B Temp" +# set temp1_min 10 +# set temp1_max 60 +# set temp2_min 10 +# set temp2_max 45 + + +chip "lm87-*" "adm1024-*" +# +# The LM87 has integrated scaling resistors, rather +# than external resistors common to most sensor devices. +# These apply to the first 6 voltage inputs in0-in5 +# (+2.5, Vccp1, +3.3, +5, 12, +Vccp2). As the scaling is fixed inside +# the chip for these inputs, it is fairly certain that the +# motherboard connections match these labels, and that the +# driver computations are correct. Therefore they do not need to +# be overridden here. + + label in0 "+2.5V" + label in1 "VCore" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" +# label in5 "VCore2" + + label fan1 "CPU Fan" +# label fan2 "Case Fan" + label temp1 "M/B Temp" + label temp2 "CPU Temp" +# label temp3 "AUX Temp" + +# set in1_min cpu0_vid * 0.95 +# set in1_max cpu0_vid * 1.05 +# set in2_min 3.3 * 0.92 +# set in2_max 3.3 * 1.08 +# set in3_min 5 * 0.92 +# set in3_max 5 * 1.08 +# set in4_min 12 * 0.90 +# set in4_max 12 * 1.10 + +# These ones are mutually exclusive with temp3. If you have temp3, +# comment out these lines as they will trigger errors on "sensors -s". +# set in0_min 2.5 * 0.92 +# set in0_max 2.5 * 1.08 +# set in5_min cpu0_vid * 0.95 +# set in5_max cpu0_vid * 1.05 + +# Increase fan clock dividers if your fans read 0 RPM while you know +# they are connected and running. +# set fan1_div 4 +# set fan2_div 4 + +# set fan1_min 3000 +# set fan2_min 3000 + +# set temp1_min 5 +# set temp1_max 65 +# set temp2_min 5 +# set temp2_max 70 + +# Uncomment if you actually have temp3 (which means you don't have 2.5V +# nor Vccp2, as they are mutually exclusive). +# set temp3_min 5 +# set temp3_max 70 + +# LM87 AIN1 and AIN2 Section +# -12 and -5 may be reversed on your board, this is +# just a guess, the datasheet gives no guidance. +# label in6 "-12V" +# label in7 "-5V" +# compute in6 (7.50 * @) - 21.45 , (@ + 21.45) / 7.50 +# compute in7 (4.05 * @) - 10.07 , (@ + 10.07) / 4.05 +# set in6_min -12 * 0.95 +# set in7_min -5 * 0.95 +# set in6_max -12 * 1.05 +# set in7_max -5 * 1.05 + + +chip "it87-*" "it8712-*" + +# The values below have been tested on Asus CUSI, CUM motherboards. + +# Voltage monitors as advised in the It8705 data sheet + + label in0 "VCore 1" + label in1 "VCore 2" + label in2 "+3.3V" + label in3 "+5V" + label in4 "+12V" + label in5 "-12V" + label in6 "-5V" + label in7 "Stdby" + label in8 "VBat" + +# Incubus Saturnus reports that the IT87 chip on Asus A7V8X-X seems +# to report the VCORE voltage approximately 0.05V higher than the board's +# BIOS does. Although it doesn't make much sense physically, uncommenting +# the next line should bring the readings in line with the BIOS' ones in +# this case. +# compute in0 -0.05+@ , @+0.05 + +# If 3.3V reads around 1.65V, uncomment the following line: +# compute in2 2*@ , @/2 + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) +# A number of Gigabyte boards (GA-8IPE1000Pro, GA-8KNXP, GA-7N400-L) use +# a different resistor combination for +5V: +# compute in3 ((10/10)+1)*@ , @/((10/10)+1) + + compute in4 ((30/10) +1)*@ , @/((30/10) +1) +# For this family of chips the negative voltage equation is different from +# the lm78. The chip uses two external resistor for scaling but one is +# tied to a positive reference voltage. See ITE8705/12 datasheet (SIS950 +# data sheet is wrong) +# Vs = (1 + Rin/Rf) * Vin - (Rin/Rf) * Vref. +# Vref = 4.096 volts, Vin is voltage measured, Vs is actual voltage. + +# The next two are negative voltages (-12 and -5). +# The following formulas must be used. Unfortunately the datasheet +# does not give recommendations for Rin, Rf, but we can back into +# them based on a nominal +2V input to the chip, together with a 4.096V Vref. +# Formula: +# actual V = (Vmeasured * (1 + Rin/Rf)) - (Vref * (Rin/Rf)) +# For -12V input use Rin/Rf = 6.68 +# For -5V input use Rin/Rf = 3.33 +# Then you can convert the forumula to a standard form like: + compute in5 (7.67 * @) - 27.36 , (@ + 27.36) / 7.67 + compute in6 (4.33 * @) - 13.64 , (@ + 13.64) / 4.33 +# +# this much simpler version is reported to work for a +# Elite Group K7S5A board +# +# compute in5 -(36/10)*@, -@/(36/10) +# compute in6 -(56/10)*@, -@/(56/10) +# + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# set in0_min 1.5 * 0.95 +# set in0_max 1.5 * 1.05 +# set in1_min 2.4 +# set in1_max 2.6 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12 * 0.95 +# set in4_max 12 * 1.05 +# set in5_max -12 * 0.95 +# set in5_min -12 * 1.05 +# set in6_max -5 * 0.95 +# set in6_min -5 * 1.05 +# set in7_min 5 * 0.95 +# set in7_max 5 * 1.05 + #the chip does not support in8 min/max + +# Temperature +# +# Important - if your temperature readings are completely whacky +# you probably need to change the sensor type. +# Adujst and uncomment the appropriate lines below. +# +# 2 = thermistor; 3 = thermal diode; 0 = unused +# set temp1_type 3 +# set temp2_type 3 +# set temp3_type 3 +# If a given sensor isn't used, you will probably want to ignore it +# (see ignore statement right below). + + label temp1 "M/B Temp" +# set temp1_max 40 +# set temp1_min 15 + label temp2 "CPU Temp" +# set temp2_max 45 +# set temp2_min 15 +# ignore temp3 +# set temp3_max 45 +# set temp3_min 15 + +# The A7V8X-X has temperatures inverted, and needs a conversion for +# CPU temp. Thanks to Preben Randhol for the formula. +# label temp1 "CPU Temp" +# label temp2 "M/B Temp" +# compute temp1 (-15.096+1.4893*@), (@+15.096)/1.4893 + +# The A7V600 also has temperatures inverted, and needs a different +# conversion for CPU temp. Thanks to Dariusz Jaszkowski for the formula. +# label temp1 "CPU Temp" +# label temp2 "M/B Temp" +# compute temp1 (@+128)/3, (3*@-128) + +# Fans +# set fan1_min 0 +# set fan2_min 3000 +# ignore fan3 +# set fan3_min 3000 + + +chip "it8716-*" + +# Voltages + + label in0 "VCore" + label in1 "VDDR" + label in2 "+3.3V" # VCC3 + label in3 "+5V" # VCC + label in4 "+12V" +# label in5 "-12V" +# label in6 "-5V" + label in7 "5VSB" # VCCH + label in8 "VBat" + + compute in3 ((6.8/10)+1)*@ , @/((6.8/10)+1) + compute in4 ((30/10)+1)*@ , @/((30/10)+1) +# compute in5 (1+232/56)*@ - 4.096*232/56 , (@ + 4.096*232/56)/(1+232/56) +# compute in6 (1+120/56)*@ - 4.096*120/56 , (@ + 4.096*120/56)/(1+120/56) + compute in7 ((6.8/10)+1)*@ , @/((6.8/10)+1) + +# If vid (nominal CPU voltage) isn't correct, hardcode the correct value +# instead. +# set in0_min cpu0_vid * 0.95 +# set in0_max cpu0_vid * 1.05 +# set in1_min 1.8 * 0.95 +# set in1_max 1.8 * 1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5 * 0.95 +# set in3_max 5 * 1.05 +# set in4_min 12 * 0.95 +# set in4_max 12 * 1.05 +# set in5_max -12 * 0.95 +# set in5_min -12 * 1.05 +# set in6_max -5 * 0.95 +# set in6_min -5 * 1.05 +# set in7_min 5 * 0.95 +# set in7_max 5 * 1.05 +# The chip does not support in8 min/max + +# Temperatures + +# If you are lucky, the BIOS has set the proper sensor types for you. +# If your temperature readings are completely whacky you probably +# need to change the sensor types. Adujst and uncomment the +# appropriate lines below. +# +# 2 = thermistor; 3 = thermal diode; 0 = unused +# set temp1_type 3 +# set temp2_type 3 +# set temp3_type 3 + +# If a given sensor isn't used, you will probably want to ignore it +# as well (see ignore statement right below). +# The CPU sensor can be any of temp1, temp2 or temp3 - it's motherboard +# dependent. Same for the motherboard temperature. + +# label temp1 "CPU Temp" +# label temp2 "M/B Temp" +# ignore temp3 + +# set temp1_max 60 +# set temp1_min 10 +# set temp2_max 50 +# set temp2_min 10 + +# Fans + +# The CPU fan can be any of fan1, fan2 or fan3 - it's motherboard +# dependent. Same for the case fan. + +# label fan1 "CPU Fan" +# label fan2 "Case Fan" +# ignore fan3 + +# set fan1_min 2000 +# set fan2_min 2000 + + +chip "fscpos-*" +# Fujitsu-Siemens Poseidon chip + +# Temperature + + label temp1 "CPU Temp" + label temp2 "M/B Temp" + label temp3 "Aux Temp" + +# Fans + +# Voltage + + label in0 "+12V" + label in1 "+5V" + label in2 "Battery" + + +chip "fscscy-*" +# Fujitsu-Siemens Scylla chip + +# Temperature + + label temp1 "CPU0 Temp" + label temp2 "CPU1 Temp" + label temp3 "M/B Temp" + label temp4 "Aux Temp" + +# Fans + + label fan1 "CPU Fan" + label fan2 "CPU Fan" + +# Voltage + + label in0 "+12V" + label in1 "+5V" + label in2 "+3.3V" + + +chip "fscher-*" +# Fujitsu-Siemens Hermes chip + +# Temperature + label temp1 "CPU Temp" + label temp2 "M/B Temp" + label temp3 "Aux Temp" + +# Fans + label fan1 "PSU Fan" + label fan2 "CPU Fan" + label fan3 "Aux Fan" + +# Voltage + label in0 "+12V" + label in1 "+5V" + label in2 "Battery" + +# Uncomment the computes line below when using the old fscher driver, leave +# them commented when using the newer unified fschmd driver +# +# M R O O M R +# compute in0 (@ * (49 * 33) / 255) + (0 / 100), (@ - (0 / 100)) * 255 / (49 * 33) +# compute in1 (@ * (20 * 33) / 255) + (0 / 100), (@ - (0 / 100)) * 255 / (20 * 33) +# compute in2 (@ * (10 * 33) / 255) + (0 / 100), (@ - (0 / 100)) * 255 / (10 * 33) + + +chip "pcf8591-*" +# +# values for the Philips PCF8591 chip +# +# Analog inputs + +# You may discard ch2 and ch3 if you don't use them (depends on the input +# configuration) +# ignore in2 +# ignore in3 + + label in0 "Chan. 0" + label in1 "Chan. 1" + label in2 "Chan. 2" + label in3 "Chan. 3" + +# The driver assumes Vref = 2.56V and Agnd = 0V. If it doesn't match +# your hardware, you have to use compute lines. The example below is +# correct for Vref = 5.0V and Agnd = 0V. +# compute in0 (@ * 500 / 256), (@ * 256 / 500) +# compute in1 (@ * 500 / 256), (@ * 256 / 500) +# compute in2 (@ * 500 / 256), (@ * 256 / 500) +# compute in3 (@ * 500 / 256), (@ * 256 / 500) + + +chip "adm1021-*" "adm1023-*" "max1617-*" "max1617a-*" "thmc10-*" "lm84-*" "gl523sm-*" "mc1066-*" + + label temp1 "Board Temp" + label temp2 "CPU Temp" +# set temp1_min 40 +# set temp1_max 70 +# set temp2_min 40 +# set temp2_max 70 + +chip "lm83-*" + + label temp1 "M/B Temp" + label temp2 "D1 Temp" + label temp3 "CPU Temp" + label temp4 "D3 Temp" + +# ignore D1 and/or D3 readings if not used +# ignore temp2 +# ignore temp4 + +# change high limits to fit your needs +# set temp1_max 55 +# set temp2_max 60 +# set temp3_max 65 +# set temp4_max 60 + +# change critical limit to fit your needs +# only one limit for all four temperatures +# should be higher than each of the high limits above +# set temp3_crit 85 + + +chip "max1619-*" + + label temp1 "M/B Temp" + label temp2 "CPU Temp" + +# change high and low limits to fit your needs +# set temp2_min 10 +# set temp2_max 100 + +# change critical limit and hysteresis to fit your needs +# set temp2_crit 50 +# set temp2_crit_hyst 40 + + +chip "lm90-*" "adm1032-*" "lm86-*" "max6657-*" "adt7461-*" "max6680-*" "w83l771-*" + + label temp1 "M/B Temp" + label temp2 "CPU Temp" + +# change high and low limits to fit your needs +# set temp1_min 10 +# set temp1_max 55 +# set temp2_min 10 +# set temp2_max 66 + +# change critical limits to fit your needs +# should be higher than the corresponding high limit above +# set temp1_crit 75 +# set temp2_crit 85 + +# change the hysteresis values (to critical limits) to fit your needs +# note #1: hyst2 will be automatically set with the same delta +# note #2: the internal register, which stores a single, relative value +# for both channels, cannot hold values greater than 31, so the delta +# between critical temperatures and respective absolute hysteresis can +# never exceed this value +# set temp1_crit_hyst 70 + +chip "lm89-*" "lm99-*" + + label temp1 "G/C Temp" + label temp2 "GPU Temp" + +# note #1: the LM99 needs the compute statement below if you're running +# a kernel <= 2.6.27; since kernel 2.6.28 the offset is handled in the +# lm90 driver directly instead +# note #2: there is no way for us to differentiate between a LM89 and a +# LM99; you have to know what you have; the driver will assume a LM99, +# use the force_lm86 module parameter if you have a LM89 +# compute temp2 @+16, @-16 + +# change high and low limits to fit your needs +# set temp1_min 10 +# set temp1_max 90 +# set temp2_min 10 +# set temp2_max 100 + +# change critical limits to fit your needs +# should be higher than the corresponding high limit above +# set temp1_crit 100 +# set temp2_crit 110 + +# change the hysteresis values (to critical limits) to fit your needs +# note #1: hyst2 will be automatically set with the same delta +# note #2: the internal register, which stores a single, relative value +# for both channels, cannot hold values greater than 31, so the delta +# between critical temperatures and respective absolute hysteresis can +# never exceed this value +# set temp1_crit_hyst 105 + + +chip "lm63-*" + + label temp1 "M/B Temp" + label temp2 "CPU Temp" + label fan1 "CPU Fan" + +# Change limits to fit your needs. Note that temp2_crit is read-only. +# set temp1_max 50 +# set temp2_min 10 +# set temp2_max 70 +# set temp2_crit_hyst 75 +# set fan1_min 2000 + + +chip "vt1211-*" + + label in0 "+3.3V" + label in1 "+2.5V" + label in2 "VCore" + label in3 "+5V" + label in4 "+12V" + label in5 "+3.3V" + + label temp1 "CPU Temp" + label temp2 "Int Temp" + + label fan1 "Case Fan" + label fan2 "CPU Fan" + +# All voltage calculations have the form +# compute inX @ * (1 + R1 / R2), @ / (1 + R1 / R2) +# +# The following are the resistor values as recommended by VIA +# Voltage R1 R2 +# ------- ---- ---- +# VCore - - (no scaling) +# 3.3 6.8k 10k +# 2.5 2k 10k +# 5.0 14k 10k +# 12.0 47k 10k +# +# The VT1211 internal 3.3V (in5) is scaled by the driver and doesn't +# need to be adjusted here. VCore doesn't need scaling at all. + + compute in0 @ * (1 + 6.8 / 10), @ / (1 + 6.8 / 10) + compute in1 @ * (1 + 2 / 10), @ / (1 + 2 / 10) + compute in3 @ * (1 + 14 / 10), @ / (1 + 14 / 10) + compute in4 @ * (1 + 47 / 10), @ / (1 + 47 / 10) + +# set in0_min 3.3 * 0.95 +# set in0_max 3.3 * 1.05 +# set in1_min 2.5 * 0.95 +# set in1_max 2.5 * 1.05 +# If your vid is wrong, hardcode the CPU voltage (e.g. 1.4) +# set in2_min cpu0_vid * 0.97 +# set in2_max cpu0_vid * 1.03 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12.0 * 0.90 +# set in4_max 12.0 * 1.10 + set in5_min 3.3 * 0.95 + set in5_max 3.3 * 1.05 + +# The temperature calculations are of the form +# compute tempX (@ - Offset) / Gain, (@ * Gain) + Offset +# +# The following are the gain and offset values as recommended by VIA +# Diode Type Gain Offset +# ---------- ---- ------ +# Intel CPU 0.9528 88.638 +# 0.9686 65.000 *) +# VIA C3 Ezra 0.9528 83.869 +# VIA C3 Ezra-T 0.9528 73.869 +# +# *) These are the values from the previous sensors.conf. I don't know +# where they came from or how they got derived. +# +# The VT1211 internal temperature (temp2) is scaled by the driver +# and doesn't need to be adjusted here. + + compute temp1 (@ - 73.869) / 0.9528, (@ * 0.9528) + 73.869 + +# The thermistor calculations are of the form +# compute tempX 1 / (1 / 298.15 - (` Vmax / @ - 1)) / B) - 273.15, \ +# Vmax / (1 + (^ (B / 298.15 - B / (273.15 + @)))) +# +# B is the thermistor beta value, Vmax is the reference voltage, '^' is the +# exp() operator and '`' is the ln() operator. +# Given B = 3435 and Vmax = 2.2V and assuming that the thermistor forms a +# resistor divider with a resistor equal to the thermistor's nominal value at +# 25 degrees C, the following compute lines can be used: + + compute temp3 1 / (1 / 298.15 - (` (2.2 / @ - 1)) / 3435) - 273.15, \ + 2.2 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @)))) + compute temp4 1 / (1 / 298.15 - (` (2.2 / @ - 1)) / 3435) - 273.15, \ + 2.2 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @)))) + compute temp5 1 / (1 / 298.15 - (` (2.2 / @ - 1)) / 3435) - 273.15, \ + 2.2 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @)))) + compute temp6 1 / (1 / 298.15 - (` (2.2 / @ - 1)) / 3435) - 273.15, \ + 2.2 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @)))) + compute temp7 1 / (1 / 298.15 - (` (2.2 / @ - 1)) / 3435) - 273.15, \ + 2.2 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @)))) + +# set temp1_max 85 +# set temp1_max_hyst 80 +# set temp2_max 65 +# set temp2_max_hyst 60 +# set temp3_max 65 +# set temp3_max_hyst 60 +# set temp4_max 45 +# set temp4_max_hyst 40 + +# set fan1_min 3000 +# set fan2_min 3000 + +chip "vt8231-*" + + label in1 "+2.5V" + label in2 "VCore" + label in3 "+5V" + label in4 "+12V" + label in5 "+3.3V" + + label temp1 "CPU Temp" + label temp2 "M/B Temp" + +# Here are the resistor values as recommended by VIA: +# Voltage R1 R2 +# VCore no scaling +# 2.5 2k 10k +# 3.5 (3.3V ext.) 6.8k 10k +# 5.0 14k 10k +# 12.0 47k 10k + +# compute in0 @ * (1 + 6.8 / 10), @ / (1 + 6.8 / 10) + compute in1 @ * (1 + 2 / 10), @ / (1 + 2 / 10) + compute in3 @ * (1 + 14 / 10), @ / (1 + 14 / 10) + compute in4 @ * (1 + 47 / 10), @ / (1 + 47 / 10) +# in5 is scaled internally so scaling is done by the driver. + +# set in0_min 2.5 * 0.95 +# set in0_max 2.5 * 1.05 +# set in1_min 2.5 * 0.95 +# set in1_max 2.5 * 1.05 +# Replace "2.0" with your nominal CPU voltage for in2. +# set in2_min 2.0 * 0.95 +# set in2_max 2.0 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12.0 * 0.95 +# set in4_max 12.0 * 1.05 +# set in5_min 3.3 * 0.95 +# set in5_max 3.3 * 1.05 + +# For Intel CPU: + compute temp1 (@ - 65) / 0.9686, (@ * 0.9686) + 65 + +# For VIA EPIA CPU (provided by Roger Lucas): +# compute temp1 (@ - 45) / 0.7809, (@ * 0.7809) + 45 + +# Thermistor calculations +# 3435 is the thermistor beta, 2.2 is the reference voltage. +# '^' is the e**x operator; '`' is the ln(x) operator +# This assumes that the thermistor forms a resistor divider with a resistor +# equal to its nominal value at 25 degrees C. + + compute temp2 1 / (1 / 298.15 - (` (2.2 / @ - 1)) / 3435) - 273.15, \ + 2.2 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @)))) + compute temp3 1 / (1 / 298.15 - (` (2.2 / @ - 1)) / 3435) - 273.15, \ + 2.2 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @)))) + +# set temp1_max 65 +# set temp1_max_hyst 60 +# set temp2_max 45 +# set temp2_max_hyst 40 + +# set fan1_min 3000 +# set fan2_min 3000 + + +chip "smsc47m1-*" + +# SMSC LPC47M10x, LPC47M13x, LPC47M14x and LPC47B27x chips + +# set fan1_min 3000 +# set fan2_min 3000 + +chip "smsc47m192-*" + +# Temperature and voltage input from SMSC LPC47M192 and LPC47M997 chips +# This example works on a Gigabyte K8U motherboard +# Voltages are scaled internally, no computations needed + + label in0 "+2.5V" +# set in0_min 2.5 * 0.95 +# set in0_max 2.5 * 1.05 + + label in1 "VCore" +# set in1_min cpu0_vid * 0.95 +# set in1_max cpu0_vid * 1.05 + + label in2 "+3.3V" +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 + + label in3 "+5V" +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 + + label in4 "+12V" +# set in4_min 12.0 * 0.95 +# set in4_max 12.0 * 1.05 + + label in5 "VCC" +# set in5_min 3.3 * 0.95 +# set in5_max 3.3 * 1.05 + + label in6 "+1.5V" +# set in6_min 1.5 * 0.95 +# set in6_max 1.5 * 1.05 +# ignore in6 + + label in7 "+1.8V" +# set in7_min 1.8 * 0.95 +# set in7_max 1.8 * 1.05 +# Haven't yet heard from any board that has 1.8V connected, so +# this might be more appropriate: +# ignore in7 + + label temp1 "Chip Temp" +# set temp1_min 0 +# set temp1_max 60 + + label temp2 "CPU Temp" +# set temp2_min 0 +# set temp2_max 60 + + label temp3 "Sys Temp" +# set temp3_min 0 +# set temp3_max 60 + +# +# This example was tested vs. Asus P4S333 +# +chip "asb100-*" + + label in0 "VCore 1" + #set in0_min cpu0_vid * 0.95 + #set in0_max cpu0_vid * 1.05 + + label in1 "VCore 2" + ignore in1 + #set in1_min cpu0_vid * 0.95 + #set in1_max cpu0_vid * 1.05 + + label in2 "+3.3V" + #set in2_min 3.3 * 0.95 + #set in2_max 3.3 * 1.05 + + label in3 "+5V" + compute in3 1.68 * @ , @ / 1.68 + #set in3_min 5.0 * 0.95 + #set in3_max 5.0 * 1.05 + + label in4 "+12V" + compute in4 3.8 * @ , @ / 3.8 + #set in4_min 12 * 0.90 + #set in4_max 12 * 1.10 + + label in5 "-12V (reserved)" + #ignore in5 + compute in5 -@ * 3.97 , -@ / 3.97 + #set in5_max -12 * 0.90 + #set in5_min -12 * 1.10 + + label in6 "-5V (reserved)" + #ignore in6 + compute in6 -@ * 1.666 , -@ / 1.666 + #set in6_max -5 * 0.95 + #set in6_min -5 * 1.05 + + label temp1 "M/B Temp" + #set temp1_max 45 + #set temp1_max_hyst 40 + + label temp2 "CPU Temp (Intel)" + #ignore temp2 + #set temp2_max 60 + #set temp2_max_hyst 50 + + # PWRTMP connector on P4S333, for external sensor + label temp3 "Power Temp" + #ignore temp3 + #set temp3_max 45 + #set temp3_max_hyst 40 + + + # Used for Athlon diode, ignore for P4S333 + label temp4 "CPU Temp (AMD)" + #set temp4_max 60 + #set temp4_max_hyst 50 + #ignore temp4 + + label fan1 "CPU Fan" + #set fan1_div 4 + #set fan1_min 2000 + + label fan2 "Chassis Fan" + #set fan2_div 2 + #set fan2_min 4000 + + label fan3 "Power Fan" + #set fan3_div 2 + #set fan3_min 4000 + +# +# Sample configuration for the Intel S845WD1-E +# courtesy of Marcus Schopen +# +chip "lm85-*" "lm85b-*" "lm85c-*" "adm1027-*" "adt7463-*" "adt7468-*" "emc6d100-*" "emc6d102-*" + +# Voltage inputs +# Depending on the hardware setup, the ADT7463 and ADT7468 may not have in4. + label in0 "V1.5" # AGP on Intel S845WD1-E + label in1 "VCore" + label in2 "V3.3" + label in3 "V5" + label in4 "V12" + +# Temperature inputs + label temp1 "CPU Temp" + label temp2 "Board Temp" + label temp3 "Remote Temp" + +# Fan inputs + label fan1 "CPU Fan" + +# Voltage scaling is done on-chip. No 'compute' directive +# should be necessary. If in0 has external scaling set +# it here. + +# compute in0 @ * 2.5, @ / 2.5 + +# Adjust fans speeds for actual pulses per rev +# compute fan1 @ * 2, @ / 2 # 1 pulse per rev +# compute fan2 @ / 2, @ * 2 # 4 pulse per rev + +# Ignore fans you (or your motherboard) don't have +# ignore fan2 +# ignore fan3 +# ignore fan4 + +# Set voltage limits +# set in0_min 1.5 * 0.95 +# set in0_max 1.5 * 1.05 +# set in1_min cpu0_vid * 0.95 +# set in1_max cpu0_vid * 1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12 * 0.95 +# set in4_max 12 * 1.05 + +# Set Fan limits +# set fan1_min 4000 + +# Set Temp Limits +# set temp1_min 10 +# set temp1_max 50 +# set temp2_min 10 +# set temp2_max 35 +# set temp3_min 10 +# set temp3_max 35 + +chip "pc87365-*" "pc87366-*" + +# Voltage inputs + + label in7 "Vsb" + label in8 "Vdd" + label in9 "Vbat" + label in10 "AVdd" + + compute in7 @*2, @/2 + compute in8 @*2, @/2 + compute in10 @*2, @/2 + +# These are the operating conditions as recommended by National +# Semiconductor + set in7_min 3.0 + set in7_max 3.6 + set in8_min 3.0 + set in8_max 3.6 +# set in9_min 2.4 +# set in9_max 3.6 + set in10_min 3.0 + set in10_max 3.6 + +# Temperature inputs + + label temp1 "CPU0 Temp" + label temp2 "CPU1 Temp" + label temp3 "S-IO Temp" + +# set temp1_min 0 +# set temp1_max 70 +# set temp1_crit 85 +# set temp2_min 0 +# set temp2_max 70 +# set temp2_crit 85 +# set temp3_min 0 +# set temp3_max 70 +# set temp3_crit 85 + +# Thermistors +# On some systems, thermistors are used instead of thermal diodes. +# Note that these are the same pins used differently, so you really +# can't have them all on a given system. +# ignore temp1 +# ignore temp2 + ignore temp4 + ignore temp5 + ignore temp6 + +# 3435 is the thermistor beta. +# This assumes that the thermistor forms a resistor divider with a resistor +# equal to its nominal value at 25 degres Celsius. If not, change the values. +# We also assume that you have a working in10 (which is forcibly enabled by +# default). If not, use 3.3 instead, but you lose accuracy. + + compute temp4 3435 / (` (1 / (1 - @ / in10_input) - 1) + 3435 / 298.15) - 273.15, \ + in10_input * (1 - 1 / (1 + (^ (3435 / (273.15 + @) - 3435 / 298.15)))) + compute temp5 3435 / (` (1 / (1 - @ / in10_input) - 1) + 3435 / 298.15) - 273.15, \ + in10_input * (1 - 1 / (1 + (^ (3435 / (273.15 + @) - 3435 / 298.15)))) + compute temp6 3435 / (` (1 / (1 - @ / in10_input) - 1) + 3435 / 298.15) - 273.15, \ + in10_input * (1 - 1 / (1 + (^ (3435 / (273.15 + @) - 3435 / 298.15)))) + +# set temp4_min 0 +# set temp4_max 70 +# set temp4_crit 85 +# set temp5_min 0 +# set temp5_max 70 +# set temp5_crit 85 +# set temp6_min 0 +# set temp6_max 70 +# set temp6_crit 85 + +# Fan inputs + +# Ignore fans you don't have +# ignore fan2 +# ignore fan3 + +# set fan1_min 2000 +# set fan2_min 2000 +# set fan3_min 2000 + + +chip "adm1030-*" + + label temp1 "SYS Temp" + label temp2 "CPU Temp" + +# set temp1_max 60 +# set temp2_max 70 +# set temp1_crit 85 +# set temp2_crit 85 + + label fan1 "CPU Fan" + +# set fan1_min 2000 + + +chip "adm1031-*" + + label temp1 "SYS Temp" + label temp2 "CPU Temp" + label temp3 "AUX Temp" + +# set temp1_max 60 +# set temp2_max 70 +# set temp3_max 70 +# set temp1_crit 85 +# set temp2_crit 85 +# set temp3_crit 85 + + label fan1 "CPU Fan" + label fan2 "Case Fan" + +# set fan1_min 2000 +# set fan2_min 2000 + + +chip "w83l785ts-*" + + label temp1 "CPU Diode" + +chip "lm92-*" + + label temp1 "CPU Temp" + +# Change limits as you see fit +# set temp1_min 14 +# set temp1_max 60 +# set temp1_crit 72 +# Hysteresis is computed from critical limit +# The same relative hysteresis is used for all of low, high +# and critical limits. +# set temp1_crit_hyst 70 + + +# Winbond W83627EHF configuration originally contributed by Leon Moonen +# This is for an Asus P5P800, voltages for A8V-E SE. +chip "w83627ehf-*" "w83627dhg-*" + + label in0 "VCore" + label in1 "+12V" + label in2 "AVCC" + label in3 "3VCC" + label in6 "+5V" + label in7 "VSB" + label in8 "VBAT" + +# +12V is in1 and +5V is in6 as recommended by datasheet + compute in1 @*(1+(56/10)), @/(1+(56/10)) + compute in6 @*(1+(22/10)), @/(1+(22/10)) +# set in1_min 12.0*0.9 +# set in1_max 12.0*1.1 +# set in6_min 5.0*0.95 +# set in6_max 5.0*1.05 + +# Set the 3.3V +# set in2_min 3.3*0.95 +# set in2_max 3.3*1.05 +# set in3_min 3.3*0.95 +# set in3_max 3.3*1.05 +# set in7_min 3.3*0.95 +# set in7_max 3.3*1.05 +# set in8_min 3.3*0.95 +# set in8_max 3.3*1.05 + +# Fans + label fan1 "Case Fan" + label fan2 "CPU Fan" + label fan3 "Aux Fan" +# ignore fan3 +# ignore fan4 +# set fan1_min 1200 +# set fan2_min 1700 + +# Temperatures + label temp1 "Sys Temp" + label temp2 "CPU Temp" + label temp3 "AUX Temp" + +# ignore temp3 +# set temp1_max 45 +# set temp1_max_hyst 40 +# set temp2_max 45 +# set temp2_max_hyst 40 + + +# Fintek F71805F/FG configuration +# This is the recommended wiring and resistor values from the F71805F/FG +# datasheet. Your motherboard manufacturer may or may not have followed +# these. +chip "f71805f-*" "f71872f-*" +# Voltages + label in0 "+3.3V" + label in1 "Vtt1.2V" + label in2 "Vram" + label in3 "Vchip" + label in4 "+5V" + label in5 "+12V" + label in6 "Vcc1.5V" + label in7 "Vcore" + label in8 "5VSB" + + # in0 is scaled internally + compute in2 @*(1+100/100), @/(1+100/100) + compute in3 @*(1+100/47), @/(1+100/47) + compute in4 @*(1+200/47), @/(1+200/47) + compute in5 @*(1+200/20), @/(1+200/20) + compute in8 @*(1+200/47), @/(1+200/47) + + # in0 is the chip's own VCC. + set in0_min 3.0 + set in0_max 3.6 + + #set in1_min 1.2 * 0.95 + #set in1_max 1.2 * 1.05 + #set in2_min 2.5 * 0.95 + #set in2_max 2.6 * 1.05 + #set in3_min 3.3 * 0.95 + #set in3_max 3.3 * 1.05 + #set in4_min 5.0 * 0.95 + #set in4_max 5.0 * 1.05 + #set in5_min 12.0 * 0.95 + #set in5_max 12.0 * 1.05 + #set in6_min 1.5 * 0.95 + #set in6_max 1.5 * 1.05 + # in7 nominal value depends on the CPU model + #set in7_min 1.4 * 0.95 + #set in7_max 1.4 * 1.05 + #set in8_min 5.0 * 0.95 + #set in8_max 5.0 * 1.05 + +# Fans + label fan1 "CPU Fan" + label fan2 "Sys Fan" + label fan3 "Aux Fan" + + #set fan1_min 2100 + #set fan2_min 1400 + #set fan3_min 1400 + +# Temperatures + label temp1 "CPU Temp" + label temp2 "Sys Temp" + label temp3 "Aux Temp" + + #set temp1_max 60 + #set temp1_max_hyst 58 + #set temp2_max 50 + #set temp2_max_hyst 48 + #set temp3_max 50 + #set temp3_max_hyst 48 + + +# Abit Uguru sensor part configuration. +# The Abit Uguru is relatively straight forward to configure. +# label statements: +# The voltage (in) temp and fan sensors are usually in the same order as listed +# in the BIOS, but not always! +# compute statements: +# The temp and fan sensors don't need any compute statements. Most voltage +# inputs are directly connected to the IC and thus don't need an compute line +# because the 0-3494 mV voltage given by the kernel driver is correct. The sen- +# sors for higher voltages however are connect through a divider and measure +# ranges of: 0-4361mV, 0-6248mV or 0-14510mV. Thus the measured voltages must +# be multiplied by resp. 1.248, 1.788 or 4.153. 3.3 volt sources use the 1.248 +# mutiplier, 5 volt the 1.788 and 12 volt the 4.153. +# set statements: +# The Abit BIOS sets reasonable treshholds and allows changing them, thus +# set statements may be omitted. The abituguru kernel driver does support +# them if you want to add them. +# +# The configuration below is for the Kv8Pro and AV8 this is the default as this +# driver is developed and tested on a Kv8Pro. +# Configurations for many other Abit boards can be found at: +# http://www.lm-sensors.org/trac/wiki/Configurations/Abit +# If your motherboard isn't listed there and you create a configuration for it +# please add it there. + +chip "abituguru-*" + + label in0 "CPU Core Voltage" + label in1 "DDR Voltage" + label in2 "DDR VTT Voltage" + label in3 "NB Voltage" + label in4 "SB Voltage" + label in5 "HyperTransport Voltage" + label in6 "AGP VDDQ Voltage" + label in7 "ATX +5V" + compute in7 @*1.788 , @/1.788 + label in8 "ATX +3.3V" + compute in8 @*1.248 , @/1.248 + label in9 "Standby Voltage (+5V)" + compute in9 @*1.788 , @/1.788 + label in10 "3VDual Voltage" + compute in10 @*1.248 , @/1.248 + + label temp1 "CPU Temperature" + label temp2 "SYS Temperature" + label temp3 "PWM Temperature" + ignore temp4 + ignore temp5 + ignore temp6 + ignore temp7 + + label fan1 "CPU FAN Speed" + label fan2 "NB FAN Speed" + label fan3 "SYS FAN Speed" + label fan4 "AUX1 FAN Speed" + label fan5 "AUX2 FAN Speed" + ignore fan6 + +chip "k8temp-*" + + label temp1 "Core0 Temp" + label temp2 "Core0 Temp" + label temp3 "Core1 Temp" + label temp4 "Core1 Temp" + + +# +# Sample configuration for the SMSC DME1737 and ASUS A8000 +# +chip "dme1737-*" + +# Voltage inputs + label in0 "V5stby" + label in1 "Vccp" + label in2 "V3.3" + label in3 "V5" + label in4 "V12" + label in5 "V3.3stby" + label in6 "Vbat" + +# Temperature inputs + label temp1 "RD1 Temp" + label temp2 "Int Temp" + label temp3 "CPU Temp" + +# Fan inputs + label fan1 "CPU Fan" + +# Set voltage limits +# set in0_min 5.0 * 0.95 +# set in0_max 5.0 * 1.05 +# set in1_min 1.4 * 0.95 +# set in1_max 1.4 * 1.05 +# set in2_min 3.3 * 0.95 +# set in2_max 3.3 * 1.05 +# set in3_min 5.0 * 0.95 +# set in3_max 5.0 * 1.05 +# set in4_min 12.0 * 0.95 +# set in4_max 12.0 * 1.05 +# set in5_min 3.3 * 0.95 +# set in5_max 3.3 * 1.05 +# set in6_min 3.0 * 0.95 +# set in6_max 3.0 * 1.05 + +# Set Temp Limits +# set temp1_min 10 +# set temp1_max 75 +# set temp2_min 10 +# set temp2_max 75 +# set temp3_min 10 +# set temp3_max 75 + +# Set Fan limits +# set fan1_min 1000 +# set fan2_min 1000 +# set fan3_min 1000 +# set fan4_min 1000 +# set fan5_min 1000 +# set fan6_min 1000 + + +# +# sample configuration for the Fintek f71882fg and f71883fg +# +# The configuration below is for the Epox EP-9U1697 GLI board, which has a +# Fintek f71883fg relabeled as Epox ep1308, this is the default config as this +# driver is developed and tested on an Epox EP-9U1697 GLI board. +# +# Premade configurations for other boards can be found at: +# http://www.lm-sensors.org/trac/wiki/Configurations/ +# If your motherboard isn't listed there and you create a configuration for it +# please add it there. +# +chip "f71882fg-*" + +# Temperature + label temp1 "CPU" + label temp2 "System" + ignore temp3 + +# Fans + label fan1 "CPU" + label fan2 "System" + label fan3 "Power" + label fan4 "Aux" + +# Voltage + label in0 "3.3V" + label in1 "Vcore" + label in2 "Vdimm" + label in3 "Vchip" + label in4 "+5V" + label in5 "12V" + label in6 "5VSB" + label in7 "3VSB" + label in8 "Battery" + +# never change the in0, in7 and in8 compute, these are hardwired in the chip! + compute in0 (@ * 2), (@ / 2) + compute in2 (@ * 2), (@ / 2) + compute in3 (@ * 2), (@ / 2) + compute in4 (@ * 5.25), (@ / 5.25) + compute in5 (@ * 12.83), (@ / 12.83) + compute in6 (@ * 5.25), (@ / 5.25) + compute in7 (@ * 2), (@ / 2) + compute in8 (@ * 2), (@ / 2) + + +chip "adm1022-*" "thmc50-*" + + label temp1 "M/B Temp" + # Single CPU setup + label temp2 "CPU Temp" + + # Dual CPU setup (ADM1022 only) + #label temp2 "CPU0 Temp" + #label temp3 "CPU1 Temp" + +# Asus/Fintek F8000 +chip "f8000-*" + + # All 3 voltages are internal, but scaling is not done by the driver + # so we do it here + compute in0 @*2, @/2 + compute in1 @*2, @/2 + compute in2 @*2, @/2 + + label in0 "+3.3V" + label in1 "3VSB" + label in2 "Vbat" diff --git a/lib/Module.mk b/lib/Module.mk new file mode 100644 index 0000000..d34b1ed --- /dev/null +++ b/lib/Module.mk @@ -0,0 +1,176 @@ +# Module.mk - Makefile for a Linux module for reading sensor data. +# Copyright (c) 1998, 1999 Frodo Looijaard +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. + +# Note that MODULE_DIR (the directory in which this file resides) is a +# 'simply expanded variable'. That means that its value is substituted +# verbatim in the rules, until it is redefined. +MODULE_DIR := lib +LIB_DIR := $(MODULE_DIR) + +# The manual dirs and files +LIBMAN3DIR := $(MANDIR)/man3 +LIBMAN3FILES := $(MODULE_DIR)/libsensors.3 +LIBMAN5DIR := $(MANDIR)/man5 +LIBMAN5FILES := $(MODULE_DIR)/sensors.conf.5 + +# The main and minor version of the library +# The library soname (major number) must be changed if and only if the interface is +# changed in a backward incompatible way. The interface is defined by +# the public header files - in this case they are error.h and sensors.h. +LIBMAINVER := 4 +LIBMINORVER := 4.0 +LIBVER := $(LIBMAINVER).$(LIBMINORVER) + +# The static lib name, the shared lib name, and the internal ('so') name of +# the shared lib. +LIBSHBASENAME := libsensors.so +LIBSHLIBNAME := libsensors.so.$(LIBVER) +LIBSTLIBNAME := libsensors.a +LIBSHSONAME := libsensors.so.$(LIBMAINVER) + +LIBTARGETS := $(MODULE_DIR)/$(LIBSHLIBNAME) \ + $(MODULE_DIR)/$(LIBSHSONAME) $(MODULE_DIR)/$(LIBSHBASENAME) +ifeq ($(BUILD_STATIC_LIB),1) +LIBTARGETS += $(MODULE_DIR)/$(LIBSTLIBNAME) +endif + +LIBCSOURCES := $(MODULE_DIR)/data.c $(MODULE_DIR)/general.c \ + $(MODULE_DIR)/error.c $(MODULE_DIR)/access.c \ + $(MODULE_DIR)/init.c $(MODULE_DIR)/sysfs.c + +LIBOTHEROBJECTS := $(MODULE_DIR)/conf-parse.o $(MODULE_DIR)/conf-lex.o +LIBSHOBJECTS := $(LIBCSOURCES:.c=.lo) $(LIBOTHEROBJECTS:.o=.lo) +LIBSTOBJECTS := $(LIBCSOURCES:.c=.ao) $(LIBOTHEROBJECTS:.o=.ao) +LIBEXTRACLEAN := $(MODULE_DIR)/conf-parse.h $(MODULE_DIR)/conf-parse.c \ + $(MODULE_DIR)/conf-lex.c + +LIBHEADERFILES := $(MODULE_DIR)/error.h $(MODULE_DIR)/sensors.h + +# How to create the shared library +$(MODULE_DIR)/$(LIBSHLIBNAME): $(LIBSHOBJECTS) $(LIB_DIR)/libsensors.map + $(CC) -shared $(LDFLAGS) -Wl,--version-script=$(LIB_DIR)/libsensors.map -Wl,-soname,$(LIBSHSONAME) -o $@ $(LIBSHOBJECTS) -lc -lm + +$(MODULE_DIR)/$(LIBSHSONAME): $(MODULE_DIR)/$(LIBSHLIBNAME) + $(RM) $@ + $(LN) $(LIBSHLIBNAME) $@ + +$(MODULE_DIR)/$(LIBSHBASENAME): $(MODULE_DIR)/$(LIBSHLIBNAME) + $(RM) $@ + $(LN) $(LIBSHLIBNAME) $@ + +# And the static library +$(MODULE_DIR)/$(LIBSTLIBNAME): $(LIBSTOBJECTS) + $(RM) $@ + $(AR) rcvs $@ $^ + +# Depencies for non-C sources +$(MODULE_DIR)/conf-lex.c: $(MODULE_DIR)/conf-lex.l $(MODULE_DIR)/general.h \ + $(MODULE_DIR)/data.h $(MODULE_DIR)/conf-parse.h +$(MODULE_DIR)/conf-parse.c: $(MODULE_DIR)/conf-parse.y $(MODULE_DIR)/general.h \ + $(MODULE_DIR)/data.h +$(MODULE_DIR)/conf-parse.h: $(MODULE_DIR)/conf-parse.c + +# Include all dependency files +INCLUDEFILES += $(LIBSHOBJECTS:.lo=.ld) $(LIBSTOBJECTS:.ao=.ad) + +# Special warning prevention for flex-generated files +FLEXNOWARN:=-Wno-shadow -Wno-undef -Wno-unused -Wno-missing-prototypes -Wno-sign-compare +$(MODULE_DIR)/conf-lex.ao: $(MODULE_DIR)/conf-lex.c + $(CC) $(ARCPPFLAGS) $(ARCFLAGS) $(FLEXNOWARN) -c $< -o $@ +$(MODULE_DIR)/conf-lex.lo: $(MODULE_DIR)/conf-lex.c + $(CC) $(LIBCPPFLAGS) $(LIBCFLAGS) $(FLEXNOWARN) -c $< -o $@ + +# Special warning prevention for bison-generated files +YACCNOWARN:=-Wno-undef +$(MODULE_DIR)/conf-parse.ao: $(MODULE_DIR)/conf-parse.c + $(CC) $(ARCPPFLAGS) $(ARCFLAGS) $(YACCNOWARN) -c $< -o $@ +$(MODULE_DIR)/conf-parse.lo: $(MODULE_DIR)/conf-parse.c + $(CC) $(LIBCPPFLAGS) $(LIBCFLAGS) $(YACCNOWARN) -c $< -o $@ + +REMOVELIBST := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(LIBDIR)/%,$(LIB_DIR)/$(LIBSTLIBNAME)) +REMOVELIBSH := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(LIBDIR)/%,$(LIB_DIR)/$(LIBSHLIBNAME)) +REMOVELNSO := $(DESTDIR)$(LIBDIR)/$(LIBSHSONAME) +REMOVELNBS := $(DESTDIR)$(LIBDIR)/$(LIBSHBASENAME) +REMOVELIBHF := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(LIBINCLUDEDIR)/%,$(LIBHEADERFILES)) +REMOVEMAN3 := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(LIBMAN3DIR)/%,$(LIBMAN3FILES)) +REMOVEMAN5 := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(LIBMAN5DIR)/%,$(LIBMAN5FILES)) + +all-lib: $(LIBTARGETS) +user :: all-lib + +# Generate warnings if the install directory isn't in /etc/ld.so.conf +# or if the library wasn't there before (which means ldconfig must be run). +# Note that some ld.so's put /usr/lib and /lib first, others put them last, +# so we can't make any assumptions. +install-lib: all-lib + $(MKDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(LIBINCLUDEDIR) $(DESTDIR)$(LIBMAN3DIR) $(DESTDIR)$(LIBMAN5DIR) + @if [ -z "$(DESTDIR)" -a ! -e "$(LIBDIR)/$(LIBSHSONAME)" ] ; then \ + echo '******************************************************************************' ; \ + echo 'Warning: This is the first installation of the $(LIBSHSONAME)*' ; \ + echo ' library files in $(LIBDIR)!' ; \ + echo ' You must update the library cache or the userspace tools may fail' ; \ + echo ' or have unpredictable results!' ; \ + echo ' Run the following command: /sbin/ldconfig' ; \ + echo '******************************************************************************' ; \ + fi +ifeq ($(BUILD_STATIC_LIB),1) + $(INSTALL) -m 644 $(LIB_DIR)/$(LIBSTLIBNAME) $(DESTDIR)$(LIBDIR) +endif + $(INSTALL) -m 755 $(LIB_DIR)/$(LIBSHLIBNAME) $(DESTDIR)$(LIBDIR) + $(LN) $(LIBSHLIBNAME) $(DESTDIR)$(LIBDIR)/$(LIBSHSONAME) + $(LN) $(LIBSHSONAME) $(DESTDIR)$(LIBDIR)/$(LIBSHBASENAME) + @if [ -z "$(DESTDIR)" -a "$(LIBDIR)" != "/usr/lib" -a "$(LIBDIR)" != "/lib" ] ; then \ + if [ -e "/usr/lib/$(LIBSHSONAME)" -o -e "/usr/lib/$(LIBSHBASENAME)" ] ; then \ + echo '******************************************************************************' ; \ + echo 'Warning: You have at least one $(LIBSHBASENAME) library file in /usr/lib' ; \ + echo ' and the new library files are in $(LIBDIR)!' ; \ + echo ' These old files must be removed or the userspace tools may fail' ; \ + echo ' or have unpredictable results!' ; \ + echo ' Run the following command: rm /usr/lib/$(LIBSHBASENAME)*' ; \ + echo '******************************************************************************' ; \ + fi ; \ + cat /etc/ld.so.conf /etc/ld.so.conf.d/*.conf 2>/dev/null | grep -q '\(^\|[[:space:]:,]\)$(LIBDIR)\([[:space:]:,=]\|$$\)' || \ + ( echo '******************************************************************************' ; \ + echo 'Warning: Library directory $(LIBDIR) is not in /etc/ld.so.conf!' ; \ + echo ' Add it and run /sbin/ldconfig for the userspace tools to work.' ; \ + echo '******************************************************************************' ) ; \ + fi + $(INSTALL) -m 644 $(LIBHEADERFILES) $(DESTDIR)$(LIBINCLUDEDIR) + $(INSTALL) -m 644 $(LIBMAN3FILES) $(DESTDIR)$(LIBMAN3DIR) + $(INSTALL) -m 644 $(LIBMAN5FILES) $(DESTDIR)$(LIBMAN5DIR) + $(LN) sensors.conf.5 $(DESTDIR)$(LIBMAN5DIR)/sensors3.conf.5 + + +user_install :: install-lib + +user_uninstall:: + $(RM) $(REMOVELIBSH) $(REMOVELNSO) $(REMOVELNBS) +ifeq ($(BUILD_STATIC_LIB),1) + $(RM) $(REMOVELIBST) +endif + $(RM) $(REMOVELIBHF) $(REMOVEMAN3) $(REMOVEMAN5) +# Remove directory if empty, ignore failure + $(RMDIR) $(DESTDIR)$(LIBINCLUDEDIR) 2> /dev/null || true + +clean-lib: + $(RM) $(LIB_DIR)/*.ld $(LIB_DIR)/*.ad + $(RM) $(LIB_DIR)/*.lo $(LIB_DIR)/*.ao + $(RM) $(LIBTARGETS) $(LIBEXTRACLEAN) +# old versions + $(RM) $(LIB_DIR)/$(LIBSHBASENAME).* +clean :: clean-lib diff --git a/lib/access.c b/lib/access.c new file mode 100644 index 0000000..f63634e --- /dev/null +++ b/lib/access.c @@ -0,0 +1,563 @@ +/* + access.c - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + Copyright (C) 2007-2010 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#include +#include +#include +#include "access.h" +#include "sensors.h" +#include "data.h" +#include "error.h" +#include "sysfs.h" + +/* We watch the recursion depth for variables only, as an easy way to + detect cycles. */ +#define DEPTH_MAX 8 + +static int sensors_eval_expr(const sensors_chip_features *chip_features, + const sensors_expr *expr, + double val, int depth, double *result); + +/* Compare two chips name descriptions, to see whether they could match. + Return 0 if it does not match, return 1 if it does match. */ +static int sensors_match_chip(const sensors_chip_name *chip1, + const sensors_chip_name *chip2) +{ + if ((chip1->prefix != SENSORS_CHIP_NAME_PREFIX_ANY) && + (chip2->prefix != SENSORS_CHIP_NAME_PREFIX_ANY) && + strcmp(chip1->prefix, chip2->prefix)) + return 0; + + if ((chip1->bus.type != SENSORS_BUS_TYPE_ANY) && + (chip2->bus.type != SENSORS_BUS_TYPE_ANY) && + (chip1->bus.type != chip2->bus.type)) + return 0; + + if ((chip1->bus.nr != SENSORS_BUS_NR_ANY) && + (chip2->bus.nr != SENSORS_BUS_NR_ANY) && + (chip1->bus.nr != chip2->bus.nr)) + return 0; + + if ((chip1->addr != chip2->addr) && + (chip1->addr != SENSORS_CHIP_NAME_ADDR_ANY) && + (chip2->addr != SENSORS_CHIP_NAME_ADDR_ANY)) + return 0; + + return 1; +} + +/* Returns, one by one, a pointer to all sensor_chip structs of the + config file which match with the given chip name. Last should be + the value returned by the last call, or NULL if this is the first + call. Returns NULL if no more matches are found. Do not modify + the struct the return value points to! + Note that this visits the list of chips from last to first. Usually, + you want the match that was latest in the config file. */ +static sensors_chip * +sensors_for_all_config_chips(const sensors_chip_name *name, + const sensors_chip *last) +{ + int nr, i; + sensors_chip_name_list chips; + + for (nr = last ? last - sensors_config_chips - 1 : + sensors_config_chips_count - 1; nr >= 0; nr--) { + + chips = sensors_config_chips[nr].chips; + for (i = 0; i < chips.fits_count; i++) { + if (sensors_match_chip(&chips.fits[i], name)) + return sensors_config_chips + nr; + } + } + return NULL; +} + +/* Look up a chip in the intern chip list, and return a pointer to it. + Do not modify the struct the return value points to! Returns NULL if + not found.*/ +static const sensors_chip_features * +sensors_lookup_chip(const sensors_chip_name *name) +{ + int i; + + for (i = 0; i < sensors_proc_chips_count; i++) + if (sensors_match_chip(&sensors_proc_chips[i].chip, name)) + return &sensors_proc_chips[i]; + + return NULL; +} + +/* Look up a subfeature of the given chip, and return a pointer to it. + Do not modify the struct the return value points to! Returns NULL if + not found.*/ +static const sensors_subfeature * +sensors_lookup_subfeature_nr(const sensors_chip_features *chip, + int subfeat_nr) +{ + if (subfeat_nr < 0 || + subfeat_nr >= chip->subfeature_count) + return NULL; + return chip->subfeature + subfeat_nr; +} + +/* Look up a feature of the given chip, and return a pointer to it. + Do not modify the struct the return value points to! Returns NULL if + not found.*/ +static const sensors_feature * +sensors_lookup_feature_nr(const sensors_chip_features *chip, int feat_nr) +{ + if (feat_nr < 0 || + feat_nr >= chip->feature_count) + return NULL; + return chip->feature + feat_nr; +} + +/* Look up a subfeature by name, and return a pointer to it. + Do not modify the struct the return value points to! Returns NULL if + not found.*/ +static const sensors_subfeature * +sensors_lookup_subfeature_name(const sensors_chip_features *chip, + const char *name) +{ + int j; + + for (j = 0; j < chip->subfeature_count; j++) + if (!strcmp(chip->subfeature[j].name, name)) + return chip->subfeature + j; + return NULL; +} + +/* Check whether the chip name is an 'absolute' name, which can only match + one chip, or whether it has wildcards. Returns 0 if it is absolute, 1 + if there are wildcards. */ +int sensors_chip_name_has_wildcards(const sensors_chip_name *chip) +{ + if ((chip->prefix == SENSORS_CHIP_NAME_PREFIX_ANY) || + (chip->bus.type == SENSORS_BUS_TYPE_ANY) || + (chip->bus.nr == SENSORS_BUS_NR_ANY) || + (chip->addr == SENSORS_CHIP_NAME_ADDR_ANY)) + return 1; + else + return 0; +} + +/* Look up the label for a given feature. Note that chip should not + contain wildcard values! The returned string is newly allocated (free it + yourself). On failure, NULL is returned. + If no label exists for this feature, its name is returned itself. */ +char *sensors_get_label(const sensors_chip_name *name, + const sensors_feature *feature) +{ + char *label; + const sensors_chip *chip; + char buf[PATH_MAX]; + FILE *f; + int i; + + if (sensors_chip_name_has_wildcards(name)) + return NULL; + + for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));) + for (i = 0; i < chip->labels_count; i++) + if (!strcmp(feature->name, chip->labels[i].name)) { + label = chip->labels[i].value; + goto sensors_get_label_exit; + } + + /* No user specified label, check for a _label sysfs file */ + snprintf(buf, PATH_MAX, "%s/%s_label", name->path, feature->name); + + if ((f = fopen(buf, "r"))) { + i = fread(buf, 1, sizeof(buf), f); + fclose(f); + if (i > 0) { + /* i - 1 to strip the '\n' at the end */ + buf[i - 1] = 0; + label = buf; + goto sensors_get_label_exit; + } + } + + /* No label, return the feature name instead */ + label = feature->name; + +sensors_get_label_exit: + label = strdup(label); + if (!label) + sensors_fatal_error(__func__, "Allocating label text"); + return label; +} + +/* Looks up whether a feature should be ignored. Returns + 1 if it should be ignored, 0 if not. */ +static int sensors_get_ignored(const sensors_chip_name *name, + const sensors_feature *feature) +{ + const sensors_chip *chip; + int i; + + for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));) + for (i = 0; i < chip->ignores_count; i++) + if (!strcmp(feature->name, chip->ignores[i].name)) + return 1; + return 0; +} + +/* Read the value of a subfeature of a certain chip. Note that chip should not + contain wildcard values! This function will return 0 on success, and <0 + on failure. */ +static int __sensors_get_value(const sensors_chip_name *name, int subfeat_nr, + int depth, double *result) +{ + const sensors_chip_features *chip_features; + const sensors_subfeature *subfeature; + const sensors_expr *expr = NULL; + double val; + int res, i; + + if (depth >= DEPTH_MAX) + return -SENSORS_ERR_RECURSION; + if (sensors_chip_name_has_wildcards(name)) + return -SENSORS_ERR_WILDCARDS; + if (!(chip_features = sensors_lookup_chip(name))) + return -SENSORS_ERR_NO_ENTRY; + if (!(subfeature = sensors_lookup_subfeature_nr(chip_features, + subfeat_nr))) + return -SENSORS_ERR_NO_ENTRY; + if (!(subfeature->flags & SENSORS_MODE_R)) + return -SENSORS_ERR_ACCESS_R; + + /* Apply compute statement if it exists */ + if (subfeature->flags & SENSORS_COMPUTE_MAPPING) { + const sensors_feature *feature; + const sensors_chip *chip; + + feature = sensors_lookup_feature_nr(chip_features, + subfeature->mapping); + + chip = NULL; + while (!expr && + (chip = sensors_for_all_config_chips(name, chip))) + for (i = 0; i < chip->computes_count; i++) { + if (!strcmp(feature->name, + chip->computes[i].name)) { + expr = chip->computes[i].from_proc; + break; + } + } + } + + res = sensors_read_sysfs_attr(name, subfeature, &val); + if (res) + return res; + if (!expr) + *result = val; + else if ((res = sensors_eval_expr(chip_features, expr, val, depth, + result))) + return res; + return 0; +} + +int sensors_get_value(const sensors_chip_name *name, int subfeat_nr, + double *result) +{ + return __sensors_get_value(name, subfeat_nr, 0, result); +} + +/* Set the value of a subfeature of a certain chip. Note that chip should not + contain wildcard values! This function will return 0 on success, and <0 + on failure. */ +int sensors_set_value(const sensors_chip_name *name, int subfeat_nr, + double value) +{ + const sensors_chip_features *chip_features; + const sensors_subfeature *subfeature; + const sensors_expr *expr = NULL; + int i, res; + double to_write; + + if (sensors_chip_name_has_wildcards(name)) + return -SENSORS_ERR_WILDCARDS; + if (!(chip_features = sensors_lookup_chip(name))) + return -SENSORS_ERR_NO_ENTRY; + if (!(subfeature = sensors_lookup_subfeature_nr(chip_features, + subfeat_nr))) + return -SENSORS_ERR_NO_ENTRY; + if (!(subfeature->flags & SENSORS_MODE_W)) + return -SENSORS_ERR_ACCESS_W; + + /* Apply compute statement if it exists */ + if (subfeature->flags & SENSORS_COMPUTE_MAPPING) { + const sensors_feature *feature; + const sensors_chip *chip; + + feature = sensors_lookup_feature_nr(chip_features, + subfeature->mapping); + + chip = NULL; + while (!expr && + (chip = sensors_for_all_config_chips(name, chip))) + for (i = 0; i < chip->computes_count; i++) { + if (!strcmp(feature->name, + chip->computes[i].name)) { + expr = chip->computes[i].to_proc; + break; + } + } + } + + to_write = value; + if (expr) + if ((res = sensors_eval_expr(chip_features, expr, + value, 0, &to_write))) + return res; + return sensors_write_sysfs_attr(name, subfeature, to_write); +} + +const sensors_chip_name *sensors_get_detected_chips(const sensors_chip_name + *match, int *nr) +{ + const sensors_chip_name *res; + + while (*nr < sensors_proc_chips_count) { + res = &sensors_proc_chips[(*nr)++].chip; + if (!match || sensors_match_chip(res, match)) + return res; + } + return NULL; +} + +const char *sensors_get_adapter_name(const sensors_bus_id *bus) +{ + int i; + + /* bus types with a single instance */ + switch (bus->type) { + case SENSORS_BUS_TYPE_ISA: + return "ISA adapter"; + case SENSORS_BUS_TYPE_PCI: + return "PCI adapter"; + /* SPI should not be here, but for now SPI adapters have no name + so we don't have any custom string to return. */ + case SENSORS_BUS_TYPE_SPI: + return "SPI adapter"; + case SENSORS_BUS_TYPE_VIRTUAL: + return "Virtual device"; + case SENSORS_BUS_TYPE_ACPI: + return "ACPI interface"; + /* HID should probably not be there either, but I don't know if + HID buses have a name nor where to find it. */ + case SENSORS_BUS_TYPE_HID: + return "HID adapter"; + case SENSORS_BUS_TYPE_MDIO: + return "MDIO adapter"; + } + + /* bus types with several instances */ + for (i = 0; i < sensors_proc_bus_count; i++) + if (sensors_proc_bus[i].bus.type == bus->type && + sensors_proc_bus[i].bus.nr == bus->nr) + return sensors_proc_bus[i].adapter; + return NULL; +} + +const sensors_feature * +sensors_get_features(const sensors_chip_name *name, int *nr) +{ + const sensors_chip_features *chip; + + if (!(chip = sensors_lookup_chip(name))) + return NULL; /* No such chip */ + + while (*nr < chip->feature_count + && sensors_get_ignored(name, &chip->feature[*nr])) + (*nr)++; + if (*nr >= chip->feature_count) + return NULL; + return &chip->feature[(*nr)++]; +} + +const sensors_subfeature * +sensors_get_all_subfeatures(const sensors_chip_name *name, + const sensors_feature *feature, int *nr) +{ + const sensors_chip_features *chip; + const sensors_subfeature *subfeature; + + if (!(chip = sensors_lookup_chip(name))) + return NULL; /* No such chip */ + + /* Seek directly to the first subfeature */ + if (*nr < feature->first_subfeature) + *nr = feature->first_subfeature; + + if (*nr >= chip->subfeature_count) + return NULL; /* end of list */ + subfeature = &chip->subfeature[(*nr)++]; + if (subfeature->mapping == feature->number) + return subfeature; + return NULL; /* end of subfeature list */ +} + +const sensors_subfeature * +sensors_get_subfeature(const sensors_chip_name *name, + const sensors_feature *feature, + sensors_subfeature_type type) +{ + const sensors_chip_features *chip; + int i; + + if (!(chip = sensors_lookup_chip(name))) + return NULL; /* No such chip */ + + for (i = feature->first_subfeature; i < chip->subfeature_count && + chip->subfeature[i].mapping == feature->number; i++) { + if (chip->subfeature[i].type == type) + return &chip->subfeature[i]; + } + return NULL; /* No such subfeature */ +} + +/* Evaluate an expression */ +static int sensors_eval_expr(const sensors_chip_features *chip_features, + const sensors_expr *expr, + double val, int depth, double *result) +{ + double res1, res2; + int res; + const sensors_subfeature *subfeature; + + if (expr->kind == sensors_kind_val) { + *result = expr->data.val; + return 0; + } + if (expr->kind == sensors_kind_source) { + *result = val; + return 0; + } + if (expr->kind == sensors_kind_var) { + if (!(subfeature = sensors_lookup_subfeature_name(chip_features, + expr->data.var))) + return -SENSORS_ERR_NO_ENTRY; + return __sensors_get_value(&chip_features->chip, + subfeature->number, depth + 1, + result); + } + if ((res = sensors_eval_expr(chip_features, expr->data.subexpr.sub1, + val, depth, &res1))) + return res; + if (expr->data.subexpr.sub2 && + (res = sensors_eval_expr(chip_features, expr->data.subexpr.sub2, + val, depth, &res2))) + return res; + switch (expr->data.subexpr.op) { + case sensors_add: + *result = res1 + res2; + return 0; + case sensors_sub: + *result = res1 - res2; + return 0; + case sensors_multiply: + *result = res1 * res2; + return 0; + case sensors_divide: + if (res2 == 0.0) + return -SENSORS_ERR_DIV_ZERO; + *result = res1 / res2; + return 0; + case sensors_negate: + *result = -res1; + return 0; + case sensors_exp: + *result = exp(res1); + return 0; + case sensors_log: + if (res1 < 0.0) + return -SENSORS_ERR_DIV_ZERO; + *result = log(res1); + return 0; + } + return 0; +} + +/* Execute all set statements for this particular chip. The chip may not + contain wildcards! This function will return 0 on success, and <0 on + failure. */ +static int sensors_do_this_chip_sets(const sensors_chip_name *name) +{ + const sensors_chip_features *chip_features; + sensors_chip *chip; + double value; + int i; + int err = 0, res; + const sensors_subfeature *subfeature; + + chip_features = sensors_lookup_chip(name); /* Can't fail */ + + for (chip = NULL; (chip = sensors_for_all_config_chips(name, chip));) + for (i = 0; i < chip->sets_count; i++) { + subfeature = sensors_lookup_subfeature_name(chip_features, + chip->sets[i].name); + if (!subfeature) { + sensors_parse_error_wfn("Unknown feature name", + chip->sets[i].line.filename, + chip->sets[i].line.lineno); + err = -SENSORS_ERR_NO_ENTRY; + continue; + } + + res = sensors_eval_expr(chip_features, + chip->sets[i].value, 0, + 0, &value); + if (res) { + sensors_parse_error_wfn("Error parsing expression", + chip->sets[i].line.filename, + chip->sets[i].line.lineno); + err = res; + continue; + } + if ((res = sensors_set_value(name, subfeature->number, + value))) { + sensors_parse_error_wfn("Failed to set value", + chip->sets[i].line.filename, + chip->sets[i].line.lineno); + err = res; + continue; + } + } + return err; +} + +/* Execute all set statements for this particular chip. The chip may contain + wildcards! This function will return 0 on success, and <0 on failure. */ +int sensors_do_chip_sets(const sensors_chip_name *name) +{ + int nr, this_res; + const sensors_chip_name *found_name; + int res = 0; + + for (nr = 0; (found_name = sensors_get_detected_chips(name, &nr));) { + this_res = sensors_do_this_chip_sets(found_name); + if (this_res) + res = this_res; + } + return res; +} diff --git a/lib/access.h b/lib/access.h new file mode 100644 index 0000000..4273f06 --- /dev/null +++ b/lib/access.h @@ -0,0 +1,33 @@ +/* + access.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + Copyright (C) 2007-2010 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_SENSORS_ACCESS_H +#define LIB_SENSORS_ACCESS_H + +#include "sensors.h" +#include "data.h" + +/* Check whether the chip name is an 'absolute' name, which can only match + one chip, or whether it has wildcards. Returns 0 if it is absolute, 1 + if there are wildcards. */ +int sensors_chip_name_has_wildcards(const sensors_chip_name *chip); + +#endif /* def LIB_SENSORS_ACCESS_H */ diff --git a/lib/conf-lex.l b/lib/conf-lex.l new file mode 100644 index 0000000..43ddbd8 --- /dev/null +++ b/lib/conf-lex.l @@ -0,0 +1,372 @@ +%{ +/* + conf-lex.l - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#include +#include + +#include "general.h" +#include "data.h" +#include "conf-parse.h" +#include "error.h" +#include "scanner.h" + +static int buffer_count; +static int buffer_max; +static char *buffer; + +char sensors_lex_error[100]; + +const char *sensors_yyfilename; +int sensors_yylineno; + +#define buffer_malloc() sensors_malloc_array(&buffer,&buffer_count,\ + &buffer_max,1) +#define buffer_free() sensors_free_array(&buffer,&buffer_count,\ + &buffer_max) +#define buffer_add_char(c) sensors_add_array_el(c,&buffer,\ + &buffer_count,\ + &buffer_max,1) +#define buffer_add_string(s) sensors_add_array_els(s,strlen(s),\ + &buffer, \ + &buffer_count,&buffer_max,1) + +%} + + /* Scanner for configuration files */ + +%option nodefault +%option noyywrap +%option nounput + + /* All states are exclusive */ + +%x MIDDLE +%x STRING +%x ERR + + /* Any whitespace-like character */ + +BLANK [ \f\r\t\v] + +IDCHAR [[:alnum:]_] + + /* Note: `10', `10.4' and `.4' are valid, `10.' is not */ + +FLOAT [[:digit:]]*\.?[[:digit:]]+ + + /* Only positive whole numbers are recognized here */ + +NUM 0|([1-9][[:digit:]]*) + + +%% + + /* + * STATE: INITIAL + */ + +{ + +<> { /* EOF from this state terminates */ + return 0; + } + +{BLANK}+ ; /* eat as many blanks as possible at once */ + +{BLANK}*\n { /* eat a bare newline (possibly preceded by blanks) */ + sensors_yylineno++; + } + + /* comments */ + +#.* ; /* eat the rest of the line after comment char */ + +#.*\n { /* eat the rest of the line after comment char */ + sensors_yylineno++; + } + + /* + * Keywords must be followed by whitespace - eat that too. + * If there isn't trailing whitespace, we still need to + * accept it as lexically correct (even though the parser + * will reject it anyway.) + */ + +label{BLANK}* { + sensors_yylval.line.filename = sensors_yyfilename; + sensors_yylval.line.lineno = sensors_yylineno; + BEGIN(MIDDLE); + return LABEL; + } + +set{BLANK}* { + sensors_yylval.line.filename = sensors_yyfilename; + sensors_yylval.line.lineno = sensors_yylineno; + BEGIN(MIDDLE); + return SET; + } + +compute{BLANK}* { + sensors_yylval.line.filename = sensors_yyfilename; + sensors_yylval.line.lineno = sensors_yylineno; + BEGIN(MIDDLE); + return COMPUTE; + } + +bus{BLANK}* { + sensors_yylval.line.filename = sensors_yyfilename; + sensors_yylval.line.lineno = sensors_yylineno; + BEGIN(MIDDLE); + return BUS; + } + +chip{BLANK}* { + sensors_yylval.line.filename = sensors_yyfilename; + sensors_yylval.line.lineno = sensors_yylineno; + BEGIN(MIDDLE); + return CHIP; + } + +ignore{BLANK}* { + sensors_yylval.line.filename = sensors_yyfilename; + sensors_yylval.line.lineno = sensors_yylineno; + BEGIN(MIDDLE); + return IGNORE; + } + + /* Anything else at the beginning of a line is an error */ + +[a-z]+ | +. { + BEGIN(ERR); + strcpy(sensors_lex_error,"Invalid keyword"); + return ERROR; + } +} + + /* + * STATE: ERROR + */ + +{ + +.* ; /* eat whatever is left on this line */ + +\n { + BEGIN(INITIAL); + sensors_yylineno++; + return EOL; + } +} + + /* + * STATE: MIDDLE + */ + +{ + +{BLANK}+ ; /* eat as many blanks as possible at once */ + +\n { /* newline here sends EOL token to parser */ + BEGIN(INITIAL); + sensors_yylineno++; + return EOL; + } + +<> { /* EOF here sends EOL token to parser also */ + BEGIN(INITIAL); + return EOL; + } + +\\{BLANK}*\n { /* eat an escaped newline with no state change */ + sensors_yylineno++; + } + + /* comments */ + +#.* ; /* eat the rest of the line after comment char */ + +#.*\n { /* eat the rest of the line after comment char */ + BEGIN(INITIAL); + sensors_yylineno++; + return EOL; + } + + /* A number */ + +{FLOAT} { + sensors_yylval.value = atof(sensors_yytext); + return FLOAT; + } + + /* Some operators */ + +"+" return '+'; +"-" return '-'; +"*" return '*'; +"/" return '/'; +"(" return '('; +")" return ')'; +"," return ','; +"@" return '@'; +"^" return '^'; +"`" return '`'; + + /* Quoted string */ + +\" { + buffer_malloc(); + BEGIN(STRING); + } + + /* A normal, unquoted identifier */ + +{IDCHAR}+ { + sensors_yylval.name = strdup(sensors_yytext); + if (! sensors_yylval.name) + sensors_fatal_error("conf-lex.l", + "Allocating a new string"); + + return NAME; + } + + /* anything else is bogus */ + +. | +[[:digit:]]*\. | +\\{BLANK}* { + BEGIN(ERR); + return ERROR; + } +} + + /* + * STATE: STRING + */ + +{ + + /* Oops, newline or EOF while in a string is not good */ + +\n | +\\\n { + buffer_add_char("\0"); + strcpy(sensors_lex_error, + "No matching double quote."); + buffer_free(); + yyless(0); + BEGIN(ERR); + return ERROR; + } + +<> { + strcpy(sensors_lex_error, + "Reached end-of-file without a matching double quote."); + buffer_free(); + BEGIN(MIDDLE); + return ERROR; + } + + /* At the end */ + +\"\" { + buffer_add_char("\0"); + strcpy(sensors_lex_error, + "Quoted strings must be separated by whitespace."); + buffer_free(); + BEGIN(ERR); + return ERROR; + } + +\" { + buffer_add_char("\0"); + sensors_yylval.name = strdup(buffer); + if (! sensors_yylval.name) + sensors_fatal_error("conf-lex.l", + "Allocating a new string"); + buffer_free(); + BEGIN(MIDDLE); + return NAME; + } + +\\a buffer_add_char("\a"); +\\b buffer_add_char("\b"); +\\f buffer_add_char("\f"); +\\n buffer_add_char("\n"); +\\r buffer_add_char("\r"); +\\t buffer_add_char("\t"); +\\v buffer_add_char("\v"); + + /* Other escapes: just copy the character behind the slash */ + +\\. { + buffer_add_char(&sensors_yytext[1]); + } + + /* Anything else (including a bare '\' which may be followed by EOF) */ + +\\ | +[^\\\n\"]+ { + buffer_add_string(sensors_yytext); + } +} + +%% + +/* + Do the buffer handling manually. This allows us to scan as many + config files as we need to, while cleaning up properly after each + one. The "BEGIN(0)" line ensures that we start in the default state, + even if e.g. the previous config file was syntactically broken. + + Returns 0 if successful, !0 otherwise. +*/ + +static YY_BUFFER_STATE scan_buf = (YY_BUFFER_STATE)0; + +int sensors_scanner_init(FILE *input, const char *filename) +{ + BEGIN(0); + if (!(scan_buf = sensors_yy_create_buffer(input, YY_BUF_SIZE))) + return -1; + + sensors_yy_switch_to_buffer(scan_buf); + sensors_yyfilename = filename; + sensors_yylineno = 1; + return 0; +} + +void sensors_scanner_exit(void) +{ + sensors_yy_delete_buffer(scan_buf); + scan_buf = (YY_BUFFER_STATE)0; + +/* As of flex 2.5.9, yylex_destroy() must be called when done with the + scaller, otherwise we'll leak memory. */ +#if defined(YY_FLEX_MAJOR_VERSION) && defined(YY_FLEX_MINOR_VERSION) && defined(YY_FLEX_SUBMINOR_VERSION) +#if YY_FLEX_MAJOR_VERSION > 2 || \ + (YY_FLEX_MAJOR_VERSION == 2 && (YY_FLEX_MINOR_VERSION > 5 || \ + (YY_FLEX_MINOR_VERSION == 5 && YY_FLEX_SUBMINOR_VERSION >= 9))) + sensors_yylex_destroy(); +#endif +#endif +} + diff --git a/lib/conf-parse.y b/lib/conf-parse.y new file mode 100644 index 0000000..1937f54 --- /dev/null +++ b/lib/conf-parse.y @@ -0,0 +1,347 @@ +%{ +/* + conf-parse.y - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#define YYERROR_VERBOSE + +#include +#include +#include + +#include "data.h" +#include "general.h" +#include "error.h" +#include "conf.h" +#include "access.h" +#include "init.h" + +static void sensors_yyerror(const char *err); +static sensors_expr *malloc_expr(void); + +static sensors_chip *current_chip = NULL; + +#define bus_add_el(el) sensors_add_array_el(el,\ + &sensors_config_busses,\ + &sensors_config_busses_count,\ + &sensors_config_busses_max,\ + sizeof(sensors_bus)) +#define label_add_el(el) sensors_add_array_el(el,\ + ¤t_chip->labels,\ + ¤t_chip->labels_count,\ + ¤t_chip->labels_max,\ + sizeof(sensors_label)); +#define set_add_el(el) sensors_add_array_el(el,\ + ¤t_chip->sets,\ + ¤t_chip->sets_count,\ + ¤t_chip->sets_max,\ + sizeof(sensors_set)); +#define compute_add_el(el) sensors_add_array_el(el,\ + ¤t_chip->computes,\ + ¤t_chip->computes_count,\ + ¤t_chip->computes_max,\ + sizeof(sensors_compute)); +#define ignore_add_el(el) sensors_add_array_el(el,\ + ¤t_chip->ignores,\ + ¤t_chip->ignores_count,\ + ¤t_chip->ignores_max,\ + sizeof(sensors_ignore)); +#define chip_add_el(el) sensors_add_array_el(el,\ + &sensors_config_chips,\ + &sensors_config_chips_count,\ + &sensors_config_chips_max,\ + sizeof(sensors_chip)); + +#define fits_add_el(el,list) sensors_add_array_el(el,\ + &(list).fits,\ + &(list).fits_count,\ + &(list).fits_max, \ + sizeof(sensors_chip_name)); + +%} + +%union { + double value; + char *name; + void *nothing; + sensors_chip_name_list chips; + sensors_expr *expr; + sensors_bus_id bus; + sensors_chip_name chip; + sensors_config_line line; +} + +%left '-' '+' +%left '*' '/' +%left NEG +%right '^' '`' + +%token ',' +%token EOL +%token BUS +%token LABEL +%token SET +%token CHIP +%token COMPUTE +%token IGNORE +%token FLOAT +%token NAME +%token ERROR + +%type chip_name_list +%type expression +%type bus_id +%type adapter_name +%type function_name +%type string +%type chip_name + +%start input + +%% + +input: /* empty */ + | input line +; + +line: bus_statement EOL + | label_statement EOL + | set_statement EOL + | chip_statement EOL + | compute_statement EOL + | ignore_statement EOL + | error EOL +; + +bus_statement: BUS bus_id adapter_name + { sensors_bus new_el; + new_el.line = $1; + new_el.bus = $2; + new_el.adapter = $3; + bus_add_el(&new_el); + } +; + +label_statement: LABEL function_name string + { sensors_label new_el; + if (!current_chip) { + sensors_yyerror("Label statement before first chip statement"); + free($2); + free($3); + YYERROR; + } + new_el.line = $1; + new_el.name = $2; + new_el.value = $3; + label_add_el(&new_el); + } +; + +set_statement: SET function_name expression + { sensors_set new_el; + if (!current_chip) { + sensors_yyerror("Set statement before first chip statement"); + free($2); + sensors_free_expr($3); + YYERROR; + } + new_el.line = $1; + new_el.name = $2; + new_el.value = $3; + set_add_el(&new_el); + } +; + +compute_statement: COMPUTE function_name expression ',' expression + { sensors_compute new_el; + if (!current_chip) { + sensors_yyerror("Compute statement before first chip statement"); + free($2); + sensors_free_expr($3); + sensors_free_expr($5); + YYERROR; + } + new_el.line = $1; + new_el.name = $2; + new_el.from_proc = $3; + new_el.to_proc = $5; + compute_add_el(&new_el); + } +; + +ignore_statement: IGNORE function_name + { sensors_ignore new_el; + if (!current_chip) { + sensors_yyerror("Ignore statement before first chip statement"); + free($2); + YYERROR; + } + new_el.line = $1; + new_el.name = $2; + ignore_add_el(&new_el); + } +; + +chip_statement: CHIP chip_name_list + { sensors_chip new_el; + new_el.line = $1; + new_el.labels = NULL; + new_el.sets = NULL; + new_el.computes = NULL; + new_el.ignores = NULL; + new_el.labels_count = new_el.labels_max = 0; + new_el.sets_count = new_el.sets_max = 0; + new_el.computes_count = new_el.computes_max = 0; + new_el.ignores_count = new_el.ignores_max = 0; + new_el.chips = $2; + chip_add_el(&new_el); + current_chip = sensors_config_chips + + sensors_config_chips_count - 1; + } +; + +chip_name_list: chip_name + { + $$.fits = NULL; + $$.fits_count = $$.fits_max = 0; + fits_add_el(&$1,$$); + } + | chip_name_list chip_name + { $$ = $1; + fits_add_el(&$2,$$); + } +; + +expression: FLOAT + { $$ = malloc_expr(); + $$->data.val = $1; + $$->kind = sensors_kind_val; + } + | NAME + { $$ = malloc_expr(); + $$->data.var = $1; + $$->kind = sensors_kind_var; + } + | '@' + { $$ = malloc_expr(); + $$->kind = sensors_kind_source; + } + | expression '+' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_add; + $$->data.subexpr.sub1 = $1; + $$->data.subexpr.sub2 = $3; + } + | expression '-' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_sub; + $$->data.subexpr.sub1 = $1; + $$->data.subexpr.sub2 = $3; + } + | expression '*' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_multiply; + $$->data.subexpr.sub1 = $1; + $$->data.subexpr.sub2 = $3; + } + | expression '/' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_divide; + $$->data.subexpr.sub1 = $1; + $$->data.subexpr.sub2 = $3; + } + | '-' expression %prec NEG + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_negate; + $$->data.subexpr.sub1 = $2; + $$->data.subexpr.sub2 = NULL; + } + | '(' expression ')' + { $$ = $2; } + | '^' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_exp; + $$->data.subexpr.sub1 = $2; + $$->data.subexpr.sub2 = NULL; + } + | '`' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_log; + $$->data.subexpr.sub1 = $2; + $$->data.subexpr.sub2 = NULL; + } +; + +bus_id: NAME + { int res = sensors_parse_bus_id($1,&$$); + free($1); + if (res) { + sensors_yyerror("Parse error in bus id"); + YYERROR; + } + } +; + +adapter_name: NAME + { $$ = $1; } +; + +function_name: NAME + { $$ = $1; } +; + +string: NAME + { $$ = $1; } +; + +chip_name: NAME + { int res = sensors_parse_chip_name($1,&$$); + free($1); + if (res) { + sensors_yyerror("Parse error in chip name"); + YYERROR; + } + } +; + +%% + +void sensors_yyerror(const char *err) +{ + if (sensors_lex_error[0]) { + sensors_parse_error_wfn(sensors_lex_error, sensors_yyfilename, sensors_yylineno); + sensors_lex_error[0] = '\0'; + } else + sensors_parse_error_wfn(err, sensors_yyfilename, sensors_yylineno); +} + +sensors_expr *malloc_expr(void) +{ + sensors_expr *res = malloc(sizeof(sensors_expr)); + if (! res) + sensors_fatal_error(__func__, "Allocating a new expression"); + return res; +} diff --git a/lib/conf.h b/lib/conf.h new file mode 100644 index 0000000..2efdb0a --- /dev/null +++ b/lib/conf.h @@ -0,0 +1,34 @@ +/* + conf.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_SENSORS_CONF_H +#define LIB_SENSORS_CONF_H + +/* This is defined in conf-lex.l */ +int sensors_yylex(void); +extern char sensors_lex_error[]; +extern const char *sensors_yyfilename; +extern int sensors_yylineno; +extern FILE *sensors_yyin; + +/* This is defined in conf-parse.y */ +int sensors_yyparse(void); + +#endif /* def LIB_SENSORS_CONF_H */ diff --git a/lib/data.c b/lib/data.c new file mode 100644 index 0000000..937709f --- /dev/null +++ b/lib/data.c @@ -0,0 +1,281 @@ +/* + data.c - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + Copyright (C) 2007-2010 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* this define needed for strndup() */ +#define _GNU_SOURCE + +#include +#include + +#include "access.h" +#include "error.h" +#include "data.h" +#include "sensors.h" +#include "../version.h" + +const char *libsensors_version = LM_VERSION; + +char **sensors_config_files = NULL; +int sensors_config_files_count = 0; +int sensors_config_files_max = 0; + +sensors_chip *sensors_config_chips = NULL; +int sensors_config_chips_count = 0; +int sensors_config_chips_subst = 0; +int sensors_config_chips_max = 0; + +sensors_bus *sensors_config_busses = NULL; +int sensors_config_busses_count = 0; +int sensors_config_busses_max = 0; + +sensors_chip_features *sensors_proc_chips = NULL; +int sensors_proc_chips_count = 0; +int sensors_proc_chips_max = 0; + +sensors_bus *sensors_proc_bus = NULL; +int sensors_proc_bus_count = 0; +int sensors_proc_bus_max = 0; + +void sensors_free_chip_name(sensors_chip_name *chip) +{ + free(chip->prefix); +} + +/* + Parse a chip name to the internal representation. These are valid names: + + lm78-i2c-10-5e *-i2c-10-5e + lm78-i2c-10-* *-i2c-10-* + lm78-i2c-*-5e *-i2c-*-5e + lm78-i2c-*-* *-i2c-*-* + lm78-isa-10dd *-isa-10dd + lm78-isa-* *-isa-* + lm78-* *-* + + Here 'lm78' can be any prefix. 'i2c' and 'isa' are + literal strings, just like all dashes '-' and wildcards '*'. '10' can + be any decimal i2c bus number. '5e' can be any hexadecimal i2c device + address, and '10dd' any hexadecimal isa address. + + The 'prefix' part in the result is freshly allocated. All old contents + of res is overwritten. res itself is not allocated. In case of an error + return (ie. != 0), res is undefined, but all allocations are undone. +*/ + +int sensors_parse_chip_name(const char *name, sensors_chip_name *res) +{ + char *dash; + + /* First, the prefix. It's either "*" or a real chip name. */ + if (!strncmp(name, "*-", 2)) { + res->prefix = SENSORS_CHIP_NAME_PREFIX_ANY; + name += 2; + } else { + if (!(dash = strchr(name, '-'))) + return -SENSORS_ERR_CHIP_NAME; + res->prefix = strndup(name, dash - name); + if (!res->prefix) + sensors_fatal_error(__func__, + "Allocating name prefix"); + name = dash + 1; + } + + /* Then we have either a sole "*" (all chips with this name) or a bus + type and an address. */ + if (!strcmp(name, "*")) { + res->bus.type = SENSORS_BUS_TYPE_ANY; + res->bus.nr = SENSORS_BUS_NR_ANY; + res->addr = SENSORS_CHIP_NAME_ADDR_ANY; + return 0; + } + + if (!(dash = strchr(name, '-'))) + goto ERROR; + if (!strncmp(name, "i2c", dash - name)) + res->bus.type = SENSORS_BUS_TYPE_I2C; + else if (!strncmp(name, "isa", dash - name)) + res->bus.type = SENSORS_BUS_TYPE_ISA; + else if (!strncmp(name, "pci", dash - name)) + res->bus.type = SENSORS_BUS_TYPE_PCI; + else if (!strncmp(name, "spi", dash - name)) + res->bus.type = SENSORS_BUS_TYPE_SPI; + else if (!strncmp(name, "virtual", dash - name)) + res->bus.type = SENSORS_BUS_TYPE_VIRTUAL; + else if (!strncmp(name, "acpi", dash - name)) + res->bus.type = SENSORS_BUS_TYPE_ACPI; + else if (!strncmp(name, "hid", dash - name)) + res->bus.type = SENSORS_BUS_TYPE_HID; + else if (!strncmp(name, "mdio", dash - name)) + res->bus.type = SENSORS_BUS_TYPE_MDIO; + else + goto ERROR; + name = dash + 1; + + /* Some bus types (i2c, spi) have an additional bus number. + For these, the next part is either a "*" (any bus of that type) + or a decimal number. */ + switch (res->bus.type) { + case SENSORS_BUS_TYPE_I2C: + case SENSORS_BUS_TYPE_SPI: + case SENSORS_BUS_TYPE_HID: + if (!strncmp(name, "*-", 2)) { + res->bus.nr = SENSORS_BUS_NR_ANY; + name += 2; + break; + } + + res->bus.nr = strtoul(name, &dash, 10); + if (*name == '\0' || *dash != '-' || res->bus.nr < 0) + goto ERROR; + name = dash + 1; + break; + default: + res->bus.nr = SENSORS_BUS_NR_ANY; + } + + /* Last part is the chip address, or "*" for any address. */ + if (!strcmp(name, "*")) { + res->addr = SENSORS_CHIP_NAME_ADDR_ANY; + } else { + res->addr = strtoul(name, &dash, 16); + if (*name == '\0' || *dash != '\0' || res->addr < 0) + goto ERROR; + } + + return 0; + +ERROR: + free(res->prefix); + return -SENSORS_ERR_CHIP_NAME; +} + +int sensors_snprintf_chip_name(char *str, size_t size, + const sensors_chip_name *chip) +{ + if (sensors_chip_name_has_wildcards(chip)) + return -SENSORS_ERR_WILDCARDS; + + switch (chip->bus.type) { + case SENSORS_BUS_TYPE_ISA: + return snprintf(str, size, "%s-isa-%04x", chip->prefix, + chip->addr); + case SENSORS_BUS_TYPE_PCI: + return snprintf(str, size, "%s-pci-%04x", chip->prefix, + chip->addr); + case SENSORS_BUS_TYPE_I2C: + return snprintf(str, size, "%s-i2c-%hd-%02x", chip->prefix, + chip->bus.nr, chip->addr); + case SENSORS_BUS_TYPE_SPI: + return snprintf(str, size, "%s-spi-%hd-%x", chip->prefix, + chip->bus.nr, chip->addr); + case SENSORS_BUS_TYPE_VIRTUAL: + return snprintf(str, size, "%s-virtual-%x", chip->prefix, + chip->addr); + case SENSORS_BUS_TYPE_ACPI: + return snprintf(str, size, "%s-acpi-%x", chip->prefix, + chip->addr); + case SENSORS_BUS_TYPE_HID: + return snprintf(str, size, "%s-hid-%hd-%x", chip->prefix, + chip->bus.nr, chip->addr); + case SENSORS_BUS_TYPE_MDIO: + return snprintf(str, size, "%s-mdio-%x", chip->prefix, + chip->addr); + } + + return -SENSORS_ERR_CHIP_NAME; +} + +int sensors_parse_bus_id(const char *name, sensors_bus_id *bus) +{ + char *endptr; + + if (strncmp(name, "i2c-", 4)) { + return -SENSORS_ERR_BUS_NAME; + } + name += 4; + bus->type = SENSORS_BUS_TYPE_I2C; + bus->nr = strtoul(name, &endptr, 10); + if (*name == '\0' || *endptr != '\0' || bus->nr < 0) + return -SENSORS_ERR_BUS_NAME; + return 0; +} + +static int sensors_substitute_chip(sensors_chip_name *name, + const char *filename, int lineno) +{ + int i, j; + for (i = 0; i < sensors_config_busses_count; i++) + if (sensors_config_busses[i].bus.type == name->bus.type && + sensors_config_busses[i].bus.nr == name->bus.nr) + break; + + if (i == sensors_config_busses_count) { + sensors_parse_error_wfn("Undeclared bus id referenced", + filename, lineno); + name->bus.nr = SENSORS_BUS_NR_IGNORE; + return -SENSORS_ERR_BUS_NAME; + } + + /* Compare the adapter names */ + for (j = 0; j < sensors_proc_bus_count; j++) { + if (!strcmp(sensors_config_busses[i].adapter, + sensors_proc_bus[j].adapter)) { + name->bus.nr = sensors_proc_bus[j].bus.nr; + return 0; + } + } + + /* We did not find a matching bus name, simply ignore this chip + config entry. */ + name->bus.nr = SENSORS_BUS_NR_IGNORE; + return 0; +} + +/* Bus substitution is on a per-configuration file basis, so we keep + memory (in sensors_config_chips_subst) of which chip entries have been + already substituted. */ +int sensors_substitute_busses(void) +{ + int err, i, j, lineno; + sensors_chip_name_list *chips; + const char *filename; + int res = 0; + + for (i = sensors_config_chips_subst; + i < sensors_config_chips_count; i++) { + filename = sensors_config_chips[i].line.filename; + lineno = sensors_config_chips[i].line.lineno; + chips = &sensors_config_chips[i].chips; + for (j = 0; j < chips->fits_count; j++) { + /* We can only substitute if a specific bus number + is given. */ + if (chips->fits[j].bus.nr == SENSORS_BUS_NR_ANY) + continue; + + err = sensors_substitute_chip(&chips->fits[j], + filename, lineno); + if (err) + res = err; + } + } + sensors_config_chips_subst = sensors_config_chips_count; + return res; +} diff --git a/lib/data.h b/lib/data.h new file mode 100644 index 0000000..aaf87ef --- /dev/null +++ b/lib/data.h @@ -0,0 +1,184 @@ +/* + data.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + Copyright (C) 2007-2010 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_SENSORS_DATA_H +#define LIB_SENSORS_DATA_H + +#include "sensors.h" +#include "general.h" + +/* This header file contains all kinds of data structures which are used + for the representation of the config file data and the sensors + data. */ + +/* Kinds of expression operators recognized */ +typedef enum sensors_operation { + sensors_add, sensors_sub, sensors_multiply, sensors_divide, + sensors_negate, sensors_exp, sensors_log, +} sensors_operation; + +/* An expression can have several forms */ +typedef enum sensors_expr_kind { + sensors_kind_val, sensors_kind_source, sensors_kind_var, + sensors_kind_sub +} sensors_expr_kind; + +/* An expression. It is either a floating point value, a variable name, + an operation on subexpressions, or the special value 'sub' } */ +struct sensors_expr; + +typedef struct sensors_subexpr { + sensors_operation op; + struct sensors_expr *sub1; + struct sensors_expr *sub2; +} sensors_subexpr; + +typedef struct sensors_expr { + sensors_expr_kind kind; + union { + double val; + char *var; + sensors_subexpr subexpr; + } data; +} sensors_expr; + +/* Config file line reference */ +typedef struct sensors_config_line { + const char *filename; + int lineno; +} sensors_config_line; + +/* Config file label declaration: a feature name, combined with the label + value */ +typedef struct sensors_label { + char *name; + char *value; + sensors_config_line line; +} sensors_label; + +/* Config file set declaration: a subfeature name, combined with an + expression */ +typedef struct sensors_set { + char *name; + sensors_expr *value; + sensors_config_line line; +} sensors_set; + +/* Config file compute declaration: a feature name, combined with two + expressions */ +typedef struct sensors_compute { + char *name; + sensors_expr *from_proc; + sensors_expr *to_proc; + sensors_config_line line; +} sensors_compute; + +/* Config file ignore declaration: a feature name */ +typedef struct sensors_ignore { + char *name; + sensors_config_line line; +} sensors_ignore; + +/* A list of chip names, used to represent a config file chips declaration */ +typedef struct sensors_chip_name_list { + sensors_chip_name *fits; + int fits_count; + int fits_max; +} sensors_chip_name_list; + +/* A config file chip block */ +typedef struct sensors_chip { + sensors_chip_name_list chips; + sensors_label *labels; + int labels_count; + int labels_max; + sensors_set *sets; + int sets_count; + int sets_max; + sensors_compute *computes; + int computes_count; + int computes_max; + sensors_ignore *ignores; + int ignores_count; + int ignores_max; + sensors_config_line line; +} sensors_chip; + +/* Config file bus declaration: the bus type and number, combined with adapter + name */ +typedef struct sensors_bus { + char *adapter; + sensors_bus_id bus; + sensors_config_line line; +} sensors_bus; + +/* Internal data about all features and subfeatures of a chip */ +typedef struct sensors_chip_features { + struct sensors_chip_name chip; + struct sensors_feature *feature; + struct sensors_subfeature *subfeature; + int feature_count; + int subfeature_count; +} sensors_chip_features; + +extern char **sensors_config_files; +extern int sensors_config_files_count; +extern int sensors_config_files_max; + +#define sensors_add_config_files(el) sensors_add_array_el( \ + (el), &sensors_config_files, &sensors_config_files_count, \ + &sensors_config_files_max, sizeof(char *)) + +extern sensors_chip *sensors_config_chips; +extern int sensors_config_chips_count; +extern int sensors_config_chips_subst; +extern int sensors_config_chips_max; + +extern sensors_bus *sensors_config_busses; +extern int sensors_config_busses_count; +extern int sensors_config_busses_max; + +extern sensors_chip_features *sensors_proc_chips; +extern int sensors_proc_chips_count; +extern int sensors_proc_chips_max; + +#define sensors_add_proc_chips(el) sensors_add_array_el( \ + (el), &sensors_proc_chips, &sensors_proc_chips_count,\ + &sensors_proc_chips_max, sizeof(struct sensors_chip_features)) + +extern sensors_bus *sensors_proc_bus; +extern int sensors_proc_bus_count; +extern int sensors_proc_bus_max; + +#define sensors_add_proc_bus(el) sensors_add_array_el( \ + (el), &sensors_proc_bus, &sensors_proc_bus_count,\ + &sensors_proc_bus_max, sizeof(struct sensors_bus)) + +/* Substitute configuration bus numbers with real-world bus numbers + in the chips lists */ +int sensors_substitute_busses(void); + + +/* Parse a bus id into its components. Returns 0 on success, a value from + error.h on failure. */ +int sensors_parse_bus_id(const char *name, sensors_bus_id *bus); + +#endif /* def LIB_SENSORS_DATA_H */ diff --git a/lib/error.c b/lib/error.c new file mode 100644 index 0000000..4c651c2 --- /dev/null +++ b/lib/error.c @@ -0,0 +1,87 @@ +/* + error.c - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + Copyright (C) 2007-2010 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#include +#include +#include "error.h" +#include "general.h" + +static const char *errorlist[] = { + /* Invalid error code */ "Unknown error", + /* SENSORS_ERR_WILDCARDS */ "Wildcard found in chip name", + /* SENSORS_ERR_NO_ENTRY */ "No such subfeature known", + /* SENSORS_ERR_ACCESS_R */ "Can't read", + /* SENSORS_ERR_KERNEL */ "Kernel interface error", + /* SENSORS_ERR_DIV_ZERO */ "Divide by zero", + /* SENSORS_ERR_CHIP_NAME */ "Can't parse chip name", + /* SENSORS_ERR_BUS_NAME */ "Can't parse bus name", + /* SENSORS_ERR_PARSE */ "General parse error", + /* SENSORS_ERR_ACCESS_W */ "Can't write", + /* SENSORS_ERR_IO */ "I/O error", + /* SENSORS_ERR_RECURSION */ "Evaluation recurses too deep", +}; + +const char *sensors_strerror(int errnum) +{ + if (errnum < 0) + errnum = -errnum; + if (errnum >= ARRAY_SIZE(errorlist)) + errnum = 0; + return errorlist[errnum]; +} + +static void sensors_default_parse_error(const char *err, int lineno) +{ + if (lineno) + fprintf(stderr, "Error: Line %d: %s\n", lineno, err); + else + fprintf(stderr, "Error: %s\n", err); +} + +static void sensors_default_parse_error_wfn(const char *err, + const char *filename, int lineno) +{ + /* If application provided a custom parse error reporting function + but not the variant with the filename, fall back to the original + variant without the filename, for backwards compatibility. */ + if (sensors_parse_error != sensors_default_parse_error || + !filename) + return sensors_parse_error(err, lineno); + + if (lineno) + fprintf(stderr, "Error: File %s, line %d: %s\n", filename, + lineno, err); + else + fprintf(stderr, "Error: File %s: %s\n", filename, err); +} + +static void sensors_default_fatal_error(const char *proc, const char *err) +{ + fprintf(stderr, "Fatal error in `%s': %s\n", proc, err); + exit(1); +} + +void (*sensors_parse_error) (const char *err, int lineno) = + sensors_default_parse_error; +void (*sensors_parse_error_wfn) (const char *err, const char *filename, + int lineno) = sensors_default_parse_error_wfn; +void (*sensors_fatal_error) (const char *proc, const char *err) = + sensors_default_fatal_error; diff --git a/lib/error.h b/lib/error.h new file mode 100644 index 0000000..eb23613 --- /dev/null +++ b/lib/error.h @@ -0,0 +1,74 @@ +/* + error.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + Copyright (C) 2007-2010 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_SENSORS_ERROR_H +#define LIB_SENSORS_ERROR_H + +#define SENSORS_ERR_WILDCARDS 1 /* Wildcard found in chip name */ +#define SENSORS_ERR_NO_ENTRY 2 /* No such subfeature known */ +#define SENSORS_ERR_ACCESS_R 3 /* Can't read */ +#define SENSORS_ERR_KERNEL 4 /* Kernel interface error */ +#define SENSORS_ERR_DIV_ZERO 5 /* Divide by zero */ +#define SENSORS_ERR_CHIP_NAME 6 /* Can't parse chip name */ +#define SENSORS_ERR_BUS_NAME 7 /* Can't parse bus name */ +#define SENSORS_ERR_PARSE 8 /* General parse error */ +#define SENSORS_ERR_ACCESS_W 9 /* Can't write */ +#define SENSORS_ERR_IO 10 /* I/O error */ +#define SENSORS_ERR_RECURSION 11 /* Evaluation recurses too deep */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* This function returns a pointer to a string which describes the error. + errnum may be negative (the corresponding positive error is returned). + You may not modify the result! */ +const char *sensors_strerror(int errnum); + +/* These functions are called when a parse error is detected. Give them new + values, and your own functions are called instead of the default (which + print to stderr). These functions may terminate the program, but they + usually output an error and return. The first function is the original + one, the second one was added later when support for multiple + configuration files was added. + The library code now only calls the second function. However, for + backwards compatibility, if an application provides a custom handling + function for the first function but not the second, then all parse + errors will be reported using the first function (that is, the filename + is never reported.) + Note that filename can be NULL (if filename isn't known) and lineno + can be 0 (if the error occurs before the actual parsing starts.) */ +extern void (*sensors_parse_error) (const char *err, int lineno); +extern void (*sensors_parse_error_wfn) (const char *err, + const char *filename, int lineno); + +/* This function is called when an immediately fatal error (like no + memory left) is detected. Give it a new value, and your own function + is called instead of the default (which prints to stderr and ends + the program). Never let it return! */ +extern void (*sensors_fatal_error) (const char *proc, const char *err); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* def LIB_SENSORS_ERROR_H */ diff --git a/lib/general.c b/lib/general.c new file mode 100644 index 0000000..f237e3b --- /dev/null +++ b/lib/general.c @@ -0,0 +1,85 @@ +/* + general.c - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#include "error.h" +#include "general.h" +#include +#include +#include +#include + + +#define A_BUNCH 16 + +void sensors_malloc_array(void *list, int *num_el, int *max_el, int el_size) +{ + void **my_list = (void **)list; + + *my_list = malloc(el_size*A_BUNCH); + if (! *my_list) + sensors_fatal_error(__func__, "Allocating new elements"); + *max_el = A_BUNCH; + *num_el = 0; +} + +void sensors_free_array(void *list, int *num_el, int *max_el) +{ + void **my_list = (void **)list; + + free(*my_list); + *my_list = NULL; + *num_el = 0; + *max_el = 0; +} + +void sensors_add_array_el(const void *el, void *list, int *num_el, + int *max_el, int el_size) +{ + int new_max_el; + void **my_list = (void *)list; + if (*num_el + 1 > *max_el) { + new_max_el = *max_el + A_BUNCH; + *my_list = realloc(*my_list, new_max_el * el_size); + if (! *my_list) + sensors_fatal_error(__func__, + "Allocating new elements"); + *max_el = new_max_el; + } + memcpy(((char *) *my_list) + *num_el * el_size, el, el_size); + (*num_el) ++; +} + +void sensors_add_array_els(const void *els, int nr_els, void *list, + int *num_el, int *max_el, int el_size) +{ + int new_max_el; + void **my_list = (void *)list; + if (*num_el + nr_els > *max_el) { + new_max_el = (*max_el + nr_els + A_BUNCH); + new_max_el -= new_max_el % A_BUNCH; + *my_list = realloc(*my_list, new_max_el * el_size); + if (! *my_list) + sensors_fatal_error(__func__, + "Allocating new elements"); + *max_el = new_max_el; + } + memcpy(((char *)*my_list) + *num_el * el_size, els, el_size * nr_els); + *num_el += nr_els; +} diff --git a/lib/general.h b/lib/general.h new file mode 100644 index 0000000..5d03bd2 --- /dev/null +++ b/lib/general.h @@ -0,0 +1,39 @@ +/* + general.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_SENSORS_GENERAL_H +#define LIB_SENSORS_GENERAL_H + +/* These are general purpose functions. They allow you to use variable- + length arrays, which are extended automatically. A distinction is + made between the current number of elements and the maximum number. + You can only add elements at the end. Primitive, but very useful + for internal use. */ +void sensors_malloc_array(void *list, int *num_el, int *max_el, + int el_size); +void sensors_free_array(void *list, int *num_el, int *max_el); +void sensors_add_array_el(const void *el, void *list, int *num_el, + int *max_el, int el_size); +void sensors_add_array_els(const void *els, int nr_els, void *list, + int *num_el, int *max_el, int el_size); + +#define ARRAY_SIZE(arr) (int)(sizeof(arr) / sizeof((arr)[0])) + +#endif /* def LIB_SENSORS_GENERAL_H */ diff --git a/lib/init.c b/lib/init.c new file mode 100644 index 0000000..33bee0f --- /dev/null +++ b/lib/init.c @@ -0,0 +1,341 @@ +/* + init.c - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + Copyright (C) 2007-2013 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* Needed for scandir() and alphasort() */ +#define _BSD_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sensors.h" +#include "data.h" +#include "error.h" +#include "access.h" +#include "conf.h" +#include "sysfs.h" +#include "scanner.h" +#include "init.h" + +#define DEFAULT_CONFIG_FILE ETCDIR "/sensors3.conf" +#define ALT_CONFIG_FILE ETCDIR "/sensors.conf" +#define DEFAULT_CONFIG_DIR ETCDIR "/sensors.d" + +/* Wrapper around sensors_yyparse(), which clears the locale so that + the decimal numbers are always parsed properly. */ +static int sensors_parse(void) +{ + int res; + char *locale; + + /* Remember the current locale and clear it */ + locale = setlocale(LC_ALL, NULL); + if (locale) { + locale = strdup(locale); + if (!locale) + sensors_fatal_error(__func__, "Out of memory"); + + setlocale(LC_ALL, "C"); + } + + res = sensors_yyparse(); + + /* Restore the old locale */ + if (locale) { + setlocale(LC_ALL, locale); + free(locale); + } + + return res; +} + +static void free_bus(sensors_bus *bus) +{ + free(bus->adapter); +} + +static void free_config_busses(void) +{ + int i; + + for (i = 0; i < sensors_config_busses_count; i++) + free_bus(&sensors_config_busses[i]); + free(sensors_config_busses); + sensors_config_busses = NULL; + sensors_config_busses_count = sensors_config_busses_max = 0; +} + +static int parse_config(FILE *input, const char *name) +{ + int err; + char *name_copy; + + if (name) { + /* Record configuration file name for error reporting */ + name_copy = strdup(name); + if (!name_copy) + sensors_fatal_error(__func__, "Out of memory"); + sensors_add_config_files(&name_copy); + } else + name_copy = NULL; + + if (sensors_scanner_init(input, name_copy)) { + err = -SENSORS_ERR_PARSE; + goto exit_cleanup; + } + err = sensors_parse(); + sensors_scanner_exit(); + if (err) { + err = -SENSORS_ERR_PARSE; + goto exit_cleanup; + } + + err = sensors_substitute_busses(); + +exit_cleanup: + free_config_busses(); + return err; +} + +static int config_file_filter(const struct dirent *entry) +{ + return entry->d_name[0] != '.'; /* Skip hidden files */ +} + +static int add_config_from_dir(const char *dir) +{ + int count, res, i; + struct dirent **namelist; + + count = scandir(dir, &namelist, config_file_filter, alphasort); + if (count < 0) { + /* Do not return an error if directory does not exist */ + if (errno == ENOENT) + return 0; + + sensors_parse_error_wfn(strerror(errno), NULL, 0); + return -SENSORS_ERR_PARSE; + } + + for (res = 0, i = 0; !res && i < count; i++) { + int len; + char path[PATH_MAX]; + FILE *input; + struct stat st; + + len = snprintf(path, sizeof(path), "%s/%s", dir, + namelist[i]->d_name); + if (len < 0 || len >= (int)sizeof(path)) { + res = -SENSORS_ERR_PARSE; + continue; + } + + /* Only accept regular files */ + if (stat(path, &st) < 0 || !S_ISREG(st.st_mode)) + continue; + + input = fopen(path, "r"); + if (input) { + res = parse_config(input, path); + fclose(input); + } else { + res = -SENSORS_ERR_PARSE; + sensors_parse_error_wfn(strerror(errno), path, 0); + } + } + + /* Free memory allocated by scandir() */ + for (i = 0; i < count; i++) + free(namelist[i]); + free(namelist); + + return res; +} + +/* Ideally, initialization and configuraton file loading should be exposed + separately, to make it possible to load several configuration files. */ +int sensors_init(FILE *input) +{ + int res; + + if (!sensors_init_sysfs()) + return -SENSORS_ERR_KERNEL; + if ((res = sensors_read_sysfs_bus()) || + (res = sensors_read_sysfs_chips())) + goto exit_cleanup; + + if (input) { + res = parse_config(input, NULL); + if (res) + goto exit_cleanup; + } else { + const char* name; + + /* No configuration provided, use default */ + input = fopen(name = DEFAULT_CONFIG_FILE, "r"); + if (!input && errno == ENOENT) + input = fopen(name = ALT_CONFIG_FILE, "r"); + if (input) { + res = parse_config(input, name); + fclose(input); + if (res) + goto exit_cleanup; + + } else if (errno != ENOENT) { + sensors_parse_error_wfn(strerror(errno), name, 0); + res = -SENSORS_ERR_PARSE; + goto exit_cleanup; + } + + /* Also check for files in default directory */ + res = add_config_from_dir(DEFAULT_CONFIG_DIR); + if (res) + goto exit_cleanup; + } + + return 0; + +exit_cleanup: + sensors_cleanup(); + return res; +} + +static void free_chip_name(sensors_chip_name *name) +{ + free(name->prefix); + free(name->path); +} + +static void free_chip_features(sensors_chip_features *features) +{ + int i; + + for (i = 0; i < features->subfeature_count; i++) + free(features->subfeature[i].name); + free(features->subfeature); + for (i = 0; i < features->feature_count; i++) + free(features->feature[i].name); + free(features->feature); +} + +static void free_label(sensors_label *label) +{ + free(label->name); + free(label->value); +} + +void sensors_free_expr(sensors_expr *expr) +{ + if (expr->kind == sensors_kind_var) + free(expr->data.var); + else if (expr->kind == sensors_kind_sub) { + if (expr->data.subexpr.sub1) + sensors_free_expr(expr->data.subexpr.sub1); + if (expr->data.subexpr.sub2) + sensors_free_expr(expr->data.subexpr.sub2); + } + free(expr); +} + +static void free_set(sensors_set *set) +{ + free(set->name); + sensors_free_expr(set->value); +} + +static void free_compute(sensors_compute *compute) +{ + free(compute->name); + sensors_free_expr(compute->from_proc); + sensors_free_expr(compute->to_proc); +} + +static void free_ignore(sensors_ignore *ignore) +{ + free(ignore->name); +} + +static void free_chip(sensors_chip *chip) +{ + int i; + + for (i = 0; i < chip->chips.fits_count; i++) + free_chip_name(&chip->chips.fits[i]); + free(chip->chips.fits); + chip->chips.fits_count = chip->chips.fits_max = 0; + + for (i = 0; i < chip->labels_count; i++) + free_label(&chip->labels[i]); + free(chip->labels); + chip->labels_count = chip->labels_max = 0; + + for (i = 0; i < chip->sets_count; i++) + free_set(&chip->sets[i]); + free(chip->sets); + chip->sets_count = chip->sets_max = 0; + + for (i = 0; i < chip->computes_count; i++) + free_compute(&chip->computes[i]); + free(chip->computes); + chip->computes_count = chip->computes_max = 0; + + for (i = 0; i < chip->ignores_count; i++) + free_ignore(&chip->ignores[i]); + free(chip->ignores); + chip->ignores_count = chip->ignores_max = 0; +} + +void sensors_cleanup(void) +{ + int i; + + for (i = 0; i < sensors_proc_chips_count; i++) { + free_chip_name(&sensors_proc_chips[i].chip); + free_chip_features(&sensors_proc_chips[i]); + } + free(sensors_proc_chips); + sensors_proc_chips = NULL; + sensors_proc_chips_count = sensors_proc_chips_max = 0; + + for (i = 0; i < sensors_config_chips_count; i++) + free_chip(&sensors_config_chips[i]); + free(sensors_config_chips); + sensors_config_chips = NULL; + sensors_config_chips_count = sensors_config_chips_max = 0; + sensors_config_chips_subst = 0; + + for (i = 0; i < sensors_proc_bus_count; i++) + free_bus(&sensors_proc_bus[i]); + free(sensors_proc_bus); + sensors_proc_bus = NULL; + sensors_proc_bus_count = sensors_proc_bus_max = 0; + + for (i = 0; i < sensors_config_files_count; i++) + free(sensors_config_files[i]); + free(sensors_config_files); + sensors_config_files = NULL; + sensors_config_files_count = sensors_config_files_max = 0; +} diff --git a/lib/init.h b/lib/init.h new file mode 100644 index 0000000..799f1ef --- /dev/null +++ b/lib/init.h @@ -0,0 +1,28 @@ +/* + init.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (C) 2007-2010 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_SENSORS_INIT_H +#define LIB_SENSORS_INIT_H + +#include "data.h" + +void sensors_free_expr(sensors_expr *expr); + +#endif /* def LIB_SENSORS_INIT_H */ diff --git a/lib/libsensors.3 b/lib/libsensors.3 new file mode 100644 index 0000000..bfb67c4 --- /dev/null +++ b/lib/libsensors.3 @@ -0,0 +1,290 @@ +.\" Copyright (C) 1998, 1999 Adrian Baugh +.\" Copyright (C) 2007, 2009, 2013 Jean Delvare +.\" based on sensors.h, part of libsensors by Frodo Looijaard +.\" libsensors is distributed under the LGPL +.\" +.\" Permission is granted to make and distribute verbatim copies of this +.\" manual provided the copyright notice and this permission notice are +.\" preserved on all copies. +.\" +.\" Permission is granted to copy and distribute modified versions of this +.\" manual under the conditions for verbatim copying, provided that the +.\" entire resulting derived work is distributed under the terms of a +.\" permission notice identical to this one +.\" +.\" Since the Linux kernel and libraries are constantly changing, this +.\" manual page may be incorrect or out-of-date. The author(s) assume no +.\" responsibility for errors or omissions, or for damages resulting from +.\" the use of the information contained herein. The author(s) may not +.\" have taken the same level of care in the production of this manual, +.\" which is licensed free of charge, as they might when working +.\" professionally. +.\" +.\" Formatted or processed versions of this manual, if unaccompanied by +.\" the source, must acknowledge the copyright and authors of this work. +.\" +.\" References consulted: +.\" libsensors source code +.TH libsensors 3 "September 2013" "lm-sensors 3" "Linux Programmer's Manual" + +.SH NAME +libsensors \- publicly accessible functions provided by the sensors library + +.SH SYNOPSIS +.nf +.B #include + +/* Library initialization and clean-up */ +.BI "int sensors_init(FILE *" input ");" +.B void sensors_cleanup(void); +.BI "const char *" libsensors_version ";" + +/* Chip name handling */ +.BI "int sensors_parse_chip_name(const char *" orig_name "," +.BI " sensors_chip_name *" res ");" +.BI "void sensors_free_chip_name(sensors_chip_name *" chip ");" +.BI "int sensors_snprintf_chip_name(char *" str ", size_t " size "," +.BI " const sensors_chip_name *" chip ");" +.BI "const char *sensors_get_adapter_name(const sensors_bus_id *" bus ");" + +/* Chips and features enumeration */ +.B const sensors_chip_name * +.BI "sensors_get_detected_chips(const sensors_chip_name *" match "," +.BI " int *" nr ");" +.B const sensors_feature * +.BI "sensors_get_features(const sensors_chip_name *" name "," +.BI " int *" nr ");" +.B const sensors_subfeature * +.BI "sensors_get_all_subfeatures(const sensors_chip_name *" name "," +.BI " const sensors_feature *" feature "," +.BI " int *" nr ");" +.B const sensors_subfeature * +.BI "sensors_get_subfeature(const sensors_chip_name *" name "," +.BI " const sensors_feature *" feature "," +.BI " sensors_subfeature_type " type ");" + +/* Features access */ +.BI "char *sensors_get_label(const sensors_chip_name *" name "," +.BI " const sensors_feature *" feature ");" +.BI "int sensors_get_value(const sensors_chip_name *" name ", int " subfeat_nr "," +.BI " double *" value ");" +.BI "int sensors_set_value(const sensors_chip_name *" name ", int " subfeat_nr "," +.BI " double " value ");" +.BI "int sensors_do_chip_sets(const sensors_chip_name *" name ");" + +.B #include + +/* Error decoding */ +.BI "const char *sensors_strerror(int " errnum ");" + +/* Error handlers */ +.BI "void (*sensors_parse_error) (const char *" err ", int " lineno ");" +.BI "void (*sensors_parse_error_wfn) (const char *" err "," +.BI " const char *" filename ", int " lineno ");" +.BI "void (*sensors_fatal_error) (const char *" proc ", const char *" err ");" +.fi + +.SH DESCRIPTION +.B sensors_init() +loads the configuration file and the detected chips list. If this returns a +value unequal to zero, you are in trouble; you can not assume anything will +be initialized properly. If you want to reload the configuration file, or +load a different configuration file, call sensors_cleanup() below before +calling sensors_init() again. This means you can't load multiple configuration +files at once by calling sensors_init() multiple times. + +The configuration file format is described in sensors.conf(5). + +If FILE is NULL, the default configuration files are used (see the FILES +section below). Most applications will want to do that. + +.B sensors_cleanup() +cleans everything up: you can't access anything after this, until the next sensors_init() call! + +.B libsensors_version +is a string representing the version of libsensors. + +.B sensors_parse_chip_name() +parses a chip name to the internal representation. Return 0 on success, +<0 on error. Make sure to call sensors_free_chip_name() when you're done +with the data. + +.B sensors_free_chip_name() +frees the memory that may have been allocated for the internal +representation of a chip name. You only have to call this for chip +names which do not originate from libsensors itself (that is, chip +names which were generated by sensors_parse_chip_name()). + +.B sensors_snprintf_chip_name() +prints a chip name from its internal representation. Note that chip should +not contain wildcard values! Return the number of characters printed on +success (same as snprintf), <0 on error. + +.B sensors_get_adapter_name() +returns the adapter name of a bus type, number pair, as used within the +sensors_chip_name structure. If it could not be found, it returns NULL. + +Adapters describe how a monitoring chip is hooked up to the system. +This is particularly relevant for I2C/SMBus sensor chips (bus type "i2c"), +which must be accessed over an I2C/SMBus controller. Each such controller +has a different number, assigned by the system at initialization time, +so that they can be referenced individually. + +Super\-I/O or CPU\-embedded sensors, on the other hand, can be accessed +directly and technically don't use any adapter. They have only a bus type +but no bus number, and sensors_get_adapter_name() will return a generic +adapter name for them. + +.B sensors_get_detected_chips() +returns all detected chips that match a given chip name, +one by one. If no chip name is provided, all detected chips are returned. +To start at the beginning of the list, use 0 for nr; NULL is returned if +we are at the end of the list. Do not try to change these chip names, as +they point to internal structures! + +.B sensors_get_features() +returns all main features of a specific chip. nr is an internally +used variable. Set it to zero to start at the begin of the list. If no +more features are found NULL is returned. +Do not try to change the returned structure; you will corrupt internal +data structures. + +.B sensors_get_all_subfeatures() +returns all subfeatures of a given main feature. nr is an internally +used variable. Set it to zero to start at the begin of the list. If no +more subfeatures are found NULL is returned. +Do not try to change the returned structure; you will corrupt internal +data structures. + +.B sensors_get_subfeature() +returns the subfeature of the given type for a given main feature, +if it exists, NULL otherwise. +Do not try to change the returned structure; you will corrupt internal +data structures. + +.B sensors_get_label() +looks up the label which belongs to this chip. Note that chip should not +contain wildcard values! The returned string is newly allocated (free it +yourself). On failure, NULL is returned. +If no label exists for this feature, its name is returned itself. + +.B sensors_get_value() +Reads the value of a subfeature of a certain chip. Note that chip should not +contain wildcard values! This function will return 0 on success, and <0 on +failure. + +.B sensors_set_value() +sets the value of a subfeature of a certain chip. Note that chip should not +contain wildcard values! This function will return 0 on success, and <0 on +failure. + +.B sensors_do_chip_sets() +executes all set statements for this particular chip. The chip may contain +wildcards! This function will return 0 on success, and <0 on failure. + +.B sensors_strerror() +returns a pointer to a string which describes the error. +errnum may be negative (the corresponding positive error is returned). +You may not modify the result! + +.B sensors_parse_error() +and +.B sensors_parse_error_wfn() +are functions which are called when a parse error is detected. Give them +new values, and your own functions are called instead of the default (which +print to stderr). These functions may terminate the program, but they +usually output an error and return. The first function is the original +one, the second one was added later when support for multiple +configuration files was added. +The library code now only calls the second function. However, for +backwards compatibility, if an application provides a custom handling +function for the first function but not the second, then all parse +errors will be reported using the first function (that is, the filename +is never reported.) +Note that filename can be NULL (if filename isn't known) and lineno +can be 0 (if the error occurs before the actual parsing starts.) + +.B sensors_fatal_error() +Is a function which is called when an immediately fatal error (like no +memory left) is detected. Give it a new value, and your own function +is called instead of the default (which prints to stderr and ends +the program). Never let it return! + +.SH DATA STRUCTURES + +Structure \fBsensors_chip_name\fR contains information related to a +specific chip. + +\fBtypedef struct sensors_chip_name { +.br + sensors_bus_id bus; +.br +} sensors_chip_name;\fP + +There are other members not documented here, which are only meant for +libsensors internal use. + +Structure \fBsensors_feature\fR contains information related to a given +feature of a specific chip: + +\fBtypedef struct sensors_feature { +.br + const char *name; +.br + int number; +.br + sensors_feature_type type; +.br +} sensors_feature;\fP + +There are other members not documented here, which are only meant for +libsensors internal use. + +Structure \fBsensors_subfeature\fR contains information related to a given +subfeature of a specific chip feature: + +\fBtypedef struct sensors_subfeature { +.br + const char *name; +.br + int number; +.br + sensors_subfeature_type type; +.br + int mapping; +.br + unsigned int flags; +.br +} sensors_subfeature;\fP + +The flags field is a bitfield, its value is a combination of +\fBSENSORS_MODE_R\fR (readable), \fBSENSORS_MODE_W\fR (writable) and +\fBSENSORS_COMPUTE_MAPPING\fR (affected by the computation rules of the +main feature). + +.SH FILES +.I /etc/sensors3.conf +.br +.I /etc/sensors.conf +.RS +The system-wide +.BR libsensors (3) +configuration file. /etc/sensors3.conf is tried first, and if it doesn't exist, +/etc/sensors.conf is used instead. +.RE + +.I /etc/sensors.d +.RS +A directory where you can put additional libsensors configuration files. +Files found in this directory will be processed in alphabetical order after +the default configuration file. Files with names that start with a dot are +ignored. +.RE + +.SH SEE ALSO +sensors.conf(5) + +.SH AUTHOR +Frodo Looijaard, Jean Delvare and others +http://www.lm-sensors.org/ + diff --git a/lib/libsensors.map b/lib/libsensors.map new file mode 100644 index 0000000..5e2dac0 --- /dev/null +++ b/lib/libsensors.map @@ -0,0 +1,23 @@ +{ +global: + libsensors_version; + sensors_cleanup; + sensors_do_chip_sets; + sensors_free_chip_name; + sensors_get_adapter_name; + sensors_get_all_subfeatures; + sensors_get_detected_chips; + sensors_get_features; + sensors_get_label; + sensors_get_subfeature; + sensors_get_value; + sensors_init; + sensors_parse_chip_name; + sensors_set_value; + sensors_snprintf_chip_name; + sensors_strerror; + sensors_parse_error; + sensors_parse_error_wfn; + sensors_fatal_error; +local: *; + }; diff --git a/lib/scanner.h b/lib/scanner.h new file mode 100644 index 0000000..4fb4c02 --- /dev/null +++ b/lib/scanner.h @@ -0,0 +1,28 @@ +/* + scanner.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 2006 Mark M. Hoffman + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_SENSORS_SCANNER_H +#define LIB_SENSORS_SCANNER_H + +int sensors_scanner_init(FILE *input, const char *filename); +void sensors_scanner_exit(void); + +#endif /* def LIB_SENSORS_SCANNER_H */ + diff --git a/lib/sensors.conf.5 b/lib/sensors.conf.5 new file mode 100644 index 0000000..d869523 --- /dev/null +++ b/lib/sensors.conf.5 @@ -0,0 +1,573 @@ +.\" Copyright (C) 1998, 1999 Adrian Baugh and +.\" Frodo Looijaard +.\" Copyright (C) 2008--2012 Jean Delvare +.\" +.\" Permission is granted to make and distribute verbatim copies of this +.\" manual provided the copyright notice and this permission notice are +.\" preserved on all copies. +.\" +.\" Permission is granted to copy and distribute modified versions of this +.\" manual under the conditions for verbatim copying, provided that the +.\" entire resulting derived work is distributed under the terms of a +.\" permission notice identical to this one. +.\" +.\" Since the Linux kernel and libraries are constantly changing, this +.\" manual page may be incorrect or out-of-date. The author(s) assume no +.\" responsibility for errors or omissions, or for damages resulting from +.\" the use of the information contained herein. +.\" +.\" Formatted or processed versions of this manual, if unaccompanied by +.\" the source, must acknowledge the copyright and authors of this work. +.\" +.\" References consulted: +.\" sensors.conf.eg by Frodo Looijaard +.TH sensors.conf 5 "November 2012" "lm-sensors 3" "Linux User's Manual" +.SH NAME +sensors.conf \- libsensors configuration file + +.SH DESCRIPTION +sensors.conf describes how libsensors, and so all programs using it, should +translate the raw readings from the kernel modules to real\-world values. + +.SH SEMANTICS + +On a given system, there may be one or more hardware monitoring chips. +Each chip may have several features. For example, the LM78 monitors 7 +voltage inputs, 3 fans and one temperature. Feature names are +standardized. Typical feature names are in0, in1, in2... for voltage +inputs, fan1, fan2, fan3... for fans and temp1, temp2, temp3... for +temperature inputs. + +Each feature may in turn have one or more sub\-features, each +representing an attribute of the feature: input value, low limit, high +limit, alarm, etc. Sub\-feature names are standardized as well. For +example, the first voltage input (in0) would typically have +sub\-features in0_input (measured value), in0_min (low limit), in0_max +(high limit) and in0_alarm (alarm flag). Which sub\-features are +actually present depend on the exact chip type. + +The +.I sensors.conf +configuration file will let you configure each chip, feature and +sub\-feature in a way that makes sense for your system. + +The rest of this section describes the meaning of each configuration +statement. + +.SS CHIP STATEMENT + +A +.I chip +statement selects for which chips all following +.IR compute , +.IR label , +.I ignore +and +.I set +statements are meant. A chip +selection remains valid until the next +.I chip +statement. Example: + +.RS +chip "lm78\-*" "lm79\-*" +.RE + +If a chip matches at least one of the chip descriptions, the following +configuration lines are examined for it, otherwise they are ignored. + +A chip description is built from several elements, separated by +dashes. The first element is the chip type, the second element is +the name of the bus, and the third element is the hexadecimal address +of the chip. Such chip descriptions are printed by sensors(1) as the +first line for every chip. + +The name of the bus is either +.IR isa , +.IR pci , +.IR virtual , +.I spi-*, +.I i2c-N +or +.I mdio +with +.I N +being a bus number as bound with a +.I bus +statement. This list isn't necessarily exhaustive as support for other +bus types may be added in the future. + +You may substitute the wildcard operator +.I * +for every element. Note however that it wouldn't make any sense to specify +the address without the bus type, so the address part is plain omitted +when the bus type isn't specified. +Here is how you would express the following matches: + +.TS +l l. +LM78 chip at address 0x2d on I2C bus 1 lm78\-i2c\-1\-2d +LM78 chip at address 0x2d on any I2C bus lm78\-i2c\-*\-2d +LM78 chip at address 0x290 on the ISA bus lm78\-isa\-0290 +Any LM78 chip on I2C bus 1 lm78\-i2c\-1\-* +Any LM78 on any I2C bus lm78\-i2c\-*\-* +Any LM78 chip on the ISA bus lm78\-isa\-* +Any LM78 chip lm78\-* +Any chip at address 0x2d on I2C bus 1 *\-i2c\-1\-2d +Any chip at address 0x290 on the ISA bus *\-isa\-0290 +.TE + +If several chip statements match a specific chip, they are all considered. + +.SS LABEL STATEMENT + +A +.I label +statement describes how a feature should be called. Features without a +.I label +statement are just called by their feature name. Applications can use this +to label the readings they present. Example: + +.RS +label in3 "+5V" +.RE + +The first argument is the feature name. The second argument is the feature +description. + +Note that you must use the raw feature name, which is not necessarily the +one displayed by "sensors" by default. Use "sensors \-u" to see the raw +feature names. Same applies to all other statement types below. + +.SS IGNORE STATEMENT + +An +.I ignore +statement is a hint that a specific feature should be ignored - probably +because it returns bogus values (for example, because a fan or temperature +sensor is not connected). Example: + +.RS +ignore fan1 +.RE + +The only argument is the feature name. Please note that this does not disable +anything in the actual sensor chip; it simply hides the feature in question +from libsensors users. + +.SS COMPUTE STATEMENT + +A +.I compute +statement describes how a feature's raw value should be translated to a +real\-world value, and how a real\-world value should be translated back +to a raw value again. This is most useful for voltage sensors, because +in general sensor chips have a limited range and voltages outside this +range must be divided (using resistors) before they can be monitored. +Example: + +.RS +compute in3 ((6.8/10)+1)*@, @/((6.8/10)+1) +.RE + +The example above expresses the fact that the voltage input is divided +using two resistors of values 6.8 Ohm and 10 Ohm, respectively. See the +.B VOLTAGE COMPUTATION DETAILS +section below for details. + +The first argument is the feature name. The second argument is an expression +which specifies how a raw value must be translated to a real\-world value; +`@' stands here for the raw value. This is the formula which will be applied +when reading values from the chip. The third argument is an expression that +specifies how a real\-world value should be translated back to a raw value; +`@' stands here for the real\-world value. This is the formula which will be +applied when writing values to the chip. The two formulas are obviously +related, and are separated by a comma. + +A +.I compute +statement applies to all sub\-features of the target feature for which +it makes sense. For example, the above example would affect sub\-features +in3_min and in3_max (which are voltage values) but not in3_alarm +(which is a boolean flag.) + +The following operators are supported in +.I compute +statements: +.RS ++ \- * / ( ) ^ ` +.RE +^x means exp(x) and `x means ln(x). + +You may use the name of sub\-features in these expressions; current readings +are substituted. You should be careful though to avoid circular references. + +If at any moment a translation between a raw and a real\-world value is +called for, but no +.I compute +statement applies, a one\-on\-one translation is used instead. + +.SS SET STATEMENT + +A +.I set +statement is used to write a sub\-feature value to the chip. Of course not +all sub\-feature values can be set that way, in particular input values +and alarm flags can not. Valid sub\-features are usually min/max limits. +Example: + +.RS +set in3_min 5 * 0.95 +.RE +.RS +set in3_max 5 * 1.05 +.RE + +The example above basically configures the chip to allow a 5% deviance +for the +5V power input. + +The first argument is the feature name. The second argument is an expression +which determines the written value. If there is an applying +.I compute +statement, this value is fed to its third argument to translate it to a +raw value. + +You may use the name of sub\-features in these expressions; current readings +are substituted. You should be careful though to avoid circular references. + +Please note that +.I set +statements are only executed by sensors(1) when you use the +.B \-s +option. Typical graphical sensors applications do not care about these +statements at all. + +.SS BUS STATEMENT + +A +.I bus +statement binds the description of an I2C or SMBus adapter to a bus number. +This makes it possible to refer to an adapter in the configuration file, +independent of the actual correspondence of bus numbers and actual +adapters (which may change from moment to moment). Example: + +.RS +bus "i2c\-0" "SMBus PIIX4 adapter at e800" +.RE + +The first argument is the bus number. It is the literal text +.IR i2c\- , +followed by a number. As there is a dash in this argument, it must +always be quoted. + +The second argument is the adapter name, it must match exactly the +adapter name as it appears in +.IR /sys/class/i2c\-adapter/i2c\-*/name . +It should always be quoted as well as it will most certainly contain +spaces or dashes. + +The +.I bus +statements may be scattered randomly throughout the configuration file; +there is no need to place the bus line before the place where its binding +is referred to. Still, as a matter of good style, we suggest you place +all +.I bus +statements together at the top of your configuration file. + +Running +.B sensors --bus-list +will generate these lines for you. + +In the case where multiple configuration files are used, the scope +of each +.I bus +statement is the configuration file it was defined in. This makes it +possible to have bus statements in all configuration files which will +not unexpectedly interfere with each other. + +.SS STATEMENT ORDER + +Statements can go in any order, however it is recommended to put +`set fanX_div' statements before `set fanX_min' statements, in case +a driver doesn't preserve the fanX_min setting when the fanX_div +value is changed. Even if the driver does, it's still better to put +the statements in this order to avoid accuracy loss. + +.SH VOLTAGE COMPUTATION DETAILS + +Most voltage sensors in sensor chips have a range of 0 to 4.08 V. +This is generally sufficient for the +3.3V and CPU supply voltages, so +the sensor chip reading is the actual voltage. + +Other supply voltages must be scaled with an external resistor network. +The driver reports the value at the chip's pin (0 \- 4.08 V), and the +userspace application must convert this raw value to an actual voltage. +The +.I compute +statements provide this facility. + +Unfortunately the resistor values vary among motherboard types. +Therefore you have to figure out the correct resistor values for your +own motherboard. + +For positive voltages (typically +5V and +12V), two resistors are used, +with the following formula: + R1 = R2 * (Vs/Vin \- 1) + +where: + R1 and R2 are the resistor values + Vs is the actual voltage being monitored + Vin is the voltage at the pin + +This leads to the following compute formula: + compute inX @*((R1/R2)+1), @/(((R1/R2)+1) + +Real\-world formula for +5V and +12V would look like: + compute in3 @*((6.8/10)+1), @/((6.8/10)+1) + compute in4 @*((28/10)+1), @/((28/10)+1) + +For negative voltages (typically \-5V and \-12V), two resistors are used +as well, but different boards use different strategies to bring the +voltage value into the 0 \- 4.08 V range. Some use an inverting +amplifier, others use a positive reference voltage. This leads to +different computation formulas. Note that most users won't have to care +because most modern motherboards make little use of \-12V and no use of +\-5V so they do not bother monitoring these voltage inputs. + +Real\-world examples for the inverting amplifier case: + compute in5 \-@*(240/60), \-@/(240/60) + compute in6 \-@*(100/60), \-@/(100/60) + +Real\-world examples for the positive voltage reference case: + compute in5 @*(1+232/56) \- 4.096*232/56, (@ + 4.096*232/56)/(1+232/56) + compute in6 @*(1+120/56) \- 4.096*120/56, (@ + 4.096*120/56)/(1+120/56) + +Many recent monitoring chips have a 0 \- 2.04 V range, so scaling resistors +are even more needed, and resistor values are different. + +There are also a few chips out there which have internal scaling +resistors, meaning that their value is known and doesn't change from +one motherboard to the next. For these chips, the driver usually +handles the scaling so it is transparent to the user and no +.I compute +statements are needed. + +.SH TEMPERATURE CONFIGURATION + +On top of the usual features, temperatures can have two specific +sub\-features: temperature sensor type (tempX_type) and hysteresis +values (tempX_max_hyst, tempX_crit_hyst etc.). + +.SS THERMAL SENSOR TYPES + +Available thermal sensor types: +.TS +r l. +1 PII/Celeron Diode +2 3904 transistor +3 thermal diode +4 thermistor +5 AMD AMDSI +6 Intel PECI +.TE + +For example, to set temp1 to thermistor type, use: + +.RS +set temp1_type 4 +.RE + +Only certain chips support thermal sensor type change, and even these +usually only support some of the types above. Please refer to the +specific driver documentation to find out which types are supported +by your chip. + +In theory, the BIOS should have configured the sensor types correctly, +so you shouldn't have to touch them, but sometimes it isn't the case. + +.SS THERMAL HYSTERESIS MECHANISM + +Many monitoring chips do not handle the high and critical temperature +limits as simple limits. Instead, they have two values for each +limit, one which triggers an alarm when the temperature rises and another +one which clears the alarm when the temperature falls. The latter is +typically a few degrees below the former. This mechanism is known as +hysteresis. + +The reason for implementing things that way is that high temperature +alarms typically trigger an action to attempt to cool the system down, +either by scaling down the CPU frequency, or by kicking in an extra +fan. This should normally let the temperature fall in a timely manner. +If this was clearing the alarm immediately, then the system would be +back to its original state where the temperature rises and the alarm +would immediately trigger again, causing an undesirable tight fan on, +fan off loop. The hysteresis mechanism ensures that the system is +really cool before the fan stops, so that it will not have to kick in +again immediately. + +So, in addition to tempX_max, many chips have a tempX_max_hyst +sub-feature. Likewise, tempX_crit often comes with tempX_crit_hyst. +tempX_emerg_hyst, tempX_min_hyst and tempX_lcrit_hyst exist too but +aren't as common. +Example: + +.RS +set temp1_max 60 +.RE +.RS +set temp1_max_hyst 56 +.RE + +The hysteresis mechanism can be disabled by giving both limits the same +value. + +Note that it is strongly recommended to set the hysteresis value after +the limit value it relates to in the configuration file. Implementation +details on the hardware or driver side may cause unexpected results if +the hysteresis value is set first. + +.SH BEEPS + +Some chips support alarms with beep warnings. When an alarm is triggered +you can be warned by a beeping signal through your computer speaker. On +top of per\-feature beep flags, there is usually a master beep control +switch to enable or disable beeping globally. Enable beeping using: + +.RS +set beep_enable 1 +.RE + +or disable it using: + +.RS +set beep_enable 0 +.RE + +.SH WHICH STATEMENT APPLIES + +If more than one statement of the same kind applies at a certain moment, +the last one in the configuration file is used. So usually, you should +put more general +.I chip +statements at the top, so you can overrule them below. + +.SH SYNTAX +Comments are introduced by hash marks. A comment continues to the end of the +line. Empty lines, and lines containing only whitespace or comments are +ignored. Other lines have one of the below forms. There must be whitespace +between each element, but the amount of whitespace is unimportant. A line +may be continued on the next line by ending it with a backslash; this does +not work within a comment, +.B NAME +or +.BR NUMBER . + +.RS +bus +.B NAME NAME NAME +.sp 0 +chip +.B NAME\-LIST +.sp 0 +label +.B NAME NAME +.sp 0 +compute +.B NAME EXPR +, +.B EXPR +.sp 0 +ignore +.B NAME +.sp 0 +set +.B NAME EXPR +.RE +.sp +A +.B NAME +is a string. If it only contains letters, digits and underscores, it does not +have to be quoted; in all other cases, you must use double quotes around it. +Within quotes, you can use the normal escape\-codes from C. + +A +.B NAME\-LIST +is one or more +.B NAME +items behind each other, separated by whitespace. + +A +.B EXPR +is of one of the below forms: + +.RS +.B NUMBER +.sp 0 +.B NAME +.sp 0 +@ +.sp 0 +.B EXPR ++ +.B EXPR +.sp 0 +.B EXPR +\- +.B EXPR +.sp 0 +.B EXPR +* +.B EXPR +.sp 0 +.B EXPR +/ +.B EXPR +.sp 0 +\- +.B EXPR +.sp 0 +^ +.B EXPR +.sp 0 +` +.B EXPR +.sp 0 +( +.B EXPR +) +.RE + +A +.B NUMBER +is a floating\-point number. `10', `10.4' and `.4' are examples of valid +floating\-point numbers; `10.' or `10E4' are not valid. + +.SH FILES +.I /etc/sensors3.conf +.br +.I /etc/sensors.conf +.RS +The system-wide +.BR libsensors (3) +configuration file. /etc/sensors3.conf is tried first, and if it doesn't exist, +/etc/sensors.conf is used instead. +.RE + +.I /etc/sensors.d +.RS +A directory where you can put additional libsensors configuration files. +Files found in this directory will be processed in alphabetical order after +the default configuration file. Files with names that start with a dot are +ignored. +.RE + +.SH SEE ALSO +libsensors(3) + +.SH AUTHOR +Frodo Looijaard and the lm_sensors group +http://www.lm-sensors.org/ + + + diff --git a/lib/sensors.h b/lib/sensors.h new file mode 100644 index 0000000..4c4b60a --- /dev/null +++ b/lib/sensors.h @@ -0,0 +1,311 @@ +/* + sensors.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998, 1999 Frodo Looijaard + Copyright (C) 2007-2014 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_SENSORS_SENSORS_H +#define LIB_SENSORS_SENSORS_H + +#include +#include + +/* Publicly accessible library functions */ + +/* libsensors API version define, first digit is the major version (changed + when the API + ABI breaks), the third digit is incremented to track small + API additions like new flags / enum values. The second digit is for tracking + larger additions like new methods. */ +#define SENSORS_API_VERSION 0x440 + +#define SENSORS_CHIP_NAME_PREFIX_ANY NULL +#define SENSORS_CHIP_NAME_ADDR_ANY (-1) + +#define SENSORS_BUS_TYPE_ANY (-1) +#define SENSORS_BUS_TYPE_I2C 0 +#define SENSORS_BUS_TYPE_ISA 1 +#define SENSORS_BUS_TYPE_PCI 2 +#define SENSORS_BUS_TYPE_SPI 3 +#define SENSORS_BUS_TYPE_VIRTUAL 4 +#define SENSORS_BUS_TYPE_ACPI 5 +#define SENSORS_BUS_TYPE_HID 6 +#define SENSORS_BUS_TYPE_MDIO 7 +#define SENSORS_BUS_NR_ANY (-1) +#define SENSORS_BUS_NR_IGNORE (-2) + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern const char *libsensors_version; + +typedef struct sensors_bus_id { + short type; + short nr; +} sensors_bus_id; + +/* A chip name is encoded in this structure */ +typedef struct sensors_chip_name { + char *prefix; + sensors_bus_id bus; + int addr; + char *path; +} sensors_chip_name; + +/* Load the configuration file and the detected chips list. If this + returns a value unequal to zero, you are in trouble; you can not + assume anything will be initialized properly. If you want to + reload the configuration file, call sensors_cleanup() below before + calling sensors_init() again. */ +int sensors_init(FILE *input); + +/* Clean-up function: You can't access anything after + this, until the next sensors_init() call! */ +void sensors_cleanup(void); + +/* Parse a chip name to the internal representation. Return 0 on success, <0 + on error. */ +int sensors_parse_chip_name(const char *orig_name, sensors_chip_name *res); + +/* Free memory allocated for the internal representation of a chip name. */ +void sensors_free_chip_name(sensors_chip_name *chip); + +/* Print a chip name from its internal representation. Note that chip should + not contain wildcard values! Return the number of characters printed on + success (same as snprintf), <0 on error. */ +int sensors_snprintf_chip_name(char *str, size_t size, + const sensors_chip_name *chip); + +/* This function returns the adapter name of a bus, + as used within the sensors_chip_name structure. If it could not be found, + it returns NULL */ +const char *sensors_get_adapter_name(const sensors_bus_id *bus); + +typedef struct sensors_feature sensors_feature; + +/* Look up the label for a given feature. Note that chip should not + contain wildcard values! The returned string is newly allocated (free it + yourself). On failure, NULL is returned. + If no label exists for this feature, its name is returned itself. */ +char *sensors_get_label(const sensors_chip_name *name, + const sensors_feature *feature); + +/* Read the value of a subfeature of a certain chip. Note that chip should not + contain wildcard values! This function will return 0 on success, and <0 + on failure. */ +int sensors_get_value(const sensors_chip_name *name, int subfeat_nr, + double *value); + +/* Set the value of a subfeature of a certain chip. Note that chip should not + contain wildcard values! This function will return 0 on success, and <0 + on failure. */ +int sensors_set_value(const sensors_chip_name *name, int subfeat_nr, + double value); + +/* Execute all set statements for this particular chip. The chip may contain + wildcards! This function will return 0 on success, and <0 on failure. */ +int sensors_do_chip_sets(const sensors_chip_name *name); + +/* This function returns all detected chips that match a given chip name, + one by one. If no chip name is provided, all detected chips are returned. + To start at the beginning of the list, use 0 for nr; NULL is returned if + we are at the end of the list. Do not try to change these chip names, as + they point to internal structures! */ +const sensors_chip_name *sensors_get_detected_chips(const sensors_chip_name + *match, int *nr); + +/* These defines are used in the flags field of sensors_subfeature */ +#define SENSORS_MODE_R 1 +#define SENSORS_MODE_W 2 +#define SENSORS_COMPUTE_MAPPING 4 + +typedef enum sensors_feature_type { + SENSORS_FEATURE_IN = 0x00, + SENSORS_FEATURE_FAN = 0x01, + SENSORS_FEATURE_TEMP = 0x02, + SENSORS_FEATURE_POWER = 0x03, + SENSORS_FEATURE_ENERGY = 0x04, + SENSORS_FEATURE_CURR = 0x05, + SENSORS_FEATURE_HUMIDITY = 0x06, + SENSORS_FEATURE_MAX_MAIN, + SENSORS_FEATURE_VID = 0x10, + SENSORS_FEATURE_INTRUSION = 0x11, + SENSORS_FEATURE_MAX_OTHER, + SENSORS_FEATURE_BEEP_ENABLE = 0x18, + SENSORS_FEATURE_MAX, + SENSORS_FEATURE_UNKNOWN = INT_MAX, +} sensors_feature_type; + +/* All the sensor types (in, fan, temp, vid) are a multiple of 0x100 apart, + and sensor subfeatures which have no compute mapping have bit 7 set. */ +typedef enum sensors_subfeature_type { + SENSORS_SUBFEATURE_IN_INPUT = SENSORS_FEATURE_IN << 8, + SENSORS_SUBFEATURE_IN_MIN, + SENSORS_SUBFEATURE_IN_MAX, + SENSORS_SUBFEATURE_IN_LCRIT, + SENSORS_SUBFEATURE_IN_CRIT, + SENSORS_SUBFEATURE_IN_AVERAGE, + SENSORS_SUBFEATURE_IN_LOWEST, + SENSORS_SUBFEATURE_IN_HIGHEST, + SENSORS_SUBFEATURE_IN_ALARM = (SENSORS_FEATURE_IN << 8) | 0x80, + SENSORS_SUBFEATURE_IN_MIN_ALARM, + SENSORS_SUBFEATURE_IN_MAX_ALARM, + SENSORS_SUBFEATURE_IN_BEEP, + SENSORS_SUBFEATURE_IN_LCRIT_ALARM, + SENSORS_SUBFEATURE_IN_CRIT_ALARM, + + SENSORS_SUBFEATURE_FAN_INPUT = SENSORS_FEATURE_FAN << 8, + SENSORS_SUBFEATURE_FAN_MIN, + SENSORS_SUBFEATURE_FAN_MAX, + SENSORS_SUBFEATURE_FAN_ALARM = (SENSORS_FEATURE_FAN << 8) | 0x80, + SENSORS_SUBFEATURE_FAN_FAULT, + SENSORS_SUBFEATURE_FAN_DIV, + SENSORS_SUBFEATURE_FAN_BEEP, + SENSORS_SUBFEATURE_FAN_PULSES, + SENSORS_SUBFEATURE_FAN_MIN_ALARM, + SENSORS_SUBFEATURE_FAN_MAX_ALARM, + + SENSORS_SUBFEATURE_TEMP_INPUT = SENSORS_FEATURE_TEMP << 8, + SENSORS_SUBFEATURE_TEMP_MAX, + SENSORS_SUBFEATURE_TEMP_MAX_HYST, + SENSORS_SUBFEATURE_TEMP_MIN, + SENSORS_SUBFEATURE_TEMP_CRIT, + SENSORS_SUBFEATURE_TEMP_CRIT_HYST, + SENSORS_SUBFEATURE_TEMP_LCRIT, + SENSORS_SUBFEATURE_TEMP_EMERGENCY, + SENSORS_SUBFEATURE_TEMP_EMERGENCY_HYST, + SENSORS_SUBFEATURE_TEMP_LOWEST, + SENSORS_SUBFEATURE_TEMP_HIGHEST, + SENSORS_SUBFEATURE_TEMP_MIN_HYST, + SENSORS_SUBFEATURE_TEMP_LCRIT_HYST, + SENSORS_SUBFEATURE_TEMP_ALARM = (SENSORS_FEATURE_TEMP << 8) | 0x80, + SENSORS_SUBFEATURE_TEMP_MAX_ALARM, + SENSORS_SUBFEATURE_TEMP_MIN_ALARM, + SENSORS_SUBFEATURE_TEMP_CRIT_ALARM, + SENSORS_SUBFEATURE_TEMP_FAULT, + SENSORS_SUBFEATURE_TEMP_TYPE, + SENSORS_SUBFEATURE_TEMP_OFFSET, + SENSORS_SUBFEATURE_TEMP_BEEP, + SENSORS_SUBFEATURE_TEMP_EMERGENCY_ALARM, + SENSORS_SUBFEATURE_TEMP_LCRIT_ALARM, + + SENSORS_SUBFEATURE_POWER_AVERAGE = SENSORS_FEATURE_POWER << 8, + SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST, + SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST, + SENSORS_SUBFEATURE_POWER_INPUT, + SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST, + SENSORS_SUBFEATURE_POWER_INPUT_LOWEST, + SENSORS_SUBFEATURE_POWER_CAP, + SENSORS_SUBFEATURE_POWER_CAP_HYST, + SENSORS_SUBFEATURE_POWER_MAX, + SENSORS_SUBFEATURE_POWER_CRIT, + SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL = (SENSORS_FEATURE_POWER << 8) | 0x80, + SENSORS_SUBFEATURE_POWER_ALARM, + SENSORS_SUBFEATURE_POWER_CAP_ALARM, + SENSORS_SUBFEATURE_POWER_MAX_ALARM, + SENSORS_SUBFEATURE_POWER_CRIT_ALARM, + + SENSORS_SUBFEATURE_ENERGY_INPUT = SENSORS_FEATURE_ENERGY << 8, + + SENSORS_SUBFEATURE_CURR_INPUT = SENSORS_FEATURE_CURR << 8, + SENSORS_SUBFEATURE_CURR_MIN, + SENSORS_SUBFEATURE_CURR_MAX, + SENSORS_SUBFEATURE_CURR_LCRIT, + SENSORS_SUBFEATURE_CURR_CRIT, + SENSORS_SUBFEATURE_CURR_AVERAGE, + SENSORS_SUBFEATURE_CURR_LOWEST, + SENSORS_SUBFEATURE_CURR_HIGHEST, + SENSORS_SUBFEATURE_CURR_ALARM = (SENSORS_FEATURE_CURR << 8) | 0x80, + SENSORS_SUBFEATURE_CURR_MIN_ALARM, + SENSORS_SUBFEATURE_CURR_MAX_ALARM, + SENSORS_SUBFEATURE_CURR_BEEP, + SENSORS_SUBFEATURE_CURR_LCRIT_ALARM, + SENSORS_SUBFEATURE_CURR_CRIT_ALARM, + + SENSORS_SUBFEATURE_HUMIDITY_INPUT = SENSORS_FEATURE_HUMIDITY << 8, + + SENSORS_SUBFEATURE_VID = SENSORS_FEATURE_VID << 8, + + SENSORS_SUBFEATURE_INTRUSION_ALARM = SENSORS_FEATURE_INTRUSION << 8, + SENSORS_SUBFEATURE_INTRUSION_BEEP, + + SENSORS_SUBFEATURE_BEEP_ENABLE = SENSORS_FEATURE_BEEP_ENABLE << 8, + + SENSORS_SUBFEATURE_UNKNOWN = INT_MAX, +} sensors_subfeature_type; + +/* Data about a single chip feature (or category leader) */ +struct sensors_feature { + char *name; + int number; + sensors_feature_type type; + /* Members below are for libsensors internal use only */ + int first_subfeature; + int padding1; +}; + +/* Data about a single chip subfeature: + name is the string name used to refer to this subfeature (in config files) + number is the internal subfeature number, used in many functions to refer + to this subfeature + type is the subfeature type + mapping is the number of a main feature this subfeature belongs to + (for example subfeatures fan1_input, fan1_min, fan1_div and fan1_alarm + are mapped to main feature fan1) + flags is a bitfield, its value is a combination of SENSORS_MODE_R (readable), + SENSORS_MODE_W (writable) and SENSORS_COMPUTE_MAPPING (affected by the + computation rules of the main feature) */ +typedef struct sensors_subfeature { + char *name; + int number; + sensors_subfeature_type type; + int mapping; + unsigned int flags; +} sensors_subfeature; + +/* This returns all main features of a specific chip. nr is an internally + used variable. Set it to zero to start at the begin of the list. If no + more features are found NULL is returned. + Do not try to change the returned structure; you will corrupt internal + data structures. */ +const sensors_feature * +sensors_get_features(const sensors_chip_name *name, int *nr); + +/* This returns all subfeatures of a given main feature. nr is an internally + used variable. Set it to zero to start at the begin of the list. If no + more features are found NULL is returned. + Do not try to change the returned structure; you will corrupt internal + data structures. */ +const sensors_subfeature * +sensors_get_all_subfeatures(const sensors_chip_name *name, + const sensors_feature *feature, int *nr); + +/* This returns the subfeature of the given type for a given main feature, + if it exists, NULL otherwise. + Do not try to change the returned structure; you will corrupt internal + data structures. */ +const sensors_subfeature * +sensors_get_subfeature(const sensors_chip_name *name, + const sensors_feature *feature, + sensors_subfeature_type type); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* def LIB_SENSORS_SENSORS_H */ diff --git a/lib/sysfs.c b/lib/sysfs.c new file mode 100644 index 0000000..dcc6af5 --- /dev/null +++ b/lib/sysfs.c @@ -0,0 +1,917 @@ +/* + sysfs.c - Part of libsensors, a library for reading Linux sensor data + Copyright (c) 2005 Mark M. Hoffman + Copyright (C) 2007-2014 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* this define needed for strndup() */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "data.h" +#include "error.h" +#include "access.h" +#include "general.h" +#include "sysfs.h" + + +/****************************************************************************/ + +#define ATTR_MAX 128 +#define SYSFS_MAGIC 0x62656572 + +/* + * Read an attribute from sysfs + * Returns a pointer to a freshly allocated string; free it yourself. + * If the file doesn't exist or can't be read, NULL is returned. + */ +static char *sysfs_read_attr(const char *device, const char *attr) +{ + char path[NAME_MAX]; + char buf[ATTR_MAX], *p; + FILE *f; + + snprintf(path, NAME_MAX, "%s/%s", device, attr); + + if (!(f = fopen(path, "r"))) + return NULL; + p = fgets(buf, ATTR_MAX, f); + fclose(f); + if (!p) + return NULL; + + /* Last byte is a '\n'; chop that off */ + p = strndup(buf, strlen(buf) - 1); + if (!p) + sensors_fatal_error(__func__, "Out of memory"); + return p; +} + +/* + * Call an arbitrary function for each class device of the given class + * Returns 0 on success (all calls returned 0), a positive errno for + * local errors, or a negative error value if any call fails. + */ +static int sysfs_foreach_classdev(const char *class_name, + int (*func)(const char *, const char *)) +{ + char path[NAME_MAX]; + int path_off, ret; + DIR *dir; + struct dirent *ent; + + path_off = snprintf(path, NAME_MAX, "%s/class/%s", + sensors_sysfs_mount, class_name); + if (!(dir = opendir(path))) + return errno; + + ret = 0; + while (!ret && (ent = readdir(dir))) { + if (ent->d_name[0] == '.') /* skip hidden entries */ + continue; + + snprintf(path + path_off, NAME_MAX - path_off, "/%s", + ent->d_name); + ret = func(path, ent->d_name); + } + + closedir(dir); + return ret; +} + +/* + * Call an arbitrary function for each device of the given bus type + * Returns 0 on success (all calls returned 0), a positive errno for + * local errors, or a negative error value if any call fails. + */ +static int sysfs_foreach_busdev(const char *bus_type, + int (*func)(const char *, const char *)) +{ + char path[NAME_MAX]; + int path_off, ret; + DIR *dir; + struct dirent *ent; + + path_off = snprintf(path, NAME_MAX, "%s/bus/%s/devices", + sensors_sysfs_mount, bus_type); + if (!(dir = opendir(path))) + return errno; + + ret = 0; + while (!ret && (ent = readdir(dir))) { + if (ent->d_name[0] == '.') /* skip hidden entries */ + continue; + + snprintf(path + path_off, NAME_MAX - path_off, "/%s", + ent->d_name); + ret = func(path, ent->d_name); + } + + closedir(dir); + return ret; +} + +/****************************************************************************/ + +char sensors_sysfs_mount[NAME_MAX]; + +static +int get_type_scaling(sensors_subfeature_type type) +{ + /* Multipliers for subfeatures */ + switch (type & 0xFF80) { + case SENSORS_SUBFEATURE_IN_INPUT: + case SENSORS_SUBFEATURE_TEMP_INPUT: + case SENSORS_SUBFEATURE_CURR_INPUT: + case SENSORS_SUBFEATURE_HUMIDITY_INPUT: + return 1000; + case SENSORS_SUBFEATURE_FAN_INPUT: + return 1; + case SENSORS_SUBFEATURE_POWER_AVERAGE: + case SENSORS_SUBFEATURE_ENERGY_INPUT: + return 1000000; + } + + /* Multipliers for second class subfeatures + that need their own multiplier */ + switch (type) { + case SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL: + case SENSORS_SUBFEATURE_VID: + case SENSORS_SUBFEATURE_TEMP_OFFSET: + return 1000; + default: + return 1; + } +} + +static +char *get_feature_name(sensors_feature_type ftype, char *sfname) +{ + char *name, *underscore; + + switch (ftype) { + case SENSORS_FEATURE_IN: + case SENSORS_FEATURE_FAN: + case SENSORS_FEATURE_TEMP: + case SENSORS_FEATURE_POWER: + case SENSORS_FEATURE_ENERGY: + case SENSORS_FEATURE_CURR: + case SENSORS_FEATURE_HUMIDITY: + case SENSORS_FEATURE_INTRUSION: + underscore = strchr(sfname, '_'); + name = strndup(sfname, underscore - sfname); + if (!name) + sensors_fatal_error(__func__, "Out of memory"); + + break; + default: + name = strdup(sfname); + if (!name) + sensors_fatal_error(__func__, "Out of memory"); + } + + return name; +} + +/* Static mappings for use by sensors_subfeature_get_type() */ +struct subfeature_type_match +{ + const char *name; + sensors_subfeature_type type; +}; + +struct feature_type_match +{ + const char *name; + const struct subfeature_type_match *submatches; +}; + +static const struct subfeature_type_match temp_matches[] = { + { "input", SENSORS_SUBFEATURE_TEMP_INPUT }, + { "max", SENSORS_SUBFEATURE_TEMP_MAX }, + { "max_hyst", SENSORS_SUBFEATURE_TEMP_MAX_HYST }, + { "min", SENSORS_SUBFEATURE_TEMP_MIN }, + { "min_hyst", SENSORS_SUBFEATURE_TEMP_MIN_HYST }, + { "crit", SENSORS_SUBFEATURE_TEMP_CRIT }, + { "crit_hyst", SENSORS_SUBFEATURE_TEMP_CRIT_HYST }, + { "lcrit", SENSORS_SUBFEATURE_TEMP_LCRIT }, + { "lcrit_hyst", SENSORS_SUBFEATURE_TEMP_LCRIT_HYST }, + { "emergency", SENSORS_SUBFEATURE_TEMP_EMERGENCY }, + { "emergency_hyst", SENSORS_SUBFEATURE_TEMP_EMERGENCY_HYST }, + { "lowest", SENSORS_SUBFEATURE_TEMP_LOWEST }, + { "highest", SENSORS_SUBFEATURE_TEMP_HIGHEST }, + { "alarm", SENSORS_SUBFEATURE_TEMP_ALARM }, + { "min_alarm", SENSORS_SUBFEATURE_TEMP_MIN_ALARM }, + { "max_alarm", SENSORS_SUBFEATURE_TEMP_MAX_ALARM }, + { "crit_alarm", SENSORS_SUBFEATURE_TEMP_CRIT_ALARM }, + { "emergency_alarm", SENSORS_SUBFEATURE_TEMP_EMERGENCY_ALARM }, + { "lcrit_alarm", SENSORS_SUBFEATURE_TEMP_LCRIT_ALARM }, + { "fault", SENSORS_SUBFEATURE_TEMP_FAULT }, + { "type", SENSORS_SUBFEATURE_TEMP_TYPE }, + { "offset", SENSORS_SUBFEATURE_TEMP_OFFSET }, + { "beep", SENSORS_SUBFEATURE_TEMP_BEEP }, + { NULL, 0 } +}; + +static const struct subfeature_type_match in_matches[] = { + { "input", SENSORS_SUBFEATURE_IN_INPUT }, + { "min", SENSORS_SUBFEATURE_IN_MIN }, + { "max", SENSORS_SUBFEATURE_IN_MAX }, + { "lcrit", SENSORS_SUBFEATURE_IN_LCRIT }, + { "crit", SENSORS_SUBFEATURE_IN_CRIT }, + { "average", SENSORS_SUBFEATURE_IN_AVERAGE }, + { "lowest", SENSORS_SUBFEATURE_IN_LOWEST }, + { "highest", SENSORS_SUBFEATURE_IN_HIGHEST }, + { "alarm", SENSORS_SUBFEATURE_IN_ALARM }, + { "min_alarm", SENSORS_SUBFEATURE_IN_MIN_ALARM }, + { "max_alarm", SENSORS_SUBFEATURE_IN_MAX_ALARM }, + { "lcrit_alarm", SENSORS_SUBFEATURE_IN_LCRIT_ALARM }, + { "crit_alarm", SENSORS_SUBFEATURE_IN_CRIT_ALARM }, + { "beep", SENSORS_SUBFEATURE_IN_BEEP }, + { NULL, 0 } +}; + +static const struct subfeature_type_match fan_matches[] = { + { "input", SENSORS_SUBFEATURE_FAN_INPUT }, + { "min", SENSORS_SUBFEATURE_FAN_MIN }, + { "max", SENSORS_SUBFEATURE_FAN_MAX }, + { "div", SENSORS_SUBFEATURE_FAN_DIV }, + { "pulses", SENSORS_SUBFEATURE_FAN_PULSES }, + { "alarm", SENSORS_SUBFEATURE_FAN_ALARM }, + { "min_alarm", SENSORS_SUBFEATURE_FAN_MIN_ALARM }, + { "max_alarm", SENSORS_SUBFEATURE_FAN_MAX_ALARM }, + { "fault", SENSORS_SUBFEATURE_FAN_FAULT }, + { "beep", SENSORS_SUBFEATURE_FAN_BEEP }, + { NULL, 0 } +}; + +static const struct subfeature_type_match power_matches[] = { + { "average", SENSORS_SUBFEATURE_POWER_AVERAGE }, + { "average_highest", SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST }, + { "average_lowest", SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST }, + { "input", SENSORS_SUBFEATURE_POWER_INPUT }, + { "input_highest", SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST }, + { "input_lowest", SENSORS_SUBFEATURE_POWER_INPUT_LOWEST }, + { "cap", SENSORS_SUBFEATURE_POWER_CAP }, + { "cap_hyst", SENSORS_SUBFEATURE_POWER_CAP_HYST }, + { "cap_alarm", SENSORS_SUBFEATURE_POWER_CAP_ALARM }, + { "alarm", SENSORS_SUBFEATURE_POWER_ALARM }, + { "max", SENSORS_SUBFEATURE_POWER_MAX }, + { "max_alarm", SENSORS_SUBFEATURE_POWER_MAX_ALARM }, + { "crit", SENSORS_SUBFEATURE_POWER_CRIT }, + { "crit_alarm", SENSORS_SUBFEATURE_POWER_CRIT_ALARM }, + { "average_interval", SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL }, + { NULL, 0 } +}; + +static const struct subfeature_type_match energy_matches[] = { + { "input", SENSORS_SUBFEATURE_ENERGY_INPUT }, + { NULL, 0 } +}; + +static const struct subfeature_type_match curr_matches[] = { + { "input", SENSORS_SUBFEATURE_CURR_INPUT }, + { "min", SENSORS_SUBFEATURE_CURR_MIN }, + { "max", SENSORS_SUBFEATURE_CURR_MAX }, + { "lcrit", SENSORS_SUBFEATURE_CURR_LCRIT }, + { "crit", SENSORS_SUBFEATURE_CURR_CRIT }, + { "average", SENSORS_SUBFEATURE_CURR_AVERAGE }, + { "lowest", SENSORS_SUBFEATURE_CURR_LOWEST }, + { "highest", SENSORS_SUBFEATURE_CURR_HIGHEST }, + { "alarm", SENSORS_SUBFEATURE_CURR_ALARM }, + { "min_alarm", SENSORS_SUBFEATURE_CURR_MIN_ALARM }, + { "max_alarm", SENSORS_SUBFEATURE_CURR_MAX_ALARM }, + { "lcrit_alarm", SENSORS_SUBFEATURE_CURR_LCRIT_ALARM }, + { "crit_alarm", SENSORS_SUBFEATURE_CURR_CRIT_ALARM }, + { "beep", SENSORS_SUBFEATURE_CURR_BEEP }, + { NULL, 0 } +}; + +static const struct subfeature_type_match humidity_matches[] = { + { "input", SENSORS_SUBFEATURE_HUMIDITY_INPUT }, + { NULL, 0 } +}; + +static const struct subfeature_type_match cpu_matches[] = { + { "vid", SENSORS_SUBFEATURE_VID }, + { NULL, 0 } +}; + +static const struct subfeature_type_match intrusion_matches[] = { + { "alarm", SENSORS_SUBFEATURE_INTRUSION_ALARM }, + { "beep", SENSORS_SUBFEATURE_INTRUSION_BEEP }, + { NULL, 0 } +}; +static struct feature_type_match matches[] = { + { "temp%d%c", temp_matches }, + { "in%d%c", in_matches }, + { "fan%d%c", fan_matches }, + { "cpu%d%c", cpu_matches }, + { "power%d%c", power_matches }, + { "curr%d%c", curr_matches }, + { "energy%d%c", energy_matches }, + { "intrusion%d%c", intrusion_matches }, + { "humidity%d%c", humidity_matches }, +}; + +/* Return the subfeature type and channel number based on the subfeature + name */ +static +sensors_subfeature_type sensors_subfeature_get_type(const char *name, int *nr) +{ + char c; + int i, count; + const struct subfeature_type_match *submatches; + + /* Special case */ + if (!strcmp(name, "beep_enable")) { + *nr = 0; + return SENSORS_SUBFEATURE_BEEP_ENABLE; + } + + for (i = 0; i < ARRAY_SIZE(matches); i++) + if ((count = sscanf(name, matches[i].name, nr, &c))) + break; + + if (i == ARRAY_SIZE(matches) || count != 2 || c != '_') + return SENSORS_SUBFEATURE_UNKNOWN; /* no match */ + + submatches = matches[i].submatches; + name = strchr(name + 3, '_') + 1; + for (i = 0; submatches[i].name != NULL; i++) + if (!strcmp(name, submatches[i].name)) + return submatches[i].type; + + return SENSORS_SUBFEATURE_UNKNOWN; +} + +static int sensors_compute_max_sf(void) +{ + int i, j, max, offset; + const struct subfeature_type_match *submatches; + sensors_feature_type ftype; + + max = 0; + for (i = 0; i < ARRAY_SIZE(matches); i++) { + submatches = matches[i].submatches; + for (j = 0; submatches[j].name != NULL; j++) { + ftype = submatches[j].type >> 8; + + if (ftype < SENSORS_FEATURE_VID) { + offset = submatches[j].type & 0x7F; + if (offset >= max) + max = offset + 1; + } else { + offset = submatches[j].type & 0xFF; + if (offset >= max * 2) + max = ((offset + 1) + 1) / 2; + } + } + } + + return max; +} + +static int sensors_get_attr_mode(const char *device, const char *attr) +{ + char path[NAME_MAX]; + struct stat st; + int mode = 0; + + snprintf(path, NAME_MAX, "%s/%s", device, attr); + if (!stat(path, &st)) { + if (st.st_mode & S_IRUSR) + mode |= SENSORS_MODE_R; + if (st.st_mode & S_IWUSR) + mode |= SENSORS_MODE_W; + } + return mode; +} + +static int sensors_read_dynamic_chip(sensors_chip_features *chip, + const char *dev_path) +{ + int i, fnum = 0, sfnum = 0, prev_slot; + static int max_subfeatures, feature_size; + DIR *dir; + struct dirent *ent; + struct { + int count; + sensors_subfeature *sf; + } all_types[SENSORS_FEATURE_MAX]; + sensors_subfeature *dyn_subfeatures; + sensors_feature *dyn_features; + sensors_feature_type ftype; + sensors_subfeature_type sftype; + + if (!(dir = opendir(dev_path))) + return -errno; + + /* Dynamically figure out the max number of subfeatures */ + if (!max_subfeatures) { + max_subfeatures = sensors_compute_max_sf(); + feature_size = max_subfeatures * 2; + } + + /* We use a set of large sparse tables at first (one per main + feature type present) to store all found subfeatures, so that we + can store them sorted and then later create a dense sorted table. */ + memset(&all_types, 0, sizeof(all_types)); + + while ((ent = readdir(dir))) { + char *name; + int nr; + + /* Skip directories and symlinks */ + if (ent->d_type != DT_REG) + continue; + + name = ent->d_name; + + sftype = sensors_subfeature_get_type(name, &nr); + if (sftype == SENSORS_SUBFEATURE_UNKNOWN) + continue; + ftype = sftype >> 8; + + /* Adjust the channel number */ + switch (ftype) { + case SENSORS_FEATURE_FAN: + case SENSORS_FEATURE_TEMP: + case SENSORS_FEATURE_POWER: + case SENSORS_FEATURE_ENERGY: + case SENSORS_FEATURE_CURR: + case SENSORS_FEATURE_HUMIDITY: + nr--; + break; + default: + break; + } + + /* Skip invalid entries. The high limit is arbitrary, we just + don't want to allocate an insane amount of memory. */ + if (nr < 0 || nr >= 1024) { +#ifdef DEBUG + sensors_fatal_error(__func__, + "Invalid channel number!"); +#endif + continue; + } + + /* (Re-)allocate memory if needed */ + if (all_types[ftype].count < nr + 1) { + int old_count = all_types[ftype].count; + int step = ftype < SENSORS_FEATURE_VID ? 8 : + ftype < SENSORS_FEATURE_BEEP_ENABLE ? 2 : 1; + + while (all_types[ftype].count < nr + 1) + all_types[ftype].count += step; + + all_types[ftype].sf = realloc(all_types[ftype].sf, + all_types[ftype].count * + feature_size * + sizeof(sensors_subfeature)); + if (!all_types[ftype].sf) + sensors_fatal_error(__func__, "Out of memory"); + memset(all_types[ftype].sf + old_count * feature_size, + 0, (all_types[ftype].count - old_count) * + feature_size * sizeof(sensors_subfeature)); + } + + /* "calculate" a place to store the subfeature in our sparse, + sorted table */ + if (ftype < SENSORS_FEATURE_VID) + i = nr * feature_size + + ((sftype & 0x80) >> 7) * max_subfeatures + + (sftype & 0x7F); + else + i = nr * feature_size + (sftype & 0xFF); + + if (all_types[ftype].sf[i].name) { +#ifdef DEBUG + sensors_fatal_error(__func__, "Duplicate subfeature"); +#endif + continue; + } + + /* fill in the subfeature members */ + all_types[ftype].sf[i].type = sftype; + all_types[ftype].sf[i].name = strdup(name); + if (!all_types[ftype].sf[i].name) + sensors_fatal_error(__func__, "Out of memory"); + + /* Other and misc subfeatures are never scaled */ + if (sftype < SENSORS_SUBFEATURE_VID && !(sftype & 0x80)) + all_types[ftype].sf[i].flags |= SENSORS_COMPUTE_MAPPING; + all_types[ftype].sf[i].flags |= + sensors_get_attr_mode(dev_path, name); + + sfnum++; + } + closedir(dir); + + if (!sfnum) { /* No subfeature */ + chip->subfeature = NULL; + goto exit_free; + } + + /* How many main features? */ + for (ftype = 0; ftype < SENSORS_FEATURE_MAX; ftype++) { + prev_slot = -1; + for (i = 0; i < all_types[ftype].count * feature_size; i++) { + if (!all_types[ftype].sf[i].name) + continue; + + if (i / feature_size != prev_slot) { + fnum++; + prev_slot = i / feature_size; + } + } + } + + dyn_subfeatures = calloc(sfnum, sizeof(sensors_subfeature)); + dyn_features = calloc(fnum, sizeof(sensors_feature)); + if (!dyn_subfeatures || !dyn_features) + sensors_fatal_error(__func__, "Out of memory"); + + /* Copy from the sparse array to the compact array */ + sfnum = 0; + fnum = -1; + for (ftype = 0; ftype < SENSORS_FEATURE_MAX; ftype++) { + prev_slot = -1; + for (i = 0; i < all_types[ftype].count * feature_size; i++) { + if (!all_types[ftype].sf[i].name) + continue; + + /* New main feature? */ + if (i / feature_size != prev_slot) { + fnum++; + prev_slot = i / feature_size; + + dyn_features[fnum].name = + get_feature_name(ftype, + all_types[ftype].sf[i].name); + dyn_features[fnum].number = fnum; + dyn_features[fnum].first_subfeature = sfnum; + dyn_features[fnum].type = ftype; + } + + dyn_subfeatures[sfnum] = all_types[ftype].sf[i]; + dyn_subfeatures[sfnum].number = sfnum; + /* Back to the feature */ + dyn_subfeatures[sfnum].mapping = fnum; + + sfnum++; + } + } + + chip->subfeature = dyn_subfeatures; + chip->subfeature_count = sfnum; + chip->feature = dyn_features; + chip->feature_count = ++fnum; + +exit_free: + for (ftype = 0; ftype < SENSORS_FEATURE_MAX; ftype++) + free(all_types[ftype].sf); + return 0; +} + +/* returns !0 if sysfs filesystem was found, 0 otherwise */ +int sensors_init_sysfs(void) +{ + struct statfs statfsbuf; + + snprintf(sensors_sysfs_mount, NAME_MAX, "%s", "/sys"); + if (statfs(sensors_sysfs_mount, &statfsbuf) < 0 + || statfsbuf.f_type != SYSFS_MAGIC) + return 0; + + return 1; +} + +/* returns: number of devices added (0 or 1) if successful, <0 otherwise */ +static int sensors_read_one_sysfs_chip(const char *dev_path, + const char *dev_name, + const char *hwmon_path) +{ + int domain, bus, slot, fn, vendor, product, id; + int err = -SENSORS_ERR_KERNEL; + char *bus_attr; + char bus_path[NAME_MAX]; + char linkpath[NAME_MAX]; + char subsys_path[NAME_MAX], *subsys; + int sub_len; + sensors_chip_features entry; + + /* ignore any device without name attribute */ + if (!(entry.chip.prefix = sysfs_read_attr(hwmon_path, "name"))) + return 0; + + entry.chip.path = strdup(hwmon_path); + if (!entry.chip.path) + sensors_fatal_error(__func__, "Out of memory"); + + if (dev_path == NULL) { + /* Virtual device */ + entry.chip.bus.type = SENSORS_BUS_TYPE_VIRTUAL; + entry.chip.bus.nr = 0; + /* For now we assume that virtual devices are unique */ + entry.chip.addr = 0; + goto done; + } + + /* Find bus type */ + snprintf(linkpath, NAME_MAX, "%s/subsystem", dev_path); + sub_len = readlink(linkpath, subsys_path, NAME_MAX - 1); + if (sub_len < 0 && errno == ENOENT) { + /* Fallback to "bus" link for kernels <= 2.6.17 */ + snprintf(linkpath, NAME_MAX, "%s/bus", dev_path); + sub_len = readlink(linkpath, subsys_path, NAME_MAX - 1); + } + if (sub_len < 0) { + /* Older kernels (<= 2.6.11) have neither the subsystem + symlink nor the bus symlink */ + if (errno == ENOENT) + subsys = NULL; + else + goto exit_free; + } else { + subsys_path[sub_len] = '\0'; + subsys = strrchr(subsys_path, '/') + 1; + } + + if ((!subsys || !strcmp(subsys, "i2c")) && + sscanf(dev_name, "%hd-%x", &entry.chip.bus.nr, + &entry.chip.addr) == 2) { + /* find out if legacy ISA or not */ + if (entry.chip.bus.nr == 9191) { + entry.chip.bus.type = SENSORS_BUS_TYPE_ISA; + entry.chip.bus.nr = 0; + } else { + entry.chip.bus.type = SENSORS_BUS_TYPE_I2C; + snprintf(bus_path, sizeof(bus_path), + "%s/class/i2c-adapter/i2c-%d/device", + sensors_sysfs_mount, entry.chip.bus.nr); + + if ((bus_attr = sysfs_read_attr(bus_path, "name"))) { + if (!strncmp(bus_attr, "ISA ", 4)) { + entry.chip.bus.type = SENSORS_BUS_TYPE_ISA; + entry.chip.bus.nr = 0; + } + + free(bus_attr); + } + } + } else + if ((!subsys || !strcmp(subsys, "spi")) && + sscanf(dev_name, "spi%hd.%d", &entry.chip.bus.nr, + &entry.chip.addr) == 2) { + /* SPI */ + entry.chip.bus.type = SENSORS_BUS_TYPE_SPI; + } else + if ((!subsys || !strcmp(subsys, "pci")) && + sscanf(dev_name, "%x:%x:%x.%x", &domain, &bus, &slot, &fn) == 4) { + /* PCI */ + entry.chip.addr = (domain << 16) + (bus << 8) + (slot << 3) + fn; + entry.chip.bus.type = SENSORS_BUS_TYPE_PCI; + entry.chip.bus.nr = 0; + } else + if ((!subsys || !strcmp(subsys, "platform") || + !strcmp(subsys, "of_platform"))) { + /* must be new ISA (platform driver) */ + if (sscanf(dev_name, "%*[a-z0-9_].%d", &entry.chip.addr) != 1) + entry.chip.addr = 0; + entry.chip.bus.type = SENSORS_BUS_TYPE_ISA; + entry.chip.bus.nr = 0; + } else if (subsys && !strcmp(subsys, "acpi")) { + entry.chip.bus.type = SENSORS_BUS_TYPE_ACPI; + /* For now we assume that acpi devices are unique */ + entry.chip.bus.nr = 0; + entry.chip.addr = 0; + } else + if (subsys && !strcmp(subsys, "hid") && + sscanf(dev_name, "%x:%x:%x.%x", &bus, &vendor, &product, &id) == 4) { + entry.chip.bus.type = SENSORS_BUS_TYPE_HID; + /* As of kernel 2.6.32, the hid device names don't look good */ + entry.chip.bus.nr = bus; + entry.chip.addr = id; + } else + if (subsys && !strcmp(subsys, "mdio_bus")) { + if (sscanf(dev_name, "%*[^:]:%d", &entry.chip.addr) != 1) + entry.chip.addr = 0; + entry.chip.bus.type = SENSORS_BUS_TYPE_MDIO; + entry.chip.bus.nr = 0; + } else { + /* Ignore unknown device */ + err = 0; + goto exit_free; + } + +done: + if (sensors_read_dynamic_chip(&entry, hwmon_path) < 0) + goto exit_free; + if (!entry.subfeature) { /* No subfeature, discard chip */ + err = 0; + goto exit_free; + } + sensors_add_proc_chips(&entry); + + return 1; + +exit_free: + free(entry.chip.prefix); + free(entry.chip.path); + return err; +} + +static int sensors_add_hwmon_device_compat(const char *path, + const char *dev_name) +{ + int err; + + err = sensors_read_one_sysfs_chip(path, dev_name, path); + if (err < 0) + return err; + return 0; +} + +/* returns 0 if successful, !0 otherwise */ +static int sensors_read_sysfs_chips_compat(void) +{ + int ret; + + ret = sysfs_foreach_busdev("i2c", sensors_add_hwmon_device_compat); + if (ret && ret != ENOENT) + return -SENSORS_ERR_KERNEL; + + return 0; +} + +static int sensors_add_hwmon_device(const char *path, const char *classdev) +{ + char linkpath[NAME_MAX]; + char device[NAME_MAX], *device_p; + int dev_len, err; + (void)classdev; /* hide warning */ + + snprintf(linkpath, NAME_MAX, "%s/device", path); + dev_len = readlink(linkpath, device, NAME_MAX - 1); + if (dev_len < 0) { + /* No device link? Treat as virtual */ + err = sensors_read_one_sysfs_chip(NULL, NULL, path); + } else { + device[dev_len] = '\0'; + device_p = strrchr(device, '/') + 1; + + /* The attributes we want might be those of the hwmon class + device, or those of the device itself. */ + err = sensors_read_one_sysfs_chip(linkpath, device_p, path); + if (err == 0) + err = sensors_read_one_sysfs_chip(linkpath, device_p, + linkpath); + } + if (err < 0) + return err; + return 0; +} + +/* returns 0 if successful, !0 otherwise */ +int sensors_read_sysfs_chips(void) +{ + int ret; + + ret = sysfs_foreach_classdev("hwmon", sensors_add_hwmon_device); + if (ret == ENOENT) { + /* compatibility function for kernel 2.6.n where n <= 13 */ + return sensors_read_sysfs_chips_compat(); + } + + if (ret > 0) + ret = -SENSORS_ERR_KERNEL; + return ret; +} + +/* returns 0 if successful, !0 otherwise */ +static int sensors_add_i2c_bus(const char *path, const char *classdev) +{ + sensors_bus entry; + + if (sscanf(classdev, "i2c-%hd", &entry.bus.nr) != 1 || + entry.bus.nr == 9191) /* legacy ISA */ + return 0; + entry.bus.type = SENSORS_BUS_TYPE_I2C; + + /* Get the adapter name from the classdev "name" attribute + * (Linux 2.6.20 and later). If it fails, fall back to + * the device "name" attribute (for older kernels). */ + entry.adapter = sysfs_read_attr(path, "name"); + if (!entry.adapter) + entry.adapter = sysfs_read_attr(path, "device/name"); + if (entry.adapter) + sensors_add_proc_bus(&entry); + + return 0; +} + +/* returns 0 if successful, !0 otherwise */ +int sensors_read_sysfs_bus(void) +{ + int ret; + + ret = sysfs_foreach_classdev("i2c-adapter", sensors_add_i2c_bus); + if (ret == ENOENT) + ret = sysfs_foreach_busdev("i2c", sensors_add_i2c_bus); + if (ret && ret != ENOENT) + return -SENSORS_ERR_KERNEL; + + return 0; +} + +int sensors_read_sysfs_attr(const sensors_chip_name *name, + const sensors_subfeature *subfeature, + double *value) +{ + char n[NAME_MAX]; + FILE *f; + + snprintf(n, NAME_MAX, "%s/%s", name->path, subfeature->name); + if ((f = fopen(n, "r"))) { + int res, err = 0; + + errno = 0; + res = fscanf(f, "%lf", value); + if (res == EOF && errno == EIO) + err = -SENSORS_ERR_IO; + else if (res != 1) + err = -SENSORS_ERR_ACCESS_R; + res = fclose(f); + if (err) + return err; + + if (res == EOF) { + if (errno == EIO) + return -SENSORS_ERR_IO; + else + return -SENSORS_ERR_ACCESS_R; + } + *value /= get_type_scaling(subfeature->type); + } else + return -SENSORS_ERR_KERNEL; + + return 0; +} + +int sensors_write_sysfs_attr(const sensors_chip_name *name, + const sensors_subfeature *subfeature, + double value) +{ + char n[NAME_MAX]; + FILE *f; + + snprintf(n, NAME_MAX, "%s/%s", name->path, subfeature->name); + if ((f = fopen(n, "w"))) { + int res, err = 0; + + value *= get_type_scaling(subfeature->type); + res = fprintf(f, "%d", (int) value); + if (res == -EIO) + err = -SENSORS_ERR_IO; + else if (res < 0) + err = -SENSORS_ERR_ACCESS_W; + res = fclose(f); + if (err) + return err; + + if (res == EOF) { + if (errno == EIO) + return -SENSORS_ERR_IO; + else + return -SENSORS_ERR_ACCESS_W; + } + } else + return -SENSORS_ERR_KERNEL; + + return 0; +} diff --git a/lib/sysfs.h b/lib/sysfs.h new file mode 100644 index 0000000..3f4d83a --- /dev/null +++ b/lib/sysfs.h @@ -0,0 +1,43 @@ +/* + sysfs.h - part of libsensors, a library for reading Linux sensor data + Copyright (C) Mark M. Hoffman + Copyright (C) 2007-2010 Jean Delvare + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_SENSORS_SYSFS_H +#define LIB_SENSORS_SYSFS_H + +extern char sensors_sysfs_mount[]; + +int sensors_init_sysfs(void); + +int sensors_read_sysfs_chips(void); + +int sensors_read_sysfs_bus(void); + +/* Read a value out of a sysfs attribute file */ +int sensors_read_sysfs_attr(const sensors_chip_name *name, + const sensors_subfeature *subfeature, + double *value); + +/* Write a value to a sysfs attribute file */ +int sensors_write_sysfs_attr(const sensors_chip_name *name, + const sensors_subfeature *subfeature, + double value); + +#endif /* def LIB_SENSORS_SYSFS_H */ diff --git a/lib/test/Module.mk b/lib/test/Module.mk new file mode 100644 index 0000000..2a9f6ed --- /dev/null +++ b/lib/test/Module.mk @@ -0,0 +1,24 @@ +LIB_DIR := lib +LIB_TEST_DIR := lib/test + +LIB_TEST_TARGETS := $(LIB_TEST_DIR)/test-scanner +LIB_TEST_SOURCES := $(LIB_TEST_DIR)/test-scanner.c + +LIB_TEST_SCANNER_OBJS := \ + $(LIB_TEST_DIR)/test-scanner.ro \ + $(LIB_DIR)/conf-lex.ao \ + $(LIB_DIR)/error.ao \ + $(LIB_DIR)/general.ao + +$(LIB_TEST_DIR)/test-scanner: $(LIB_TEST_SCANNER_OBJS) + $(CC) $(EXLDFLAGS) -o $@ $(LIB_TEST_SCANNER_OBJS) -Llib + +all-lib-test: $(LIB_TEST_TARGETS) +user :: all-lib-test + +$(LIB_TEST_DIR)/test-scanner.ro: $(LIB_DIR)/data.h $(LIB_DIR)/conf.h $(LIB_DIR)/conf-parse.h $(LIB_DIR)/scanner.h + +clean-lib-test: + $(RM) $(LIB_TEST_DIR)/*.rd $(LIB_TEST_DIR)/*.ro + $(RM) $(LIB_TEST_TARGETS) +clean :: clean-lib-test diff --git a/lib/test/comment-without-eol.conf b/lib/test/comment-without-eol.conf new file mode 100644 index 0000000..63a8ebe --- /dev/null +++ b/lib/test/comment-without-eol.conf @@ -0,0 +1 @@ +# this is a comment without a trailing newline \ No newline at end of file diff --git a/lib/test/comment-without-eol.conf.stdout b/lib/test/comment-without-eol.conf.stdout new file mode 100644 index 0000000..bbde636 --- /dev/null +++ b/lib/test/comment-without-eol.conf.stdout @@ -0,0 +1 @@ +1: EOF diff --git a/lib/test/comment.conf b/lib/test/comment.conf new file mode 100644 index 0000000..74c84e9 --- /dev/null +++ b/lib/test/comment.conf @@ -0,0 +1 @@ +# this is a comment diff --git a/lib/test/comment.conf.stdout b/lib/test/comment.conf.stdout new file mode 100644 index 0000000..74d0621 --- /dev/null +++ b/lib/test/comment.conf.stdout @@ -0,0 +1 @@ +2: EOF diff --git a/lib/test/empty.conf b/lib/test/empty.conf new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/test/empty.conf diff --git a/lib/test/empty.conf.stdout b/lib/test/empty.conf.stdout new file mode 100644 index 0000000..bbde636 --- /dev/null +++ b/lib/test/empty.conf.stdout @@ -0,0 +1 @@ +1: EOF diff --git a/lib/test/keywords.conf b/lib/test/keywords.conf new file mode 100644 index 0000000..94eb682 --- /dev/null +++ b/lib/test/keywords.conf @@ -0,0 +1,42 @@ +# chip keyword on a line by itself +chip + +# preceded by whitespace + chip + +# with trailing whitespace +chip + +# ditto for the rest of the keywords +label + + label + +label + +set + + set + +set + +compute + + compute + +compute + +bus + + bus + +bus + +ignore + + ignore + +ignore + +# keyword followed by EOL/EOF +chip diff --git a/lib/test/keywords.conf.stdout b/lib/test/keywords.conf.stdout new file mode 100644 index 0000000..f4b34bd --- /dev/null +++ b/lib/test/keywords.conf.stdout @@ -0,0 +1,39 @@ +2: CHIP +3: EOL +5: CHIP +6: EOL +8: CHIP +9: EOL +11: LABEL +12: EOL +13: LABEL +14: EOL +15: LABEL +16: EOL +17: SET +18: EOL +19: SET +20: EOL +21: SET +22: EOL +23: COMPUTE +24: EOL +25: COMPUTE +26: EOL +27: COMPUTE +28: EOL +29: BUS +30: EOL +31: BUS +32: EOL +33: BUS +34: EOL +35: IGNORE +36: EOL +37: IGNORE +38: EOL +39: IGNORE +40: EOL +42: CHIP +43: EOL +43: EOF diff --git a/lib/test/names-errors.conf b/lib/test/names-errors.conf new file mode 100644 index 0000000..b44ae59 --- /dev/null +++ b/lib/test/names-errors.conf @@ -0,0 +1,5 @@ +# keyword with bogus names +label ?foo +label bar% +label baz$foo +label ! diff --git a/lib/test/names-errors.conf.stdout b/lib/test/names-errors.conf.stdout new file mode 100644 index 0000000..d02e950 --- /dev/null +++ b/lib/test/names-errors.conf.stdout @@ -0,0 +1,15 @@ +2: LABEL +2: ERROR +3: EOL +3: LABEL +3: NAME: bar +3: ERROR +4: EOL +4: LABEL +4: NAME: baz +4: ERROR +5: EOL +5: LABEL +5: ERROR +6: EOL +6: EOF diff --git a/lib/test/names-quoted-errors.conf b/lib/test/names-quoted-errors.conf new file mode 100644 index 0000000..d08fa7d --- /dev/null +++ b/lib/test/names-quoted-errors.conf @@ -0,0 +1,13 @@ +chip "blah-*" + +# keyword with two quoted names, no intermediate whitespace +label "in0""foo" + +# missing closing quote before EOL +label "in1" "bar + +# (correct label statement, just for separation) +label "in2" "baz" + +# missing closing quote before immediate EOF +label "in3" "baz \ No newline at end of file diff --git a/lib/test/names-quoted-errors.conf.stdout b/lib/test/names-quoted-errors.conf.stdout new file mode 100644 index 0000000..f06f725 --- /dev/null +++ b/lib/test/names-quoted-errors.conf.stdout @@ -0,0 +1,19 @@ +1: CHIP +1: NAME: blah-* +2: EOL +4: LABEL +4: ERROR +5: EOL +7: LABEL +7: NAME: in1 +7: ERROR +8: EOL +10: LABEL +10: NAME: in2 +10: NAME: baz +11: EOL +13: LABEL +13: NAME: in3 +13: ERROR +13: EOL +13: EOF diff --git a/lib/test/names-quoted.conf b/lib/test/names-quoted.conf new file mode 100644 index 0000000..4caf00f --- /dev/null +++ b/lib/test/names-quoted.conf @@ -0,0 +1,28 @@ +chip "blah-*" + +# keyword with some quoted names +label "foo" "bar" + +# keyword with escaped newline, names, and whitespace +label \ + "foo" "bar" + +# quoted names with full range of alpha-numeric and underscores +label "abcdefg" "hijklmnop" +label "qrs" "tuv" +label "wx" "yz" +label "a0123456789" "982lksdf" +label "_abcd" "1234_" +label "_" "foo_bar_baz" +label "liajesiajef82197fjadf" "blah" + +# quoted names with escaped characters, like C +# bell, backspace, formfeed, newline, carriage return, h-tab, v-tab, \, ?, ', " +label escapes "\a\b\f\n\r\t\v\\\?\'\"" + +# quoted names with escaped chars that have no special significance +# i.e. the second string below should collapse to "hello" +label more "\h\e\l\l\o" + +# keyword with quoted names, immediate EOF +label "blue" "green" \ No newline at end of file diff --git a/lib/test/names-quoted.conf.stdout b/lib/test/names-quoted.conf.stdout new file mode 100644 index 0000000..5a66428 --- /dev/null +++ b/lib/test/names-quoted.conf.stdout @@ -0,0 +1,53 @@ +1: CHIP +1: NAME: blah-* +2: EOL +4: LABEL +4: NAME: foo +4: NAME: bar +5: EOL +7: LABEL +8: NAME: foo +8: NAME: bar +9: EOL +11: LABEL +11: NAME: abcdefg +11: NAME: hijklmnop +12: EOL +12: LABEL +12: NAME: qrs +12: NAME: tuv +13: EOL +13: LABEL +13: NAME: wx +13: NAME: yz +14: EOL +14: LABEL +14: NAME: a0123456789 +14: NAME: 982lksdf +15: EOL +15: LABEL +15: NAME: _abcd +15: NAME: 1234_ +16: EOL +16: LABEL +16: NAME: _ +16: NAME: foo_bar_baz +17: EOL +17: LABEL +17: NAME: liajesiajef82197fjadf +17: NAME: blah +18: EOL +21: LABEL +21: NAME: escapes +21: NAME:  + \?'" +22: EOL +25: LABEL +25: NAME: more +25: NAME: hello +26: EOL +28: LABEL +28: NAME: blue +28: NAME: green +28: EOL +28: EOF diff --git a/lib/test/names.conf b/lib/test/names.conf new file mode 100644 index 0000000..c052f2c --- /dev/null +++ b/lib/test/names.conf @@ -0,0 +1,25 @@ +# keyword with some unquoted names +label foo bar + +# keyword with escaped newline, names, and whitespace +label \ + foo bar + +# names with full range of alpha-numeric and underscores +label \ + abcdefg \ + hijklmnop \ + qrs \ + tuv \ + wx \ + yz \ + a0123456789 \ + 982lksdf \ + _abcd \ + 1234_ \ + _ \ + foo_bar_baz \ + liajesiajef82197fjadf + +# keyword with names, immediate EOF +label foo bar \ No newline at end of file diff --git a/lib/test/names.conf.stdout b/lib/test/names.conf.stdout new file mode 100644 index 0000000..1c3fa03 --- /dev/null +++ b/lib/test/names.conf.stdout @@ -0,0 +1,28 @@ +2: LABEL +2: NAME: foo +2: NAME: bar +3: EOL +5: LABEL +6: NAME: foo +6: NAME: bar +7: EOL +9: LABEL +10: NAME: abcdefg +11: NAME: hijklmnop +12: NAME: qrs +13: NAME: tuv +14: NAME: wx +15: NAME: yz +16: NAME: a0123456789 +17: NAME: 982lksdf +18: NAME: _abcd +19: NAME: 1234_ +20: NAME: _ +21: NAME: foo_bar_baz +22: NAME: liajesiajef82197fjadf +23: EOL +25: LABEL +25: NAME: foo +25: NAME: bar +25: EOL +25: EOF diff --git a/lib/test/non-keywords.conf b/lib/test/non-keywords.conf new file mode 100644 index 0000000..d7fc754 --- /dev/null +++ b/lib/test/non-keywords.conf @@ -0,0 +1,8 @@ +# these are not keywords +ignored + +labs + +extra +stuff + diff --git a/lib/test/non-keywords.conf.stdout b/lib/test/non-keywords.conf.stdout new file mode 100644 index 0000000..1798c37 --- /dev/null +++ b/lib/test/non-keywords.conf.stdout @@ -0,0 +1,9 @@ +2: ERROR +3: EOL +4: ERROR +5: EOL +6: ERROR +7: EOL +7: ERROR +8: EOL +9: EOF diff --git a/lib/test/test-scanner.c b/lib/test/test-scanner.c new file mode 100644 index 0000000..4b4c758 --- /dev/null +++ b/lib/test/test-scanner.c @@ -0,0 +1,106 @@ +/* + test-scanner.c - Regression test driver for the libsensors config file scanner. + Copyright (C) 2006 Mark M. Hoffman + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#include +#include + +#include "../data.h" +#include "../conf.h" +#include "../conf-parse.h" +#include "../scanner.h" + +YYSTYPE sensors_yylval; + +int main(void) +{ + int result; + + /* init the scanner */ + if ((result = sensors_scanner_init(stdin, NULL))) + return result; + + do { + result = sensors_yylex(); + + printf("%d: ", sensors_yylineno); + + switch (result) { + + case 0: + printf("EOF\n"); + break; + + case NEG: + printf("NEG\n"); + break; + + case EOL: + printf("EOL\n"); + break; + + case BUS: + printf("BUS\n"); + break; + + case LABEL: + printf("LABEL\n"); + break; + + case SET: + printf("SET\n"); + break; + + case CHIP: + printf("CHIP\n"); + break; + + case COMPUTE: + printf("COMPUTE\n"); + break; + + case IGNORE: + printf("IGNORE\n"); + break; + + case FLOAT: + printf("FLOAT: %f\n", sensors_yylval.value); + break; + + case NAME: + printf("NAME: %s\n", sensors_yylval.name); + free(sensors_yylval.name); + break; + + case ERROR: + printf("ERROR\n"); + break; + + default: + printf("%c\n", (char)result); + break; + } + + } while (result); + + /* clean up the scanner */ + sensors_scanner_exit(); + + return 0; +} + diff --git a/lib/test/test-scanner.pl b/lib/test/test-scanner.pl new file mode 100755 index 0000000..6d163a8 --- /dev/null +++ b/lib/test/test-scanner.pl @@ -0,0 +1,101 @@ +#!/usr/bin/perl -w + +# test-scanner.pl - test script for the libsensors config-file scanner +# Copyright (C) 2006 Mark M. Hoffman +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# + +require 5.004; + +use strict; +use Test::More; +use Test::Cmd; + +my ($scenario, $test); +my @scenarios = ( + { base => 'empty', status => 0, + desc => 'empty file' }, + { base => 'comment', status => 0, + desc => 'one comment line' }, + { base => 'comment-without-eol', status => 0, + desc => 'one comment line, without a trailing newline' }, + { base => 'keywords', status => 0, + desc => 'keywords with various whitespace variations' }, + { base => 'non-keywords', status => 0, + desc => 'various invalid keyword scenarios' }, + { base => 'names', status => 0, + desc => 'normal, unquoted names' }, + { base => 'names-errors', status => 0, + desc => 'invalid, unquoted names' }, + { base => 'names-quoted', status => 0, + desc => 'normal, quoted names' }, + { base => 'names-quoted-errors', status => 0, + desc => 'invalid, quoted names' }, +); + +plan tests => ($#scenarios + 1) * 3; + +chomp(my $valgrind = `which valgrind 2>/dev/null`); + +if ($valgrind) { + $test = Test::Cmd->new(prog => "$valgrind --tool=memcheck --show-reachable=yes --leak-check=full --quiet ./test-scanner", workdir => ''); +} else { + diag("Couldn't find valgrind(1), running tests without it..."); + $test = Test::Cmd->new(prog => "test-scanner", workdir => ''); +} + +foreach $scenario (@scenarios) { + my ($filename, @stdin, @stdout, @expout, @stderr, @experr, @diff); + + $filename = $scenario->{"base"} . ".conf"; + open INPUT, "< $filename" or die "Cannot open $filename: $!"; + @stdin = ; + close INPUT or die "Cannot close $filename: $!"; + + $filename = $scenario->{"base"} . ".conf.stdout"; + open OUTPUT, "< $filename" or die "Cannot open $filename: $!"; + @expout = ; + close OUTPUT or die "Cannot close $filename: $!"; + + # if stderr file is not present, assume none is expected + $filename = $scenario->{"base"} . ".conf.stderr"; + if (open ERROR, "< $filename") { + @experr = ; + close ERROR or die "Cannot close $filename: $!"; + } else { + @experr = (); + } + + $test->string($scenario->{"desc"}); + $test->run(stdin => \@stdin); + + # test return status + ok($scenario->{"status"} == $?, "status: " . $scenario->{"desc"}); + + # force the captured outputs into an array - for some reason, the + # 'standard invocation' of diff_exact() chokes without this + @stdout = $test->stdout; + @stderr = $test->stderr; + + # test stdout + ok($test->diff_exact(\@stdout, \@expout, \@diff), + "stdout: " . $scenario->{"desc"}) or print @diff; + + # test stderr + ok($test->diff_exact(\@stderr, \@experr, \@diff), + "stderr: " . $scenario->{"desc"}) or print @diff; +} + diff --git a/prog/daemon/healthd.sh b/prog/daemon/healthd.sh new file mode 100755 index 0000000..c9cb86d --- /dev/null +++ b/prog/daemon/healthd.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# +# healthd -- This is a simple daemon which can be used to alert you in the +# event of a hardware health monitoring alarm by sending an +# email to the value of ADMIN_EMAIL (defined below). +# +# To Use -- Simply start the daemon from a shell (may be backgrounded) +# +# Other details -- Checks status every 15 seconds. Sends warning emails every +# ten minutes during alarm until the alarm is cleared. +# It won't start up if there is a pending alarm on startup. +# Very low loading on the machine (sleeps almost all the time). +# This is just an example. It works, but hopefully we can +# get something better written. :') +# +# Requirements -- mail, sensors, bash, sleep +# +# Written & Copyrighten by Philip Edelbrock, 1999. +# +# Version: 1.1 +# + +ADMIN_EMAIL="root@localhost" + +# Try loading the built-in sleep implementation to avoid spawning a +# new process every 15 seconds +enable -f sleep.so sleep >/dev/null 2>&1 + +sensors_state=$(sensors) +if [[ "$sensors_state" =~ 'ALARM' ]] +then + echo "Pending Alarms on start up! Exiting!" + exit +fi + +while true +do + sleep 15 + sensors_state=$(sensors) + if [[ "$sensors_state" =~ 'ALARM' ]] + then + echo "$sensors_state" | mail -s '**** Hardware Health Warning ****' $ADMIN_EMAIL + sleep 600 + fi +done diff --git a/prog/detect/Module.mk b/prog/detect/Module.mk new file mode 100644 index 0000000..d2526d8 --- /dev/null +++ b/prog/detect/Module.mk @@ -0,0 +1,49 @@ +# Module.mk - Makefile for a Linux module for reading sensor data. +# Copyright (c) 1998, 1999 Frodo Looijaard +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. + +# Note that MODULE_DIR (the directory in which this file resides) is a +# 'simply expanded variable'. That means that its value is substituted +# verbatim in the rules, until it is redefined. +MODULE_DIR := prog/detect +PROGDETECTDIR := $(MODULE_DIR) + +PROGDETECTMAN8DIR := $(MANDIR)/man8 +PROGDETECTMAN8FILES := $(MODULE_DIR)/sensors-detect.8 + +# Regrettably, even 'simply expanded variables' will not put their currently +# defined value verbatim into the command-list of rules... +PROGDETECTSBININSTALL := $(MODULE_DIR)/sensors-detect + +REMOVEDETECTBIN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(SBINDIR)/%,$(PROGDETECTSBININSTALL)) +REMOVEDETECTMAN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(PROGDETECTMAN8DIR)/%,$(PROGDETECTMAN8FILES)) + +all-prog-detect: +user :: all-prog-detect + +install-prog-detect: all-prog-detect + $(MKDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(PROGDETECTMAN8DIR) + $(INSTALL) -m 755 $(PROGDETECTSBININSTALL) $(DESTDIR)$(SBINDIR) + $(INSTALL) -m 644 $(PROGDETECTMAN8FILES) $(DESTDIR)$(PROGDETECTMAN8DIR) +user_install :: install-prog-detect + +user_uninstall:: + $(RM) $(REMOVEDETECTBIN) + $(RM) $(REMOVEDETECTMAN) + +clean-prog-detect: +clean :: clean-prog-detect diff --git a/prog/detect/sensors-detect b/prog/detect/sensors-detect new file mode 100755 index 0000000..b1b4b20 --- /dev/null +++ b/prog/detect/sensors-detect @@ -0,0 +1,7646 @@ +#!/usr/bin/perl -w +# +# sensors-detect - Detect hardware monitoring chips +# Copyright (C) 1998 - 2002 Frodo Looijaard +# Copyright (C) 2004 - 2015 Jean Delvare +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# + +require 5.004; + +use strict; +use Fcntl qw(:DEFAULT :seek); +use File::Basename; + +# We will call modprobe, which typically lives in either /sbin, +# /usr/sbin or /usr/local/bin. So make sure these are all in the PATH. +foreach ('/usr/sbin', '/usr/local/sbin', '/sbin') { + $ENV{PATH} = "$_:".$ENV{PATH} + unless $ENV{PATH} =~ m/(^|:)$_\/?(:|$)/; +} + +######################### +# CONSTANT DECLARATIONS # +######################### + +use constant NO_CACHE => 1; +use vars qw(@pci_adapters @chip_ids @ipmi_ifs @non_hwmon_chip_ids + $i2c_addresses_to_scan $revision @i2c_byte_cache %opt); + +$revision = '$Revision$ ($Date$)'; +$revision =~ s/\$\w+: (.*?) \$/$1/g; +$revision =~ s/ \([^()]*\)//; + +# This is the list of SMBus or I2C adapters we recognize by their PCI +# signature. This is an easy and fast way to determine which SMBus or I2C +# adapters should be present. +# Each entry must have a vendid (Vendor ID), devid (Device ID) and +# procid (Device name) and driver (Device driver). +@pci_adapters = ( + { + vendid => 0x8086, + devid => 0x7113, + procid => "Intel 82371AB PIIX4 ACPI", + driver => "i2c-piix4", + }, { + vendid => 0x8086, + devid => 0x7603, + procid => "Intel 82372FB PIIX5 ACPI", + driver => "to-be-written", + }, { + vendid => 0x8086, + devid => 0x719b, + procid => "Intel 82443MX Mobile", + driver => "i2c-piix4", + }, { + vendid => 0x8086, + devid => 0x2413, + procid => "Intel 82801AA ICH", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x2423, + procid => "Intel 82801AB ICH0", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x2443, + procid => "Intel 82801BA ICH2", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x2483, + procid => "Intel 82801CA/CAM ICH3", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x24C3, + procid => "Intel 82801DB ICH4", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x24D3, + procid => "Intel 82801EB ICH5", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x25A4, + procid => "Intel 6300ESB", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x269B, + procid => "Intel Enterprise Southbridge - ESB2", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x266A, + procid => "Intel 82801FB ICH6", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x27DA, + procid => "Intel 82801G ICH7", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x283E, + procid => "Intel 82801H ICH8", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x2930, + procid => "Intel ICH9", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x5032, + procid => "Intel Tolapai", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x3A30, + procid => "Intel ICH10", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x3A60, + procid => "Intel ICH10", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x3B30, + procid => "Intel 3400/5 Series (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x1C22, + procid => "Intel Cougar Point (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x1D22, + procid => "Intel Patsburg (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x1D70, + procid => "Intel Patsburg (PCH) IDF", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x1D71, + procid => "Intel Patsburg (PCH) IDF", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x1D72, + procid => "Intel Patsburg (PCH) IDF", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x2330, + procid => "Intel DH89xxCC (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x1E22, + procid => "Intel Panther Point (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x8C22, + procid => "Intel Lynx Point (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x9C22, + procid => "Intel Lynx Point-LP (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x1F3C, + procid => "Avoton (SOC)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x8D22, + procid => "Wellsburg (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x8D7D, + procid => "Wellsburg (PCH) MS", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x8D7E, + procid => "Wellsburg (PCH) MS", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x8D7F, + procid => "Wellsburg (PCH) MS", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x23B0, + procid => "Coleto Creek (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x8CA2, + procid => "Wildcat Point (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x9CA2, + procid => "Wildcat Point-LP (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x0F12, + procid => "BayTrail (SOC)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0xA123, + procid => "Sunrise Point-H (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x9D23, + procid => "Sunrise Point-LP (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x19DF, + procid => "DNV (SOC)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x5AD4, + procid => "Broxton (SOC)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0xA1A3, + procid => "Lewisburg (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0xA223, + procid => "Lewisburg Supersku (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0xA2A3, + procid => "Kaby Lake (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x31D4, + procid => "Gemini Lake (SOC)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0xA323, + procid => "Cannon Lake-H (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x9DA3, + procid => "Cannon Lake-LP (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x18DF, + procid => "Cedar Fork (PCH)", + driver => "i2c-i801", + }, { + vendid => 0x8086, + devid => 0x8119, + procid => "Intel SCH", + driver => "i2c-isch", + }, { + vendid => 0x1106, + devid => 0x3040, + procid => "VIA Technologies VT82C586B Apollo ACPI", + driver => "i2c-via", + }, { + vendid => 0x1106, + devid => 0x3050, + procid => "VIA Technologies VT82C596 Apollo ACPI", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x3051, + procid => "VIA Technologies VT82C596B ACPI", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x3057, + procid => "VIA Technologies VT82C686 Apollo ACPI", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x3074, + procid => "VIA Technologies VT8233 VLink South Bridge", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x3147, + procid => "VIA Technologies VT8233A South Bridge", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x3177, + procid => "VIA Technologies VT8233A/8235 South Bridge", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x3227, + procid => "VIA Technologies VT8237 South Bridge", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x3337, + procid => "VIA Technologies VT8237A South Bridge", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x8235, + procid => "VIA Technologies VT8231 South Bridge", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x3287, + procid => "VIA Technologies VT8251 South Bridge", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x8324, + procid => "VIA Technologies CX700 South Bridge", + driver => "i2c-viapro", + }, { + vendid => 0x1106, + devid => 0x8353, + procid => "VIA Technologies VX800/VX820 South Bridge", + driver => "i2c-viapro", + }, { + vendid => 0x1039, + devid => 0x0008, + procid => "Silicon Integrated Systems SIS5595", + driver => "i2c-sis5595", + }, { + vendid => 0x1039, + devid => 0x0630, + procid => "Silicon Integrated Systems SIS630", + driver => "i2c-sis630", + }, { + vendid => 0x1039, + devid => 0x0730, + procid => "Silicon Integrated Systems SIS730", + driver => "i2c-sis630", + }, { + vendid => 0x1039, + devid => 0x0016, + procid => "Silicon Integrated Systems SMBus Controller", + driver => "i2c-sis96x", + }, { + # Both Ali chips below have same PCI ID. Can't be helped. Only one should load. + vendid => 0x10b9, + devid => 0x7101, + procid => "Acer Labs 1533/1543", + driver => "i2c-ali15x3", + }, { + vendid => 0x10b9, + devid => 0x7101, + procid => "Acer Labs 1535", + driver => "i2c-ali1535", + }, { + vendid => 0x10b9, + devid => 0x1563, + procid => "Acer Labs 1563", + driver => "i2c-ali1563", + }, { + vendid => 0x1022, + devid => 0x740b, + procid => "AMD-756 Athlon ACPI", + driver => "i2c-amd756", + }, { + vendid => 0x1022, + devid => 0x7413, + procid => "AMD-766 Athlon ACPI", + driver => "i2c-amd756", + }, { + vendid => 0x1022, + devid => 0x7443, + procid => "AMD-768 System Management", + driver => "i2c-amd756", + }, { + vendid => 0x1022, + devid => 0x746b, + procid => "AMD-8111 ACPI", + driver => "i2c-amd756", + }, { + vendid => 0x1022, + devid => 0x746a, + procid => "AMD-8111 SMBus 2.0", + driver => "i2c-amd8111", + }, { + vendid => 0x10de, + devid => 0x01b4, + procid => "nVidia nForce SMBus", + driver => "i2c-amd756", + }, { + vendid => 0x10de, + devid => 0x0064, + procid => "nVidia Corporation nForce2 SMBus (MCP)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x0084, + procid => "nVidia Corporation nForce2 Ultra 400 SMBus (MCP)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x00D4, + procid => "nVidia Corporation nForce3 Pro150 SMBus (MCP)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x00E4, + procid => "nVidia Corporation nForce3 250Gb SMBus (MCP)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x0052, + procid => "nVidia Corporation nForce4 SMBus (MCP)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x0034, + procid => "nVidia Corporation nForce4 SMBus (MCP-04)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x0264, + procid => "nVidia Corporation nForce SMBus (MCP51)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x0368, + procid => "nVidia Corporation nForce SMBus (MCP55)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x03eb, + procid => "nVidia Corporation nForce SMBus (MCP61)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x0446, + procid => "nVidia Corporation nForce SMBus (MCP65)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x0542, + procid => "nVidia Corporation nForce SMBus (MCP67)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x07d8, + procid => "nVidia Corporation nForce SMBus (MCP73)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x0752, + procid => "nVidia Corporation nForce SMBus (MCP78S)", + driver => "i2c-nforce2", + }, { + vendid => 0x10de, + devid => 0x0aa2, + procid => "nVidia Corporation nForce SMBus (MCP79)", + driver => "i2c-nforce2", + }, { + vendid => 0x1166, + devid => 0x0200, + procid => "ServerWorks OSB4 South Bridge", + driver => "i2c-piix4", + }, { + vendid => 0x1055, + devid => 0x9463, + procid => "SMSC Victory66 South Bridge", + driver => "i2c-piix4", + }, { + vendid => 0x1166, + devid => 0x0201, + procid => "ServerWorks CSB5 South Bridge", + driver => "i2c-piix4", + }, { + vendid => 0x1166, + devid => 0x0203, + procid => "ServerWorks CSB6 South Bridge", + driver => "i2c-piix4", + }, { + vendid => 0x1166, + devid => 0x0205, + procid => "ServerWorks HT-1000 South Bridge", + driver => "i2c-piix4", + }, { + vendid => 0x1002, + devid => 0x4353, + procid => "ATI Technologies Inc ATI SMBus", + driver => "i2c-piix4", + }, { + vendid => 0x1002, + devid => 0x4363, + procid => "ATI Technologies Inc ATI SMBus", + driver => "i2c-piix4", + }, { + vendid => 0x1002, + devid => 0x4372, + procid => "ATI Technologies Inc IXP SB400 SMBus Controller", + driver => "i2c-piix4", + }, { + vendid => 0x1002, + devid => 0x4385, + procid => "ATI Technologies Inc SB600/SB700/SB800 SMBus", + driver => "i2c-piix4", + }, { + vendid => 0x1022, + devid => 0x780b, + procid => "AMD Hudson-2 SMBus", + driver => "i2c-piix4", + }, { + vendid => 0x1022, + devid => 0x790b, + procid => "AMD KERNCZ SMBus", + driver => "i2c-piix4", + }, { + vendid => 0x100B, + devid => 0x0500, + procid => "SCx200 Bridge", + driver => "scx200_acb", + }, { + vendid => 0x100B, + devid => 0x0510, + procid => "SC1100 Bridge", + driver => "scx200_acb", + }, { + vendid => 0x100B, + devid => 0x002B, + procid => "CS5535 ISA bridge", + driver => "scx200_acb", + }, { + vendid => 0x1022, + devid => 0x2090, + procid => "CS5536 [Geode companion] ISA", + driver => "scx200_acb", + } +); + +# Look-up table to find out an I2C bus' driver based on the bus name. +# The match field should contain a regular expression matching the I2C +# bus name as it would appear in sysfs. +# Note that new drivers probably don't need to be added to this table +# if they bind to their device, as we will be able to get the driver name +# from sysfs directly. +use vars qw(@i2c_adapter_names); +@i2c_adapter_names = ( + { driver => "i2c-piix4", match => qr/^SMBus PIIX4 adapter at / }, + { driver => "i2c-i801", match => qr/^SMBus I801 adapter at / }, + { driver => "i2c-via", match => qr/^VIA i2c/ }, + { driver => "i2c-viapro", match => qr/^SMBus V(IA|ia) Pro adapter at / }, + { driver => "i2c-sis5595", match => qr/^SMBus SIS5595 adapter at / }, + { driver => "i2c-sis630", match => qr/^SMBus SIS630 adapter at / }, + { driver => "i2c-sis96x", match => qr/^SiS96x SMBus adapter at / }, + { driver => "i2c-ali15x3", match => qr/^SMBus ALI15X3 adapter at / }, + { driver => "i2c-ali1535", match => qr/^SMBus ALI1535 adapter at/ }, + { driver => "i2c-ali1563", match => qr/^SMBus ALi 1563 Adapter @ / }, + { driver => "i2c-amd756", match => qr/^SMBus (AMD756|AMD766|AMD768|AMD8111|nVidia nForce) adapter at / }, + { driver => "i2c-amd8111", match => qr/^SMBus2 AMD8111 adapter at / }, + { driver => "i2c-nforce2", match => qr/^SMBus nForce2 adapter at / }, + { driver => "scx200_acb", match => qr/^(NatSemi SCx200 ACCESS\.bus|SCx200 ACB\d+|CS553[56] ACB\d+)/ }, +); + +# This is a list of all recognized I2C and ISA chips. +# Each entry must have the following fields: +# name: The full chip name +# driver: The driver name. Put in exactly: +# * "to-be-written" if it is not yet available +# * "use-isa-instead" if no i2c driver will be written +# i2c_addrs (optional): For I2C chips, the list of I2C addresses to +# probe. +# i2c_detect (optional): For I2C chips, the function to call to detect +# this chip. The function will be passed two parameters: an open file +# descriptor to access the bus, and the I2C address to probe. +# isa_addrs (optional): For ISA chips, the list of port addresses to +# probe. +# isa_detect (optional): For ISA chips, the function to call to detect +# this chip. The function will be passed one parameter: the ISA address +# to probe. +# alias_detect (optional): For chips which can be both on the ISA and the +# I2C bus, a function which detects whether two entries are the same. +# The function will be passed three parameters: the ISA address, an +# open file descriptor to access the I2C bus, and the I2C address. +@chip_ids = ( + { + name => "Myson MTP008", + driver => "mtp008", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { mtp008_detect(@_); }, + }, { + name => "National Semiconductor LM78", + driver => "lm78", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { lm78_detect(@_, 0); }, + isa_addrs => [0x290], + isa_detect => sub { lm78_isa_detect(@_, 0); }, + alias_detect => sub { winbond_alias_detect(@_, 0x2b, 0x3d); }, + }, { + name => "National Semiconductor LM79", + driver => "lm78", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { lm78_detect(@_, 2); }, + isa_addrs => [0x290], + isa_detect => sub { lm78_isa_detect(@_, 2); }, + alias_detect => sub { winbond_alias_detect(@_, 0x2b, 0x3d); }, + }, { + name => "National Semiconductor LM75", + driver => "lm75", + i2c_addrs => [0x48..0x4f], + i2c_detect => sub { lm75_detect(@_, 0); }, + }, { + name => "National Semiconductor LM75A", + driver => "lm75", + i2c_addrs => [0x48..0x4f], + i2c_detect => sub { lm75_detect(@_, 2); }, + }, { + name => "Dallas Semiconductor DS75", + driver => "lm75", + i2c_addrs => [0x48..0x4f], + i2c_detect => sub { lm75_detect(@_, 1); }, + }, { + name => "National Semiconductor LM77", + driver => "lm77", + i2c_addrs => [0x48..0x4b], + i2c_detect => sub { lm77_detect(@_); }, + }, { + name => "National Semiconductor LM80", + driver => "lm80", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { lm80_detect(@_, 0); }, + }, { + name => "National Semiconductor LM96080", + driver => "lm80", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { lm80_detect(@_, 1); }, + }, { + name => "TI / National Semiconductor ADC128D818", + driver => "adc128d818", + i2c_addrs => [0x1d, 0x1e, 0x1f, 0x2d, 0x2e, 0x2f], + i2c_detect => sub { adc128d818_detect(@_); }, + }, { + name => "National Semiconductor LM85", + driver => "lm85", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm85_detect(@_, 0); }, + }, { + name => "National Semiconductor LM96000 or PC8374L", + driver => "lm85", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm85_detect(@_, 1); }, + }, { + name => "Analog Devices ADM1027", + driver => "lm85", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm85_detect(@_, 2); }, + }, { + name => "Analog Devices ADT7460 or ADT7463", + driver => "lm85", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm85_detect(@_, 3); }, + }, { + name => "SMSC EMC6D100 or EMC6D101", + driver => "lm85", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm85_detect(@_, 4); }, + }, { + name => "SMSC EMC6D102", + driver => "lm85", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm85_detect(@_, 5); }, + }, { + name => "SMSC EMC6D103", + driver => "lm85", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm85_detect(@_, 6); }, + }, { + name => "SMSC EMC6D103S or EMC2300", + driver => "lm85", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm85_detect(@_, 8); }, + }, { + name => "SMSC EMC6W201", + driver => "emc6w201", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { emc6w201_detect(@_); }, + }, { + name => "Winbond WPCD377I", + driver => "not-a-sensor", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm85_detect(@_, 7); }, + }, { + name => "Analog Devices ADT7462", + driver => "adt7462", + i2c_addrs => [0x5c, 0x58], + i2c_detect => sub { adt7467_detect(@_, 2); }, + }, { + name => "Analog Devices ADT7466", + driver => "to-be-written", + i2c_addrs => [0x4c], + i2c_detect => sub { adt7467_detect(@_, 3); }, + }, { + name => "Analog Devices ADT7467 or ADT7468", + driver => "lm85", + i2c_addrs => [0x2e], + i2c_detect => sub { adt7467_detect(@_, 0); }, + }, { + name => "Analog Devices ADT7470", + driver => "adt7470", + i2c_addrs => [0x2c, 0x2e, 0x2f], + i2c_detect => sub { adt7467_detect(@_, 4); }, + }, { + name => "Analog Devices ADT7473", + driver => sub { kernel_version_at_least(2, 6, 33) ? "adt7475" : "adt7473" }, + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { adt7473_detect(@_, 0); }, + }, { + name => "Analog Devices ADT7475", + driver => "adt7475", + i2c_addrs => [0x2e], + i2c_detect => sub { adt7473_detect(@_, 1); }, + }, { + name => "Analog Devices ADT7476", + driver => "adt7475", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { adt7467_detect(@_, 1); }, + }, { + name => "Analog Devices ADT7490", + driver => "adt7475", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { adt7490_detect(@_); }, + }, { + name => "Analog Devices ADT7410/ADT7420", + driver => "adt7410", + i2c_addrs => [0x48..0x4b], + i2c_detect => sub { adt7410_detect(@_); }, + }, { + name => "Analog Devices ADT7411", + driver => "adt7411", + i2c_addrs => [0x48, 0x4a, 0x4b], + i2c_detect => sub { adt7411_detect(@_); }, + }, { + name => "Andigilog aSC7511", + driver => "to-be-written", + i2c_addrs => [0x4c], + i2c_detect => sub { andigilog_aSC7511_detect(@_); }, + }, { + name => "Andigilog aSC7512", + driver => "to-be-written", + i2c_addrs => [0x58], + i2c_detect => sub { andigilog_detect(@_, 0); }, + }, { + name => "Andigilog aSC7611", + driver => "to-be-written", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { andigilog_detect(@_, 1); }, + }, { + name => "Andigilog aSC7621", + driver => "asc7621", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { andigilog_detect(@_, 2); }, + }, { + name => "National Semiconductor LM87", + driver => "lm87", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm87_detect(@_, 0); }, + }, { + name => "Analog Devices ADM1024", + driver => "lm87", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm87_detect(@_, 1); }, + }, { + name => "National Semiconductor LM93", + driver => "lm93", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm93_detect(@_, 0); }, + }, { + name => "National Semiconductor LM94 or LM96194", + driver => "lm93", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { lm93_detect(@_, 1); }, + }, { + name => "Winbond W83781D", + driver => "w83781d", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { w83781d_detect(@_, 0); }, + isa_addrs => [0x290], + isa_detect => sub { w83781d_isa_detect(@_, 0); }, + alias_detect => sub { winbond_alias_detect(@_, 0x2b, 0x3d); }, + }, { + name => "Winbond W83782D", + driver => "w83781d", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { w83781d_detect(@_, 1); }, + isa_addrs => [0x290], + isa_detect => sub { w83781d_isa_detect(@_, 1); }, + alias_detect => sub { winbond_alias_detect(@_, 0x2b, 0x3d); }, + }, { + name => "Winbond W83783S", + driver => "w83781d", + i2c_addrs => [0x2d], + i2c_detect => sub { w83781d_detect(@_, 2); }, + }, { + name => "Winbond W83791D", + driver => "w83791d", + i2c_addrs => [0x2c..0x2f], + i2c_detect => sub { w83781d_detect(@_, 7); }, + }, { + name => "Winbond W83792D", + driver => "w83792d", + i2c_addrs => [0x2c..0x2f], + i2c_detect => sub { w83781d_detect(@_, 8); }, + }, { + name => "Winbond W83793R/G", + driver => "w83793", + i2c_addrs => [0x2c..0x2f], + i2c_detect => sub { w83793_detect(@_); }, + }, { + name => "Nuvoton W83795G/ADG", + driver => "w83795", + i2c_addrs => [0x2c..0x2f], + i2c_detect => sub { w83795_detect(@_); }, + }, { + name => "Nuvoton NCT7802Y", + driver => "nct7802", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { nct7802_detect(@_); }, + }, { + name => "Nuvoton NCT7904D", + driver => "nct7904", + i2c_addrs => [0x2d..0x2e], + i2c_detect => sub { nct7904_detect(@_); }, + }, { + name => "Winbond W83627HF", + driver => "use-isa-instead", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { w83781d_detect(@_, 3); }, + }, { + name => "Winbond W83627EHF", + driver => "use-isa-instead", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { w83781d_detect(@_, 9); }, + }, { + name => "Winbond W83627DHG/W83667HG/W83677HG", + driver => "use-isa-instead", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { w83781d_detect(@_, 10); }, + }, { + name => "Asus AS99127F (rev.1)", + driver => "w83781d", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { w83781d_detect(@_, 4); }, + }, { + name => "Asus AS99127F (rev.2)", + driver => "w83781d", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { w83781d_detect(@_, 5); }, + }, { + name => "Asus ASB100 Bach", + driver => "asb100", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { w83781d_detect(@_, 6); }, + }, { + name => "Asus Mozart-2", + driver => "to-be-written", + i2c_addrs => [0x77], + i2c_detect => sub { mozart_detect(@_); }, + }, { + name => "Winbond W83L784R/AR/G", + driver => "to-be-written", + i2c_addrs => [0x2d], + i2c_detect => sub { w83l784r_detect(@_, 0); }, + }, { + name => "Winbond W83L785R/G", + driver => "to-be-written", + i2c_addrs => [0x2d], + i2c_detect => sub { w83l784r_detect(@_, 1); }, + }, { + name => "Winbond W83L786NR/NG/R/G", + driver => "w83l786ng", + i2c_addrs => [0x2e, 0x2f], + i2c_detect => sub { w83l784r_detect(@_, 2); }, + }, { + name => "Winbond W83L785TS-S", + driver => "w83l785ts", + i2c_addrs => [0x2e], + i2c_detect => sub { w83l784r_detect(@_, 3); }, + }, { + name => "Genesys Logic GL518SM", + driver => "gl518sm", + i2c_addrs => [0x2c, 0x2d], + i2c_detect => sub { gl518sm_detect(@_, 0); }, + }, { + name => "Genesys Logic GL520SM", + driver => "gl520sm", + i2c_addrs => [0x2c, 0x2d], + i2c_detect => sub { gl518sm_detect(@_, 1); }, + }, { + name => "Genesys Logic GL525SM", + driver => "to-be-written", + i2c_addrs => [0x2d], + i2c_detect => sub { gl525sm_detect(@_); }, + }, { + name => "Analog Devices ADM9240", + driver => "adm9240", + i2c_addrs => [0x2c..0x2f], + i2c_detect => sub { adm9240_detect(@_, 0); }, + }, { + name => "Dallas Semiconductor DS1780", + driver => "adm9240", + i2c_addrs => [0x2c..0x2f], + i2c_detect => sub { adm9240_detect(@_, 1); }, + }, { + name => "National Semiconductor LM81", + driver => "adm9240", + i2c_addrs => [0x2c..0x2f], + i2c_detect => sub { adm9240_detect(@_, 2); }, + }, { + name => "Analog Devices ADM1026", + driver => "adm1026", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { adm1026_detect(@_); }, + }, { + name => "Analog Devices ADM1025", + driver => "adm1025", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { adm1025_detect(@_, 0); }, + }, { + name => "Philips NE1619", + driver => "adm1025", + i2c_addrs => [0x2c..0x2d], + i2c_detect => sub { adm1025_detect(@_, 1); }, + }, { + name => "Analog Devices ADM1021", + driver => "adm1021", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { adm1021_detect(@_, 0); }, + }, { + name => "Analog Devices ADM1021A/ADM1023", + driver => "adm1021", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { adm1021_detect(@_, 1); }, + }, { + name => "Global Mixed-mode Technology G781", + driver => "lm90", + i2c_addrs => [0x4c, 0x4d], + i2c_detect => sub { lm90_detect(@_, 15); }, + }, { + name => "Maxim MAX1617", + driver => "adm1021", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { adm1021_detect(@_, 2); }, + }, { + name => "Maxim MAX1617A", + driver => "adm1021", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { adm1021_detect(@_, 3); }, + }, { + name => "Maxim MAX1668", + driver => "max1668", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { max1668_detect(@_, 0); }, + }, { + name => "Maxim MAX1805", + driver => "max1668", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { max1668_detect(@_, 1); }, + }, { + name => "Maxim MAX1989", + driver => "max1668", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { max1668_detect(@_, 2); }, + }, { + name => "Maxim MAX6639", + driver => "max6639", + i2c_addrs => [0x2c, 0x2e, 0x2f], + i2c_detect => sub { max6639_detect(@_); }, + }, { + name => "Maxim MAX6642", + driver => "max6642", + i2c_addrs => [0x48..0x4f], + i2c_detect => sub { max6642_detect(@_); }, + }, { + name => "Maxim MAX6655/MAX6656", + driver => "max6655", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { max6655_detect(@_); }, + }, { + name => "TI THMC10", + driver => "adm1021", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { adm1021_detect(@_, 4); }, + }, { + name => "National Semiconductor LM84", + driver => "adm1021", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { adm1021_detect(@_, 5); }, + }, { + name => "Genesys Logic GL523SM", + driver => "adm1021", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { adm1021_detect(@_, 6); }, + }, { + name => "Onsemi MC1066", + driver => "adm1021", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { adm1021_detect(@_, 7); }, + }, { + name => "Maxim MAX1618", + driver => "max1619", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { max1619_detect(@_, 1); }, + }, { + name => "Maxim MAX1619", + driver => "max1619", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { max1619_detect(@_, 0); }, + }, { + name => "National Semiconductor LM82/LM83", + driver => "lm83", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { lm83_detect(@_); }, + }, { + name => "National Semiconductor LM90", + driver => "lm90", + i2c_addrs => [0x4c], + i2c_detect => sub { lm90_detect(@_, 0); }, + }, { + name => "National Semiconductor LM89/LM99", + driver => "lm90", + i2c_addrs => [0x4c..0x4d], + i2c_detect => sub { lm90_detect(@_, 1); }, + }, { + name => "National Semiconductor LM86", + driver => "lm90", + i2c_addrs => [0x4c], + i2c_detect => sub { lm90_detect(@_, 2); }, + }, { + name => "Analog Devices ADM1032", + driver => "lm90", + i2c_addrs => [0x4c..0x4d], + i2c_detect => sub { lm90_detect(@_, 3); }, + }, { + name => "Maxim MAX6654", + driver => "to-be-written", # probably lm90 + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { lm90_detect(@_, 4); }, + }, { + name => "Maxim MAX6690", + driver => "to-be-written", # probably lm90 + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { lm90_detect(@_, 12); }, + }, { + name => "Maxim MAX6657/MAX6658/MAX6659", + driver => "lm90", + i2c_addrs => [0x4c], + i2c_detect => sub { max6657_detect(@_); }, + }, { + name => "Maxim MAX6659", + driver => "lm90", + i2c_addrs => [0x4d..0x4e], # 0x4c is handled above + i2c_detect => sub { max6657_detect(@_); }, + }, { + name => "Maxim MAX6646", + driver => "lm90", + i2c_addrs => [0x4d], + i2c_detect => sub { lm90_detect(@_, 6); }, + }, { + name => "Maxim MAX6647", + driver => "lm90", + i2c_addrs => [0x4e], + i2c_detect => sub { lm90_detect(@_, 6); }, + }, { + name => "Maxim MAX6648/MAX6649/MAX6692", + driver => "lm90", + i2c_addrs => [0x4c], + i2c_detect => sub { lm90_detect(@_, 6); }, + }, { + name => "Maxim MAX6680/MAX6681", + driver => "lm90", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { max6680_95_detect(@_, 0); }, + }, { + name => "Maxim MAX6695/MAX6696", + driver => "lm90", + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { max6680_95_detect(@_, 1); }, + }, { + name => "Winbond W83L771W/G", + driver => "lm90", + i2c_addrs => [0x4c], + i2c_detect => sub { lm90_detect(@_, 8); }, + }, { + name => "Winbond W83L771AWG/ASG", + driver => "lm90", + i2c_addrs => [0x4c], + i2c_detect => sub { lm90_detect(@_, 11); }, + }, { + name => "Texas Instruments TMP400", + driver => "to-be-written", # tmp401 + i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e], + i2c_detect => sub { tmp401_detect(@_, 0); }, + }, { + name => "Texas Instruments TMP401", + driver => "tmp401", + i2c_addrs => [0x4c], + i2c_detect => sub { tmp401_detect(@_, 1); }, + }, { + name => "Texas Instruments TMP411A", + driver => "tmp401", + i2c_addrs => [0x4c], + i2c_detect => sub { tmp401_detect(@_, 2); }, + }, { + name => "Texas Instruments TMP411B", + driver => "tmp401", + i2c_addrs => [0x4d], + i2c_detect => sub { tmp401_detect(@_, 3); }, + }, { + name => "Texas Instruments TMP411C", + driver => "tmp401", + i2c_addrs => [0x4e], + i2c_detect => sub { tmp401_detect(@_, 4); }, + }, { + name => "Texas Instruments TMP421", + driver => "tmp421", + i2c_addrs => [0x1c..0x1f, 0x2a, 0x4c..0x4f], + i2c_detect => sub { tmp42x_detect(@_, 0); }, + }, { + name => "Texas Instruments TMP422", + driver => "tmp421", + i2c_addrs => [0x4c..0x4f], + i2c_detect => sub { tmp42x_detect(@_, 1); }, + }, { + name => "Texas Instruments TMP423", + driver => "tmp421", + i2c_addrs => [0x4c, 0x4d], + i2c_detect => sub { tmp42x_detect(@_, 2); }, + }, { + name => "Texas Instruments TMP431", + driver => "tmp401", + i2c_addrs => [0x4c, 0x4d], + i2c_detect => sub { tmp401_detect(@_, 5); }, + }, { + name => "Texas Instruments TMP432", + driver => "tmp401", + i2c_addrs => [0x4c, 0x4d], + i2c_detect => sub { tmp401_detect(@_, 6); }, + }, { + name => "Texas Instruments TMP435", + driver => "tmp401", + i2c_addrs => [0x48..0x4f], # 0x37 not probed + i2c_detect => sub { tmp401_detect(@_, 7); }, + }, { + name => "Texas Instruments TMP441", + driver => "tmp421", + i2c_addrs => [0x1c..0x1f, 0x2a, 0x4c..0x4f], + i2c_detect => sub { tmp42x_detect(@_, 3); }, + }, { + name => "Texas Instruments TMP442", + driver => "tmp421", + i2c_addrs => [0x4c, 0x4d], + i2c_detect => sub { tmp42x_detect(@_, 4); }, + }, { + name => "Texas Instruments TMP451", + driver => "lm90", + i2c_addrs => [0x4c], + i2c_detect => sub { tmp401_detect(@_, 8); }, + }, { + name => "Texas Instruments AMC6821", + driver => "amc6821", + i2c_addrs => [0x18..0x1a, 0x2c..0x2e, 0x4c..0x4e], + i2c_detect => sub { amc6821_detect(@_); }, + }, { + name => "National Semiconductor LM95231", + driver => "lm95241", + i2c_addrs => [0x2b, 0x19, 0x2a], + i2c_detect => sub { lm95231_detect(@_, 0); }, + }, { + name => "National Semiconductor LM95233", + driver => "lm95234", + i2c_addrs => [0x18, 0x2a, 0x2b], + i2c_detect => sub { lm95231_detect(@_, 5); }, + }, { + name => "National Semiconductor LM95234", + driver => "lm95234", + i2c_addrs => [0x18, 0x4d, 0x4e], + i2c_detect => sub { lm95231_detect(@_, 3); }, + }, { + name => "National Semiconductor LM95235", + driver => "lm95245", + i2c_addrs => [0x18, 0x29, 0x4c], + i2c_detect => sub { lm95231_detect(@_, 4); }, + }, { + name => "National Semiconductor LM95241", + driver => "lm95241", + i2c_addrs => [0x2b, 0x19, 0x2a], + i2c_detect => sub { lm95231_detect(@_, 1); }, + }, { + name => "National Semiconductor LM95245", + driver => "lm95245", + i2c_addrs => [0x18, 0x19, 0x29, 0x4c, 0x4d], + i2c_detect => sub { lm95231_detect(@_, 2); }, + }, { + name => "National Semiconductor LM63", + driver => "lm63", + i2c_addrs => [0x4c], + i2c_detect => sub { lm63_detect(@_, 1); }, + }, { + name => "National Semiconductor LM64", + driver => "lm63", + i2c_addrs => [0x18, 0x4e], + i2c_detect => sub { lm63_detect(@_, 3); }, + }, { + name => "National Semiconductor LM96163", + driver => "lm63", + i2c_addrs => [0x4c], + i2c_detect => sub { lm63_detect(@_, 4); }, + }, { + name => "Fintek F75363SG", + driver => "lm63", # Not yet + i2c_addrs => [0x4c], + i2c_detect => sub { lm63_detect(@_, 2); }, + }, { + name => "National Semiconductor LM73", + driver => "lm73", + i2c_addrs => [0x48..0x4a, 0x4c..0x4e], + i2c_detect => sub { lm73_detect(@_); }, + }, { + name => "National Semiconductor LM92", + driver => "lm92", + i2c_addrs => [0x48..0x4b], + i2c_detect => sub { lm92_detect(@_, 0); }, + }, { + name => "National Semiconductor LM76", + driver => "lm92", + i2c_addrs => [0x48..0x4b], + i2c_detect => sub { lm92_detect(@_, 1); }, + }, { + name => "Maxim MAX6633/MAX6634/MAX6635", + driver => "lm92", + i2c_addrs => [0x48..0x4f], # The MAX6633 can also use 0x40-0x47 but we + # don't want to probe these addresses, it's + # dangerous. + i2c_detect => sub { lm92_detect(@_, 2); }, + }, { + name => "Analog Devices ADT7461", + driver => "lm90", + i2c_addrs => [0x4c..0x4d], + i2c_detect => sub { lm90_detect(@_, 5); }, + }, { + name => "Analog Devices ADT7461A, ON Semiconductor NCT1008", + driver => "lm90", + i2c_addrs => [0x4c..0x4d], + i2c_detect => sub { lm90_detect(@_, 13); }, + }, { + name => "NXP/Philips SA56004", + driver => "lm90", + i2c_addrs => [0x48..0x4f], + i2c_detect => sub { lm90_detect(@_, 14); }, + }, { + name => "Analog Devices ADT7481", + driver => "to-be-written", + i2c_addrs => [0x4c, 0x4b], + i2c_detect => sub { adt7481_detect(@_); }, + }, { + name => "Analog Devices ADM1029", + driver => "adm1029", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { adm1029_detect(@_); }, + }, { + name => "Analog Devices ADM1030", + driver => "adm1031", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { adm1031_detect(@_, 0); }, + }, { + name => "Analog Devices ADM1031", + driver => "adm1031", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { adm1031_detect(@_, 1); }, + }, { + name => "Analog Devices ADM1033", + driver => "to-be-written", + i2c_addrs => [0x50..0x53], + i2c_detect => sub { adm1034_detect(@_, 0); }, + }, { + name => "Analog Devices ADM1034", + driver => "to-be-written", + i2c_addrs => [0x50..0x53], + i2c_detect => sub { adm1034_detect(@_, 1); }, + }, { + name => "Analog Devices ADM1022", + driver => "thmc50", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { adm1022_detect(@_, 0); }, + }, { + name => "Texas Instruments THMC50", + driver => "thmc50", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { adm1022_detect(@_, 1); }, + }, { + name => "Analog Devices ADM1028", + driver => "thmc50", + i2c_addrs => [0x2e], + i2c_detect => sub { adm1022_detect(@_, 2); }, + }, { + name => "Texas Instruments THMC51", + driver => "to-be-written", # thmc50 + i2c_addrs => [0x2e], # At least (no datasheet) + i2c_detect => sub { adm1022_detect(@_, 3); }, + }, { + name => "VIA VT1211 (I2C)", + driver => "use-isa-instead", + i2c_addrs => [0x2d], + i2c_detect => sub { vt1211_i2c_detect(@_); }, + }, { + name => "ITE IT8712F", + driver => "it87", + i2c_addrs => [0x28..0x2f], + i2c_detect => sub { it8712_i2c_detect(@_); }, + }, { + name => "FSC Poseidon I", + driver => sub { kernel_version_at_least(2, 6, 24) ? "fschmd" : "fscpos" }, + i2c_addrs => [0x73], + i2c_detect => sub { fsc_detect(@_, 0); }, + }, { + name => "FSC Poseidon II", + driver => "to-be-written", + i2c_addrs => [0x73], + i2c_detect => sub { fsc_detect(@_, 1); }, + }, { + name => "FSC Scylla", + driver => "fschmd", + i2c_addrs => [0x73], + i2c_detect => sub { fsc_detect(@_, 2); }, + }, { + name => "FSC Hermes", + driver => sub { kernel_version_at_least(2, 6, 24) ? "fschmd" : "fscher" }, + i2c_addrs => [0x73], + i2c_detect => sub { fsc_detect(@_, 3); }, + }, { + name => "FSC Heimdal", + driver => "fschmd", + i2c_addrs => [0x73], + i2c_detect => sub { fsc_detect(@_, 4); }, + }, { + name => "FSC Heracles", + driver => "fschmd", + i2c_addrs => [0x73], + i2c_detect => sub { fsc_detect(@_, 5); }, + }, { + name => "FSC Hades", + driver => "fschmd", + i2c_addrs => [0x73], + i2c_detect => sub { fsc_detect(@_, 6); }, + }, { + name => "FSC Syleus", + driver => "fschmd", + i2c_addrs => [0x73], + i2c_detect => sub { fsc_detect(@_, 7); }, + }, { + name => "ALi M5879", + driver => "to-be-written", + i2c_addrs => [0x2c..0x2d], + i2c_detect => sub { m5879_detect(@_); }, + }, { + name => "SMSC LPC47M15x/192/292/997", + driver => "smsc47m192", + i2c_addrs => [0x2c..0x2d], + i2c_detect => sub { smsc47m192_detect(@_); }, + }, { + name => "SMSC DME1737", + driver => "dme1737", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { dme1737_detect(@_, 1); }, + }, { + name => "SMSC SCH5027D-NW", + driver => "dme1737", + i2c_addrs => [0x2c..0x2e], + i2c_detect => sub { dme1737_detect(@_, 2); }, + }, { + name => "SMSC EMC2103", + driver => "emc2103", + i2c_addrs => [0x2e], + i2c_detect => sub { emc1403_detect(@_, 2); }, + }, { + name => "SMSC EMC2104", + driver => "to-be-written", + i2c_addrs => [0x2f], + i2c_detect => sub { emc1403_detect(@_, 13); }, + }, { + name => "Fintek F75121R/F75122R/RG (VID+GPIO)", + driver => "to-be-written", + i2c_addrs => [0x4e], # 0x37 not probed + i2c_detect => sub { fintek_detect(@_, 2); }, + }, { + name => "Fintek F75373S/SG", + driver => "f75375s", + i2c_addrs => [0x2d..0x2e], + i2c_detect => sub { fintek_detect(@_, 3); }, + }, { + name => "Fintek F75375S/SP", + driver => "f75375s", + i2c_addrs => [0x2d..0x2e], + i2c_detect => sub { fintek_detect(@_, 4); }, + }, { + name => "Fintek F75387SG/RG", + driver => "to-be-written", + i2c_addrs => [0x2d..0x2e], + i2c_detect => sub { fintek_detect(@_, 5); }, + }, { + name => "Fintek F75383S/M", + driver => "to-be-written", + i2c_addrs => [0x4c], + i2c_detect => sub { fintek_detect(@_, 6); }, + }, { + name => "Fintek F75384S/M", + driver => "to-be-written", + i2c_addrs => [0x4d], + i2c_detect => sub { fintek_detect(@_, 6); }, + }, { + name => "Fintek custom power control IC", + driver => "to-be-written", + i2c_addrs => [0x2f], + i2c_detect => sub { fintek_detect(@_, 7); }, + }, { + name => "SMSC EMC1002", + driver => "to-be-written", + i2c_addrs => [0x4c, 0x4d], # 0x3c, 0x3d not probed + i2c_detect => sub { emc1403_detect(@_, 4); }, + }, { + name => "SMSC EMC1023", + driver => "to-be-written", # emc1023 + i2c_addrs => [0x48, 0x49, 0x4c, 0x4d], + i2c_detect => sub { emc1023_detect(@_, 0); }, + }, { + name => "SMSC EMC1033", + driver => "to-be-written", + i2c_addrs => [0x4c, 0x4d], # 0x3c, 0x3d not probed + i2c_detect => sub { emc1403_detect(@_, 5); }, + }, { + name => "SMSC EMC1043", + driver => "to-be-written", # emc1023 + i2c_addrs => [0x48, 0x49, 0x4c, 0x4d], + i2c_detect => sub { emc1023_detect(@_, 1); }, + }, { + name => "SMSC EMC1046", + driver => "to-be-written", + i2c_addrs => [0x4c, 0x4d], + i2c_detect => sub { emc1403_detect(@_, 6); }, + }, { + name => "SMSC EMC1047", + driver => "to-be-written", + i2c_addrs => [0x18], # 0x10 not probed + i2c_detect => sub { emc1403_detect(@_, 7); }, + }, { + name => "SMSC EMC1053", + driver => "to-be-written", # emc1023 + i2c_addrs => [0x48, 0x49, 0x4c, 0x4d], + i2c_detect => sub { emc1023_detect(@_, 2); }, + }, { + name => "SMSC EMC1063", + driver => "to-be-written", # emc1023 + i2c_addrs => [0x48, 0x49, 0x4c, 0x4d], + i2c_detect => sub { emc1023_detect(@_, 3); }, + }, { + name => "SMSC EMC1072", + driver => "to-be-written", + i2c_addrs => [0x1c, 0x2c, 0x4c, 0x5c], # 0x3c, 0x6c, 0x7c not probed + i2c_detect => sub { emc1403_detect(@_, 8); }, + }, { + name => "SMSC EMC1073", + driver => "to-be-written", + i2c_addrs => [0x1c, 0x2c, 0x4c, 0x5c], # 0x3c, 0x6c, 0x7c not probed + i2c_detect => sub { emc1403_detect(@_, 9); }, + }, { + name => "SMSC EMC1074", + driver => "to-be-written", + i2c_addrs => [0x1c, 0x2c, 0x4c, 0x5c], # 0x3c, 0x6c, 0x7c not probed + i2c_detect => sub { emc1403_detect(@_, 10); }, + }, { + name => "SMSC EMC1402", + driver => "emc1403", + i2c_addrs => [0x18, 0x29, 0x4c, 0x4d], + i2c_detect => sub { emc1403_detect(@_, 11); }, + }, { + name => "SMSC EMC1403", + driver => "emc1403", + i2c_addrs => [0x18, 0x29, 0x4c, 0x4d], + i2c_detect => sub { emc1403_detect(@_, 0); }, + }, { + name => "SMSC EMC1404", + driver => "emc1403", + i2c_addrs => [0x18, 0x29, 0x4c, 0x4d], + i2c_detect => sub { emc1403_detect(@_, 1); }, + }, { + name => "SMSC EMC1422", + driver => "emc1403", + i2c_addrs => [0x4c], + i2c_detect => sub { emc1403_detect(@_, 14); }, + }, { + name => "SMSC EMC1423", + driver => "emc1403", + i2c_addrs => [0x4c], + i2c_detect => sub { emc1403_detect(@_, 3); }, + }, { + name => "SMSC EMC1424", + driver => "emc1403", + i2c_addrs => [0x4c], + i2c_detect => sub { emc1403_detect(@_, 12); }, + }, { + name => "ST STTS424", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 0); }, + }, { + name => "ST STTS424E", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 10); }, + }, { + name => "ST STTS2002", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 11); }, + }, { + name => "ST STTS3000", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 12); }, + }, { + name => "NXP SE97/SE97B", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 1); }, + }, { + name => "NXP SE98", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 2); }, + }, { + name => "Analog Devices ADT7408", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 3); }, + }, { + name => "IDT TS3000/TSE2002", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 4); }, + }, { + name => "IDT TSE2004", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 16); }, + }, { + name => "IDT TS3001", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 17); }, + }, { + name => "Maxim MAX6604", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 5); }, + }, { + name => "Microchip MCP9804", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 13); }, + }, { + name => "Microchip MCP9808", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 18); }, + },{ + name => "Microchip MCP98242", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 6); }, + }, { + name => "Microchip MCP98243", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 7); }, + }, { + name => "Microchip MCP98244", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 15); }, + }, { + name => "Microchip MCP9843", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 8); }, + }, { + name => "ON CAT6095/CAT34TS02", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 9); }, + }, { + name => "ON CAT34TS02C", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 19); }, + }, { + name => "ON CAT34TS04", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 21); }, + }, { + name => "Atmel AT30TS00", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 14); }, + }, { + name => "Giantec GT30TS00", + driver => "jc42", + i2c_addrs => [0x18..0x1f], + i2c_detect => sub { jedec_JC42_4_detect(@_, 20); }, + } +); + +# IPMI interfaces have their own array now +@ipmi_ifs = ( + { + name => "IPMI BMC KCS", + driver => "to-be-written", # ipmisensors + isa_addrs => [0x0ca0], + isa_detect => sub { ipmi_detect(@_); }, + }, { + name => "IPMI BMC SMIC", + driver => "to-be-written", # ipmisensors + isa_addrs => [0x0ca8], + isa_detect => sub { ipmi_detect(@_); }, + } +); + +# Here is a similar list, but for devices which are not hardware monitoring +# chips. We only list popular devices which happen to live at the same I2C +# address as recognized hardware monitoring chips. The idea is to make it +# clear that the chip in question is of no interest for lm-sensors. +@non_hwmon_chip_ids = ( + { + name => "Winbond W83791SD", + i2c_addrs => [0x2c..0x2f], + i2c_detect => sub { w83791sd_detect(@_); }, + }, { + name => "Fintek F75111R/RG/N (GPIO)", + i2c_addrs => [0x37, 0x4e], + i2c_detect => sub { fintek_detect(@_, 1); }, + }, { + name => "ITE IT8201R/IT8203R/IT8206R/IT8266R", + i2c_addrs => [0x4e], + i2c_detect => sub { ite_overclock_detect(@_); }, + }, { + name => "SPD EEPROM", + i2c_addrs => [0x50..0x57], + i2c_detect => sub { eeprom_detect(@_); }, + }, { + name => "EDID EEPROM", + i2c_addrs => [0x50], + i2c_detect => sub { ddcmonitor_detect(@_); }, + } +); + +# This is a list of all recognized superio chips. +# Each entry must have the following fields: +# name: The full chip name +# driver: The driver name. Put in exactly: +# * "to-be-written" if it is not yet available +# * "not-a-sensor" if the chip doesn't have hardware monitoring +# capabilities (listing such chips here removes the need of manual +# lookup when people report them) +# * "via-smbus-only" if this is a Super-I/O chip whose hardware +# monitoring registers can only be accessed via the SMBus +# devid: The device ID we have to match (base device) +# devid_mask (optional): Bitmask to apply before checking the device ID +# regs (optional): Register definitions, where they differ from the standard. +# logdev: The logical device containing the sensors +# check (optional): A function to refine the detection. Will be passed +# the index and data ports as parameters. Must return 1 for a matching +# device, 0 otherwise. +# features (optional): Features supported by this device, amongst: +# * FEAT_IN +# * FEAT_FAN +# * FEAT_TEMP +use vars qw(@superio_ids_natsemi @superio_ids_smsc @superio_ids_smsc_ns + @superio_ids_winbond @superio_ids_ite @superio_ids); + +use constant FEAT_IN => (1 << 0); +use constant FEAT_FAN => (1 << 1); +use constant FEAT_TEMP => (1 << 2); +use constant FEAT_SMBUS => (1 << 7); + +@superio_ids_natsemi = ( + { + name => "Nat. Semi. PC8374L Super IO Sensors", # Also Nuvoton WPCD374L + driver => "to-be-written", + devid => 0xf1, + check => sub { + outb($_[0], 0x27); + # Guess work; seen so far: 0x11 + return (inb($_[1]) < 0x80); + }, + logdev => 0x08, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton WPCD377I Super IO", # Also WPCD376I + driver => "not-a-sensor", + devid => 0xf1, + check => sub { + outb($_[0], 0x27); + # Guess work; seen so far: 0x91 (twice) + return (inb($_[1]) >= 0x80); + }, + }, { + name => "Nat. Semi. PC87351 Super IO Fan Sensors", + driver => "to-be-written", + devid => 0xe2, + logdev => 0x08, + }, { + name => "Nat. Semi. PC87360 Super IO Fan Sensors", + driver => "pc87360", + devid => 0xe1, + logdev => 0x09, + features => FEAT_FAN, + }, { + name => "Nat. Semi. PC87363 Super IO Fan Sensors", + driver => "pc87360", + devid => 0xe8, + logdev => 0x09, + features => FEAT_FAN, + }, { + name => "Nat. Semi. PC87364 Super IO Fan Sensors", + driver => "pc87360", + devid => 0xe4, + logdev => 0x09, + features => FEAT_FAN, + }, { + name => "Nat. Semi. PC87365 Super IO Fan Sensors", + driver => "pc87360", + devid => 0xe5, + logdev => 0x09, + features => FEAT_FAN, + }, { + name => "Nat. Semi. PC87365 Super IO Voltage Sensors", + driver => "pc87360", + devid => 0xe5, + logdev => 0x0d, + features => FEAT_IN, + }, { + name => "Nat. Semi. PC87365 Super IO Thermal Sensors", + driver => "pc87360", + devid => 0xe5, + logdev => 0x0e, + features => FEAT_TEMP, + }, { + name => "Nat. Semi. PC87366 Super IO Fan Sensors", + driver => "pc87360", + devid => 0xe9, + logdev => 0x09, + features => FEAT_FAN, + }, { + name => "Nat. Semi. PC87366 Super IO Voltage Sensors", + driver => "pc87360", + devid => 0xe9, + logdev => 0x0d, + features => FEAT_IN, + }, { + name => "Nat. Semi. PC87366 Super IO Thermal Sensors", + driver => "pc87360", + devid => 0xe9, + logdev => 0x0e, + features => FEAT_TEMP, + }, { + name => "Nat. Semi. PC87372 Super IO Fan Sensors", + driver => "to-be-written", + devid => 0xf0, + logdev => 0x09, + features => FEAT_FAN, + }, { + name => "Nat. Semi. PC87373 Super IO Fan Sensors", + driver => "to-be-written", + devid => 0xf3, + logdev => 0x09, + features => FEAT_FAN, + }, { + name => "Nat. Semi. PC87591 Super IO", + driver => "to-be-written", + devid => 0xec, + logdev => 0x0f, + }, { + name => "Nat. Semi. PC87317 Super IO", + driver => "not-a-sensor", + devid => 0xd0, + }, { + name => "Nat. Semi. PC97317 Super IO", + driver => "not-a-sensor", + devid => 0xdf, + }, { + name => "Nat. Semi. PC8739x Super IO", + driver => "not-a-sensor", + devid => 0xea, + }, { + name => "Nat. Semi. PC8741x Super IO", + driver => "not-a-sensor", + devid => 0xee, + }, { + name => "Nat. Semi. PC87427 Super IO Fan Sensors", + driver => "pc87427", + devid => 0xf2, + logdev => 0x09, + features => FEAT_FAN, + }, { + name => "Nat. Semi. PC87427 Super IO Health Sensors", + driver => "to-be-written", + devid => 0xf2, + logdev => 0x14, + features => FEAT_IN | FEAT_TEMP, + }, { + name => "ITE IT8510E/TE/G Super IO", + driver => "to-be-written", + devid => 0x8510, + features => FEAT_IN | FEAT_FAN, + }, { + name => "ITE IT8511E/TE/G Super IO", + driver => "to-be-written", + devid => 0x8511, + features => FEAT_IN | FEAT_FAN, + }, { + name => "ITE IT8512E/F/G Super IO", + driver => "to-be-written", + devid => 0x8512, + features => FEAT_IN | FEAT_FAN, + }, { + name => "ITE IT8513E/F/G Super IO", + driver => "to-be-written", + devid => 0x8513, + features => FEAT_IN | FEAT_FAN, + }, { + name => "ITE IT8516E/F/G Super IO", + driver => "to-be-written", + devid => 0x8516, + features => FEAT_IN | FEAT_FAN, + }, { + name => "ITE IT8518E Super IO", + driver => "to-be-written", + devid => 0x8518, + features => FEAT_IN | FEAT_FAN, + } +); + +@superio_ids_smsc = ( + { + name => "SMSC DME1737 Super IO", + # Hardware monitoring features are accessed on the SMBus + driver => "via-smbus-only", + devid => 0x78, + }, { + name => "SMSC DME1737 Super IO", + # The DME1737 shows up twice in this list because it can return either + # 0x78 or 0x77 as its device ID. + # Hardware monitoring features are accessed on the SMBus + driver => "via-smbus-only", + devid => 0x77, + }, { + name => "SMSC EMC2700LPC Super IO", + # no datasheet + devid => 0x67, + }, { + name => "SMSC FDC37B72x Super IO", + driver => "not-a-sensor", + devid => 0x4c, + }, { + name => "SMSC FDC37B78x Super IO", + driver => "not-a-sensor", + devid => 0x44, + }, { + name => "SMSC FDC37C672 Super IO", + driver => "not-a-sensor", + devid => 0x40, + }, { + name => "SMSC FDC37M707 Super IO", + driver => "not-a-sensor", + devid => 0x42, + }, { + name => "SMSC FDC37M81x Super IO", + driver => "not-a-sensor", + devid => 0x4d, + }, { + name => "SMSC LPC47B27x Super IO Fan Sensors", + driver => "smsc47m1", + devid => 0x51, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47B34x Super IO", + driver => "not-a-sensor", + devid => 0x56, + }, { + name => "SMSC LPC47B357/M967 Super IO", + driver => "not-a-sensor", + devid => 0x5d, + }, { + name => "SMSC LPC47B367-NC Super IO", + driver => "not-a-sensor", + devid => 0x6d, + }, { + name => "SMSC LPC47B37x Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x52, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47B397-NC Super IO", + driver => "smsc47b397", + devid => 0x6f, + logdev => 0x08, + features => FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC LPC47M10x/112/13x Super IO Fan Sensors", + driver => "smsc47m1", + devid => 0x59, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47M14x Super IO Fan Sensors", + driver => "smsc47m1", + devid => 0x5f, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47M15x/192/997 Super IO Fan Sensors", + driver => "smsc47m1", + devid => 0x60, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47M172 Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x14, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47M182 Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x74, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47M233 Super IO Sensors", + driver => "to-be-written", + devid => 0x6b80, + devid_mask => 0xff80, + logdev => 0x0a, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC LPC47M292 Super IO Fan Sensors", + driver => "smsc47m1", + devid => 0x6b00, + devid_mask => 0xff80, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47M584-NC Super IO", + # No datasheet (Dell-specific part). Not compatible with + # smsc47m1 nor dme1737 nor LPC47M233. No evidence that this + # chip can do any hardware monitoring at all. + driver => "not-a-sensor", + devid => 0x76, + }, { + name => "SMSC LPC47N252 Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x0e, + logdev => 0x09, + features => FEAT_FAN, + }, { + name => "SMSC LPC47S42x Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x57, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47S45x Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x62, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47U32x Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x58, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC LPC47U33x Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x54, + logdev => 0x0a, + features => FEAT_FAN, + }, { + name => "SMSC SCH3112 Super IO", + driver => "dme1737", + devid => 0x7c, + logdev => 0x0a, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC SCH3114 Super IO", + driver => "dme1737", + devid => 0x7d, + logdev => 0x0a, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC SCH3116 Super IO", + driver => "dme1737", + devid => 0x7f, + logdev => 0x0a, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC SCH4307 Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x90, + logdev => 0x08, + features => FEAT_FAN, + }, { + name => "SMSC SCH5027D-NW Super IO", + # Hardware monitoring features are accessed on the SMBus + driver => "via-smbus-only", + devid => 0x89, + }, { + name => "SMSC SCH5127 Super IO", + driver => "dme1737", + devid => 0x86, + logdev => 0x0a, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC SCH5307-NS Super IO", + driver => "smsc47b397", + devid => 0x81, + logdev => 0x08, + features => FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC SCH5317 Super IO", + driver => "smsc47b397", + devid => 0x85, + logdev => 0x08, + features => FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC SCH5317 Super IO", + # The SCH5317 shows up twice in this list because it can return either + # 0x85 or 0x8c as its device ID. + driver => "smsc47b397", + devid => 0x8c, + logdev => 0x08, + features => FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC SCH5504-NS Super IO", + # No datasheet + driver => "not-a-sensor", + devid => 0x79, + }, { + name => "SMSC SCH5514D-NS Super IO", + # No datasheet + driver => "not-a-sensor", + devid => 0x83, + }, { + name => "SMSC SCH5627 Super IO", + driver => "sch5627", + devid => 0xc6, + regs => { + basereg_lsb => 0x66, + basereg_msb => 0x67, + }, + logdev => 0x0c, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "SMSC SCH5636 Super IO", + driver => "sch5636", + devid => 0xc7, + regs => { + basereg_lsb => 0x66, + basereg_msb => 0x67, + }, + logdev => 0x0c, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + } +); + +# Non-standard SMSC chip list. These chips differ from the standard ones +# listed above in that the device ID register address is 0x0d instead of +# 0x20 (as specified by the ISA PNP spec). +@superio_ids_smsc_ns = ( + { + name => "SMSC FDC37C665 Super IO", + driver => "not-a-sensor", + devid => 0x65, + }, { + name => "SMSC FDC37C666 Super IO", + driver => "not-a-sensor", + devid => 0x66, + }, { + name => "SMSC FDC37C669 Super IO", + driver => "not-a-sensor", + devid => 0x03, + }, { + name => "SMSC FDC37N769 Super IO", + driver => "not-a-sensor", + devid => 0x28, + }, { + name => "SMSC LPC47N217 Super IO", + driver => "not-a-sensor", + devid => 0x7a, + }, { + name => "SMSC LPC47N227 Super IO", + driver => "not-a-sensor", + devid => 0x5a, + }, { + name => "SMSC LPC47N237 Super IO", + driver => "not-a-sensor", + devid => 0x13, + }, { + name => "SMSC SIO10N268 Notebook IO", + driver => "not-a-sensor", + devid => 0x5b, + } +); + +@superio_ids_winbond = ( + { + name => "VIA VT1211 Super IO Sensors", + driver => "vt1211", + devid => 0x3c, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "VIA VT1212 Super IO Lite", # in 100 pin TQFP package + driver => "not-a-sensor", + devid => 0x3e, + }, { + name => "VIA VT1212 Super IO Lite", # in 48 pin LQFP package + driver => "not-a-sensor", + devid => 0x3f, + }, { + name => "Winbond W83627HF/F/HG/G Super IO Sensors", + # Also SMSC LPC61W492 + driver => "w83627hf", + devid => 0x52, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83627SF/GF Super IO", + driver => "not-a-sensor", + devid => 0x59, + }, { + name => "Winbond W83627THF/THG Super IO Sensors", + driver => "w83627hf", + devid => 0x82, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83637HF/HG Super IO Sensors", + driver => "w83627hf", + devid => 0x70, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83687THF Super IO Sensors", + driver => "w83627hf", + devid => 0x85, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83697HF/F/HG Super IO Sensors", + driver => "w83627hf", + devid => 0x60, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83697SF/UF/UG Super IO PWM", + driver => "to-be-written", + devid => 0x68, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83627EHF/EF/EHG/EG Super IO Sensors", + driver => "w83627ehf", + # W83627EHF datasheet says 0x886x but 0x8853 was seen, thus the + # broader mask. W83627EHG was seen with ID 0x8863. + devid => 0x8840, + devid_mask => 0xFFC0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83627DHG Super IO Sensors", + driver => "w83627ehf", + devid => 0xA020, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83627DHG-P/W83527HG Super IO Sensors", + driver => "w83627ehf", + devid => 0xB070, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83627UHG/NCT6627UD Super IO Sensors", + driver => "w83627ehf", + devid => 0xA230, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83667HG Super IO Sensors", + driver => "w83627ehf", + devid => 0xA510, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton NCT6681D/NCT6682D eSIO", + driver => "to-be-written", + devid => 0xB270, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton W83667HG-B (NCT5571D) Super IO Sensors", + driver => "w83627ehf", + devid => 0xB350, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton W83677HG-I (NCT5572D/NCT6771F/NCT6772F/NCT6775F) Super IO Sensors", + driver => "w83627ehf", + devid => 0xB470, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Winbond W83L517D Super IO", + driver => "not-a-sensor", + devid => 0x61, + }, { + name => "Nuvoton NCT5573D/NCT5577D/NCT6776F Super IO Sensors", + driver => "nct6775", + devid => 0xC330, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton NCT5532D/NCT6779D Super IO Sensors", + driver => "nct6775", + devid => 0xC560, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton NCT6683D eSIO", + driver => "nct6683", + devid => 0xC730, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton NCT6791D Super IO Sensors", + driver => "nct6775", + devid => 0xC800, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton NCT6792D Super IO Sensors", + driver => "nct6775", + devid => 0xC910, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton NCT6793D Super IO Sensors", + driver => "nct6775", + devid => 0xD120, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton NCT6795D Super IO Sensors", + driver => "nct6775", + devid => 0xD350, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton NCT6796D Super IO Sensors", + driver => "nct6775", + devid => 0xD420, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Nuvoton NCT6102D/NCT6104D/NCT6106D Super IO Sensors", + driver => "nct6775", + devid => 0xC450, + devid_mask => 0xFFF0, + logdev => 0x0b, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71805F/FG Super IO Sensors", + driver => "f71805f", + devid => 0x0406, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71808E Super IO Sensors", + driver => "f71882fg", + devid => 0x0901, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71808A Super IO Sensors", + driver => "f71882fg", + devid => 0x1001, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71862FG Super IO Sensors", + driver => "f71882fg", + devid => 0x0601, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71868A Super IO Sensors", + driver => "f71882fg", + devid => 0x1106, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71869F/E Super IO Sensors", + driver => "f71882fg", + devid => 0x0814, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71869A Super IO Sensors", + driver => "f71882fg", + devid => 0x1007, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71806FG/F71872FG Super IO Sensors", + driver => "f71805f", + devid => 0x0341, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71858DG Super IO Sensors", + driver => "f71882fg", + devid => 0x0507, + logdev => 0x02, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71882FG/F71883FG Super IO Sensors", + driver => "f71882fg", + devid => 0x0541, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71889FG/F81801U Super IO Sensors", + driver => "f71882fg", + devid => 0x0723, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71889ED Super IO Sensors", + driver => "f71882fg", + devid => 0x0909, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F71889A Super IO Sensors", + driver => "f71882fg", + devid => 0x1005, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F81216D Super IO", + driver => "not-a-sensor", + devid => 0x0208, + }, { + name => "Fintek F81218D Super IO", + driver => "not-a-sensor", + devid => 0x0206, + }, { + name => "Fintek F81768D Super IO Sensors", + driver => "f71882fg", + devid => 0x1210, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F81865F Super IO Sensors", + driver => "f71882fg", + devid => 0x0704, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Fintek F81866D Super IO Sensors", + driver => "f71882fg", + devid => 0x1010, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "Asus F8000 Super IO", + driver => "f71882fg", + devid => 0x0581, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + # Shouldn't be in this family, but seems to be still. + name => "ITE IT8708F Super IO", + driver => "not-a-sensor", + devid => 0x8708, + }, { + # Shouldn't be in this family, but seems to be still. + name => "ITE IT8710F Super IO", + driver => "not-a-sensor", + devid => 0x8710, + } +); + +@superio_ids_ite = ( + { + name => "ITE IT8603E Super IO Sensors", + driver => "it87", + devid => 0x8603, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8606E Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8606, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8607E Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8607, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8613E Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8613, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8620E Super IO Sensors", + driver => "it87", + devid => 0x8620, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8622E Super IO Sensors", + driver => "it87", + devid => 0x8622, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8623E Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8623, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8625E Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8625, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8626E Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8626, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8655E Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8655, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8665E Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8665, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8686E Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8686, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8702F Super IO Fan Sensors", + driver => "to-be-written", + devid => 0x8702, + logdev => 0x04, + features => FEAT_FAN, + }, { + name => "ITE IT8705F Super IO Sensors", + driver => "it87", + devid => 0x8705, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8712F Super IO Sensors", + driver => "it87", + devid => 0x8712, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8716F Super IO Sensors", + driver => "it87", + devid => 0x8716, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8718F Super IO Sensors", + driver => "it87", + devid => 0x8718, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8720F Super IO Sensors", + driver => "it87", + devid => 0x8720, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8721F/IT8758E Super IO Sensors", + driver => "it87", + devid => 0x8721, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8726F Super IO Sensors", + driver => "it87", + devid => 0x8726, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8728F Super IO Sensors", + driver => "it87", + devid => 0x8728, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8731F Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8731, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8732F Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8732, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8752F Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8752, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8771E Super IO Sensors", + driver => "it87", + devid => 0x8771, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8772E Super IO Sensors", + driver => "it87", + devid => 0x8772, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8780F Super IO Sensors", + driver => "to-be-written", # it87 + devid => 0x8780, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8781F Super IO Sensors", + driver => "it87", + devid => 0x8781, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8782F Super IO Sensors", + driver => "it87", + devid => 0x8782, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8783F Super IO Sensors", + driver => "it87", + devid => 0x8783, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8786E Super IO Sensors", + driver => "it87", + devid => 0x8786, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8790E Super IO Sensors", + driver => "it87", + devid => 0x8790, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8792E Super IO Sensors", + driver => "it87", + devid => 0x8733, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + }, { + name => "ITE IT8987D Embedded Controller", + driver => "to-be-written", + devid => 0x8987, + logdev => 0x04, + features => FEAT_IN | FEAT_FAN | FEAT_TEMP, + } +); + +# Entries are grouped by family. Each family entry has the following fields: +# family: The family name +# guess (optional): Typical logical device address. This lets us do +# generic probing if we fail to recognize the chip. +# enter: The password sequence to write to the address register +# chips: Array of chips +# The order of families matters, because we stop as soon as one family +# succeeds. So we have to list families with shorter password sequences +# first. +@superio_ids = ( + { + family => "National Semiconductor/ITE", + enter => + { + 0x2e => [], + 0x4e => [], + }, + chips => \@superio_ids_natsemi, + }, { + family => "SMSC", + enter => + { + 0x2e => [0x55], + 0x4e => [0x55], + }, + chips => \@superio_ids_smsc, + ns_detect => \&smsc_ns_detect_superio, + ns_chips => \@superio_ids_smsc_ns, + }, { + family => "VIA/Winbond/Nuvoton/Fintek", + guess => 0x290, + enter => + { + 0x2e => [0x87, 0x87], + 0x4e => [0x87, 0x87], + }, + chips => \@superio_ids_winbond, + }, { + family => "ITE", + guess => 0x290, + enter => + { + 0x2e => [0x87, 0x01, 0x55, 0x55], + 0x4e => [0x87, 0x01, 0x55, 0xaa], + }, + chips => \@superio_ids_ite, + } +); + +# Drivers for bridge, CPU and memory embedded sensors +# Each entry must have the following fields: +# name: The device name +# driver: The driver name. Put "to-be-written" if no driver is available. +# detect: Detection callback function. No parameter will be passed to +# this function, it must use global lists of PCI devices, CPU, +# etc. It must return a confidence value, undef if no supported +# CPU is found. +use vars qw(@cpu_ids); + +@cpu_ids = ( + { + name => "Silicon Integrated Systems SIS5595", + driver => "sis5595", + detect => \&sis5595_pci_detect, + }, { + name => "VIA VT82C686 Integrated Sensors", + driver => "via686a", + detect => \&via686a_pci_detect, + }, { + name => "VIA VT8231 Integrated Sensors", + driver => "vt8231", + detect => \&via8231_pci_detect, + }, { + name => "AMD K8 thermal sensors", + driver => "k8temp", + detect => sub { amd_pci_detect('1103') }, + }, { + name => "AMD Family 10h thermal sensors", + driver => "k10temp", + detect => \&fam10h_pci_detect, + }, { + name => "AMD Family 11h thermal sensors", + driver => "k10temp", + detect => sub { amd_pci_detect('1303') }, + }, { + name => "AMD Family 12h and 14h thermal sensors", + driver => "k10temp", + detect => sub { amd_pci_detect('1703') }, + }, { + name => "AMD Family 15h thermal sensors", + driver => "k10temp", + detect => sub { amd_pci_detect('1603', '1403', '141d', '1573', '15b3') }, + }, { + name => "AMD Family 16h thermal sensors", + driver => "k10temp", + detect => sub { amd_pci_detect('1533', '1583') }, + }, { + name => "AMD Family 17h thermal sensors", + driver => "k10temp", + detect => sub { amd_pci_detect('1463', '15d0') }, + }, { + name => "AMD Family 15h power sensors", + driver => "fam15h_power", + detect => sub { amd_pci_detect('1604') }, + }, { + name => "AMD Family 16h power sensors", + driver => "fam15h_power", + detect => sub { amd_pci_detect('1534') }, + }, { + name => "Intel digital thermal sensor", + driver => "coretemp", + detect => \&coretemp_detect, + }, { + name => "Intel AMB FB-DIMM thermal sensor", + driver => "i5k_amb", + detect => \&intel_amb_detect, + }, { + name => "Intel 5500/5520/X58 thermal sensor", + driver => "i5500_temp", + detect => \&intel_5500_detect, + }, { + name => "VIA C7 thermal sensor", + driver => "via-cputemp", + detect => \&via_c7_detect, + }, { + name => "VIA Nano thermal sensor", + driver => "via-cputemp", + detect => \&via_nano_detect, + } +); + +####################### +# AUXILIARY FUNCTIONS # +####################### + +# $_[0] is the sought value +# $_[1..] is the list to seek in +# Returns: 1 if found, 0 if not. +sub contains +{ + my $sought = shift; + local $_; + + foreach (@_) { + return 1 if $sought eq $_; + } + return 0; +} + +# Address can be decimal or hexadecimal +sub valid_address +{ + my $value = shift; + + if ($value !~ m/^(0x[0-9a-f]+|[0-9]+)$/i) { + print "$value is not a valid address, sorry.\n"; + exit -1; + } + $value = oct($value) if $value =~ m/^0x/i; + + return $value; +} + +sub parse_not_to_scan +{ + my ($min, $max, $to_parse) = @_; + my @ranges = split /\s*,\s*/, $to_parse; + my @res; + my $range; + + foreach $range (@ranges) { + my ($start, $end) = split /\s*-\s*/, $range; + $start = valid_address($start); + if (defined $end) { + $end = valid_address($end); + if ($end <= $start) { + print "$start-$end is not a valid range, sorry.\n"; + exit -1; + } + $start = $min if $start < $min; + $end = $max if $end > $max; + push @res, ($start..$end); + } else { + push @res, $start if $start >= $min and $start <= $max; + } + } + + return sort { $a <=> $b } @res; +} + +# $_[0]: Reference to list 1 +# $_[1]: Reference to list 2 +# Result: 0 if they have no elements in common, 1 if they have +# Elements must be numeric. +sub any_list_match +{ + my ($list1, $list2) = @_; + my ($el1, $el2); + + foreach $el1 (@$list1) { + foreach $el2 (@$list2) { + return 1 if $el1 == $el2; + } + } + return 0; +} + +# $_[0]: Reference to base hash +# $_[1]: Reference to overlay hash +# Result: Overlayed hash +sub overlay_hash +{ + my ($base, $overlay) = @_; + my %result = %{$base}; + + foreach my $key (keys %{$overlay}) { + $result{$key} = $overlay->{$key}; + } + return %result; +} + +# Read answer from stdin or accept default answer automatically +sub read_answer +{ + if ($opt{auto}) { + print "\n"; + return ""; + } + return || ""; +} + +################### +# I/O PORT ACCESS # +################### + +sub initialize_ioports +{ + if (sysopen(IOPORTS, "/dev/port", O_RDWR)) { + binmode(IOPORTS); + return 1; + } + print STDERR "/dev/port: $!\n"; + return 0; +} + +sub close_ioports +{ + close(IOPORTS); +} + +# $_[0]: port to read +# Returns: -1 on failure, read value on success. +sub inb +{ + my ($res, $nrchars); + sysseek(IOPORTS, $_[0], 0) or return -1; + $nrchars = sysread(IOPORTS, $res, 1); + return -1 if not defined $nrchars or $nrchars != 1; + $res = unpack("C", $res); + return $res; +} + +# $_[0]: port to write +# $_[1]: value to write +# We assume this can't fail. +sub outb +{ + sysseek(IOPORTS, $_[0], 0); + syswrite(IOPORTS, pack("C", $_[1]), 1); +} + +# $_[0]: Address register +# $_[1]: Data register +# $_[2]: Register to read +# Returns: read value +sub isa_read_byte +{ + outb($_[0], $_[2]); + return inb($_[1]); +} + +# $_[0]: Base address +# $_[1]: Register to read +# Returns: read value +# This one can be used for any ISA chip with index register at +# offset 5 and data register at offset 6. +sub isa_read_i5d6 +{ + my ($addr, $reg) = @_; + return isa_read_byte($addr + 5, $addr + 6, $reg); +} + +################# +# AUTODETECTION # +################# + +use vars qw($dev_i2c $sysfs_root $systemd_systemctl $systemd_system_dir); + +sub initialize_conf +{ + my $use_devfs = 0; + open(local *INPUTFILE, "/proc/mounts") or die "Can't access /proc/mounts!"; + local $_; + while () { + if (m@^\w+ /dev devfs @) { + $use_devfs = 1; + $dev_i2c = '/dev/i2c/'; + } + if (m@^\S+ (/\w+) sysfs @) { + $sysfs_root = $1; + } + } + close(INPUTFILE); + + # We need sysfs for many things + if (!defined $sysfs_root) { + print "Sysfs not mounted?\n"; + exit -1; + } + + my $use_udev = 0; + if (open(*INPUTFILE, '/etc/udev/udev.conf')) { + while () { + next unless m/^\s*udev_db\s*=\s*\"([^"]*)\"/ + || m/^\s*udev_db\s*=\s*(\S+)/; + if (-e $1) { + $use_udev = 1; + $dev_i2c = '/dev/i2c-'; + } + last; + } + close(INPUTFILE); + } + + if (!$use_udev) { + # Try some known default udev db locations, just in case + if (-e '/dev/.udev.tdb' || -e '/dev/.udev' + || -e '/dev/.udevdb' || -e '/run/udev') { + $use_udev = 1; + $dev_i2c = '/dev/i2c-'; + } + } + + if (!($use_devfs || $use_udev)) { + if (! -c '/dev/i2c-0' && -x '/sbin/MAKEDEV') { + system("/sbin/MAKEDEV i2c"); + } + if (! -c '/dev/i2c-0' && -x '/dev/MAKEDEV') { + system("/dev/MAKEDEV i2c"); + } + if (-c '/dev/i2c-0') { + $dev_i2c = '/dev/i2c-'; + } else { # default + print "No i2c device files found.\n"; + exit -1; + } + } + + # Detect systemd presence and paths + if (-x "/usr/bin/systemctl") { + $systemd_systemctl = "/usr/bin/systemctl"; + } elsif (-x "/bin/systemctl") { + $systemd_systemctl = "/bin/systemctl"; + } + + if (-d "/usr/lib/systemd/system") { + $systemd_system_dir = "/usr/lib/systemd/system"; + } elsif (-d "/lib/systemd/system") { + $systemd_system_dir = "/lib/systemd/system"; + } +} + +# [0] -> VERSION +# [1] -> PATCHLEVEL +# [2] -> SUBLEVEL +# [3] -> EXTRAVERSION +# +use vars qw($kernel_version @kernel_version $kernel_arch); + +sub initialize_kernel_version +{ + chomp($kernel_version = `uname -r`); + $kernel_version =~ /(\d+)\.(\d+)\.(\d+)(.*)/; + @kernel_version = ($1, $2, $3, $4); + chomp($kernel_arch = `uname -m`); + + # We only support kernels >= 2.6.5 + if (!kernel_version_at_least(2, 6, 5)) { + print "Kernel version is unsupported (too old, >= 2.6.5 needed)\n"; + exit -1; + } +} + +sub print_kernel_version +{ + printf "# Kernel: \%d.\%d.\%d\%s \%s\n", @kernel_version, $kernel_arch; +} + +sub kernel_version_at_least +{ + my ($vers, $plvl, $slvl) = @_; + return 1 if ($kernel_version[0] > $vers || + ($kernel_version[0] == $vers && + ($kernel_version[1] > $plvl || + ($kernel_version[1] == $plvl && + ($kernel_version[2] >= $slvl))))); + return 0; +} + +# @cpu is a list of reference to hashes, one hash per CPU. +# Each entry has the following keys: vendor_id, cpu family, model, +# model name and stepping, directly taken from /proc/cpuinfo. +use vars qw(@cpu); + +sub initialize_cpu_list +{ + local $_; + my $entry; + + open(local *INPUTFILE, "/proc/cpuinfo") or die "Can't access /proc/cpuinfo!"; + while () { + if (m/^processor\s*:\s*(\d+)/) { + push @cpu, $entry if scalar keys(%{$entry}); # Previous entry + $entry = { # New entry + nr => $1, + vendor_id => "undefined", + }; + next; + } + if (m/^(vendor_id|cpu family|model|model name|stepping|cpuid level)\s*:\s*(.+)$/) { + my $k = $1; + my $v = $2; + $v =~ s/\s+/ /g; # Merge multiple spaces + $v =~ s/ $//; # Trim trailing space + $entry->{$k} = $v; + next; + } + } + close(INPUTFILE); + push @cpu, $entry if scalar keys(%{$entry}); # Last entry +} + +sub print_cpu_info +{ + my $cpu = $cpu[0]; + print "# Processor: $cpu->{'model name'} ($cpu->{'cpu family'}/$cpu->{model}/$cpu->{stepping})\n"; +} + +# @i2c_adapters is a list of references to hashes, one hash per I2C/SMBus +# adapter present on the system. Each entry has the following keys: path, +# parent, name (directly taken from sysfs), driver and autoload. +use vars qw(@i2c_adapters); + +# Find out whether the driver would be automatically loaded by the modalias +# mechanism. +sub device_driver_autoloads +{ + my $device = shift; + + my $modalias = sysfs_device_attribute($device, "modalias"); + return 0 unless defined($modalias); + + # At the moment we only handle PCI and USB drivers. Other driver + # types, most notably platform and i2c drivers, do not follow the + # device driver model to the letter, and often create their own + # devices. Such drivers appear to be autoloaded when they are not. + return 0 unless $modalias =~ m/^(pci|usb):/; + + my $result = `modprobe -n -v --first-time $modalias 2>&1`; + return ($result =~ m/^insmod/ || + $result =~ m/\balready in kernel\b/); +} + +sub initialize_i2c_adapters_list +{ + my ($entry, $base_dir, $have_i2c_adapter_class); + local $_; + + if (-d "${sysfs_root}/class/i2c-adapter") { + $base_dir = "${sysfs_root}/class/i2c-adapter"; + $have_i2c_adapter_class = 1; + } else { + $base_dir = "${sysfs_root}/bus/i2c/devices"; + $have_i2c_adapter_class = 0; + } + opendir(local *ADAPTERS, $base_dir) or return; + + while (defined($_ = readdir(ADAPTERS))) { + next unless m/^i2c-(\d+)$/; + my $nr = $1; + $entry = {}; # New entry + + # The layout in sysfs has changed over the years + if ($have_i2c_adapter_class) { + my $link = readlink("${base_dir}/i2c-$nr/device"); + if (!defined $link) { + $entry->{path} = "${base_dir}/i2c-$nr"; + $entry->{parent} = "${base_dir}/i2c-$nr"; + } elsif ($link =~ m/^(.*)\/i2c-$nr$/) { + $entry->{path} = "${base_dir}/i2c-$nr/device"; + $entry->{parent} = "${base_dir}/i2c-$nr/$1"; + } + } + + # This works for all recent kernels (with or without + # CONFIG_I2C_COMPAT) + if (!defined $entry->{path}) { + my $link = readlink("${base_dir}/i2c-$nr"); + $entry->{path} = "${base_dir}/i2c-$nr"; + $link =~ s/(\/i2c-[0-9]+)+$//; # Handle multiplexers too + $entry->{parent} = "${base_dir}/$link"; + } + + $entry->{name} = sysfs_device_attribute($entry->{path}, "name"); + next if $entry->{name} eq "ISA main adapter"; + + # First try to get the I2C adapter driver name from sysfs, + # and if it fails, fall back to searching our list of known + # I2C adapters. + $entry->{driver} = sysfs_device_module($entry->{parent}) + || find_i2c_adapter_driver($entry->{name}) + || 'UNKNOWN'; + + $entry->{autoload} = device_driver_autoloads($entry->{parent}); + $i2c_adapters[$nr] = $entry; + } + closedir(ADAPTERS); +} + +# %hwmon_autoloaded is a list of hwmon drivers which are autoloaded +# (typically by udev.) We don't need to load these drivers ourselves. +use vars qw(%hwmon_autoloaded); + +sub initialize_hwmon_autoloaded +{ + my $class_dir = "${sysfs_root}/class/hwmon"; + opendir(local *HWMON, $class_dir) or return; + + my ($hwmon, $driver); + while (defined($hwmon = readdir(HWMON))) { + next unless $hwmon =~ m/^hwmon\d+$/; + + $driver = sysfs_device_module("${class_dir}/$hwmon/device"); + next unless defined($driver); + + if (device_driver_autoloads("${class_dir}/$hwmon/device")) { + $driver =~ tr/-/_/; + $hwmon_autoloaded{$driver}++ + } + } + closedir(HWMON); +} + +sub hwmon_is_autoloaded +{ + my $driver = shift; + $driver =~ tr/-/_/; + return exists($hwmon_autoloaded{$driver}); +} + +########### +# MODULES # +########### + +use vars qw(%modules_builtin %modules_list %modules_supported @modules_we_loaded); + +sub initialize_modules_list +{ + local ($_, *INPUTFILE); + + # Starting with kernel 2.6.33, a list of built-in modules is available + if (open(*INPUTFILE, "/lib/modules/$kernel_version/modules.builtin")) { + while () { + tr/-/_/; + $modules_builtin{$1} = 1 if m/\/([^\/]+)\.ko$/; + } + close(INPUTFILE); + } + + # List all loaded modules + open(*INPUTFILE, "/proc/modules") or return; + while () { + $modules_list{$1} = 1 if m/^(\S*)/; + } +} + +sub is_module_loaded +{ + my $module = shift; + $module =~ tr/-/_/; + return exists $modules_list{$module} || exists $modules_builtin{$module}; +} + +sub is_module_builtin +{ + my $module = shift; + $module =~ tr/-/_/; + return exists $modules_builtin{$module}; +} + +sub load_module +{ + my $module = shift; + + return if is_module_loaded($module); + + system("modprobe", $module); + if (($? >> 8) != 0) { + print "Failed to load module $module.\n"; + return -1; + } + + print "Module $module loaded successfully.\n"; + push @modules_we_loaded, $module; + + # Update the list of loaded modules + my $normalized = $module; + $normalized =~ tr/-/_/; + $modules_list{$normalized} = 1; +} + +# udev may take some time to create device nodes when loading modules +sub udev_settle +{ + if (!(-x "/sbin/udevadm" && system("/sbin/udevadm settle") == 0) + && !(-x "/sbin/udevsettle" && system("/sbin/udevsettle") == 0)) { + sleep(1); + } +} + +sub initialize_modules_supported +{ + foreach my $chip (@chip_ids) { + next if $chip->{driver} eq "to-be-written"; + next if $chip->{driver} eq "use-isa-instead"; + + my $normalized = $chip->{driver}; + $normalized =~ tr/-/_/; + $modules_supported{$normalized}++; + } +} + +sub unload_modules +{ + return unless @modules_we_loaded; + + # Attempt to unload all kernel drivers we loaded ourselves + while (my $module = pop @modules_we_loaded) { + print "Unloading $module... "; + system("modprobe -r $module 2> /dev/null"); + if (($? >> 8) == 0) { + print "OK\n"; + } else { + print "failed\n"; + } + } + print "\n"; +} + +############ +# DMI DATA # +############ + +use vars qw(%dmi $dmidecode_ok); + +# Returns: 1 if dmidecode is recent enough, 0 if not +# Cache the result in case it is needed again later. +sub check_dmidecode_version +{ + return $dmidecode_ok if defined $dmidecode_ok; + + my $version; + if (open(local *DMIDECODE, "dmidecode --version 2>/dev/null |")) { + $version = ; + close(DMIDECODE); + chomp $version if defined $version; + } + + if (!defined $version + || !($version =~ m/^(\d+).(\d+)$/) + || !(($1 == 2 && $2 >= 7) || $1 > 2)) { + print "# DMI data unavailable, please consider installing dmidecode 2.7\n". + "# or later for better results.\n"; + $dmidecode_ok = 0; + } else { + $dmidecode_ok = 1; + } + + return $dmidecode_ok; +} + +sub initialize_dmi_data +{ + my %items = ( + # sysfs file name => dmidecode string name + sys_vendor => 'system-manufacturer', + product_name => 'system-product-name', + product_version => 'system-version', + board_vendor => 'baseboard-manufacturer', + board_name => 'baseboard-product-name', + board_version => 'baseboard-product-name', + chassis_type => 'chassis-type', + ); + # Many BIOS have broken DMI data, filter it out + my %fake = ( + 'system manufacturer' => 1, + 'system product name' => 1, + 'system name' => 1, + 'system version' => 1, + 'to be filled by o.e.m.' => 1, + ); + my $dmi_id_dir; + + # First try reading the strings from sysfs if available + if (-d ($dmi_id_dir = "$sysfs_root/devices/virtual/dmi/id") # kernel >= 2.6.28 + || -d ($dmi_id_dir = "$sysfs_root/class/dmi/id")) { + foreach my $k (keys %items) { + $dmi{$k} = sysfs_device_attribute($dmi_id_dir, $k); + } + } else { + # Else fallback on calling dmidecode + return unless check_dmidecode_version(); + + foreach my $k (keys %items) { + next unless open(local *DMIDECODE, + "dmidecode -s $items{$k} 2>/dev/null |"); + $dmi{$k} = ; + close(DMIDECODE); + } + } + + # Strip trailing white-space, discard empty field + foreach my $k (keys %dmi) { + if (!defined $dmi{$k}) { + delete $dmi{$k}; + next; + } + $dmi{$k} =~ s/\s*$//; + delete $dmi{$k} if $dmi{$k} eq '' || exists $fake{lc($dmi{$k})}; + } +} + +sub print_dmi_summary +{ + my ($system, $board); + if (defined $dmi{sys_vendor} && defined $dmi{product_name}) { + $system = "$dmi{sys_vendor} $dmi{product_name}"; + } + if (defined $dmi{board_vendor} && defined $dmi{board_name}) { + $board = "$dmi{board_vendor} $dmi{board_name}"; + } + + if (defined $system) { + print "# System: $system"; + print " [$dmi{product_version}]" if defined $dmi{product_version}; + print " (laptop)" if (is_laptop()); + print "\n"; + } + print "# Board: $board\n" if defined $board + && (!defined $system || $system ne $board); +} + +sub dmi_match +{ + my $key = shift; + my $value; + + return unless defined $dmi{$key}; + while (defined ($value = shift)) { + return 1 if $dmi{$key} =~ m/\b$value\b/i; + } + return 0; +} + +sub is_laptop +{ + return 0 unless $dmi{chassis_type}; + return 1 if $dmi{chassis_type} =~ m/(Portable|Laptop|Notebook|Hand Held)/i; + return 1 if $dmi{chassis_type} =~ m/^(8|9|10|11|14)$/; + return 0; +} + +################# +# SYSFS HELPERS # +################# + +# From a sysfs device path, return the module name, or undef +sub sysfs_device_module +{ + my $device = shift; + + my $link = readlink("$device/driver/module"); + return unless defined $link; + return basename($link); +} + +# From a sysfs device path, return the driver name, or undef +sub sysfs_device_driver +{ + my $device = shift; + + my $link = readlink("$device/driver"); + return unless defined $link; + return basename($link); +} + +# From a sysfs device path, return the subsystem name, or undef +sub sysfs_device_subsystem +{ + my $device = shift; + + my $link = readlink("$device/subsystem"); + return unless defined $link; + return basename($link); +} + +# From a sysfs device path and an attribute name, return the attribute +# value, or undef +sub sysfs_device_attribute +{ + my ($device, $attr) = @_; + my $value; + + open(local *FILE, "$device/$attr") or return; + $value = ; + close(FILE); + return unless defined $value; + + chomp($value); + return $value; +} + +############## +# PCI ACCESS # +############## + +use vars qw(%pci_list); + +# This function returns a list of hashes. Each hash has some PCI information: +# 'domain', 'bus', 'slot' and 'func' uniquely identify a PCI device in a +# computer; 'vendid' and 'devid' uniquely identify a type of device. +# 'class' lets us spot unknown SMBus adapters. +sub read_sys_dev_pci +{ + my $devices = shift; + my ($dev, @pci_list); + + opendir(local *DEVICES, "$devices") + or return \@pci_list; + + while (defined($dev = readdir(DEVICES))) { + my %record; + next unless $dev =~ + m/^(?:([\da-f]+):)?([\da-f]+):([\da-f]+)\.([\da-f]+)$/; + + $record{domain} = hex $1; + $record{bus} = hex $2; + $record{slot} = hex $3; + $record{func} = hex $4; + + $record{vendid} = oct sysfs_device_attribute("$devices/$dev", + "vendor"); + $record{devid} = oct sysfs_device_attribute("$devices/$dev", + "device"); + $record{class} = (oct sysfs_device_attribute("$devices/$dev", + "class")) >> 8; + + push @pci_list, \%record; + } + + return \@pci_list; +} + +sub initialize_pci +{ + my $pci_list; + local $_; + + $pci_list = read_sys_dev_pci("$sysfs_root/bus/pci/devices"); + + # Note that we lose duplicate devices at this point, but we don't + # really care. What matters to us is which unique devices are present, + # not how many of each. + %pci_list = map { + sprintf("%04x:%04x", $_->{vendid}, $_->{devid}) => $_ + } @{$pci_list}; +} + +##################### +# ADAPTER DETECTION # +##################### + +# Build and return a PCI device's bus ID +sub pci_busid +{ + my $device = shift; + my $busid; + + $busid = sprintf("\%02x:\%02x.\%x", + $device->{bus}, $device->{slot}, $device->{func}); + $busid = sprintf("\%04x:", $device->{domain}) . $busid + if defined $device->{domain}; + + return $busid; +} + +sub adapter_pci_detection +{ + my ($key, $device, $try, %smbus, $count); + + # Build a list of detected SMBus devices + foreach $key (keys %pci_list) { + $device = $pci_list{$key}; + $smbus{$key}++ + if exists $device->{class} && + ($device->{class} == 0x0c01 || # Access Bus + $device->{class} == 0x0c05); # SMBus + } + + # Loop over the known I2C/SMBus adapters + foreach $try (@pci_adapters) { + $key = sprintf("%04x:%04x", $try->{vendid}, $try->{devid}); + next unless exists $pci_list{$key}; + + $device = $pci_list{$key}; + + if ($try->{driver} eq "to-be-written") { + printf "No known driver for device \%s: \%s\n", + pci_busid($device), $try->{procid}; + } else { + printf "Using driver `\%s' for device \%s: \%s\n", + $try->{driver}, pci_busid($device), + $try->{procid}; + $count++; + load_module($try->{driver}); + } + + # Delete from detected SMBus device list + delete $smbus{$key}; + } + + # Now see if there are unknown SMBus devices left + foreach $key (keys %smbus) { + $device = $pci_list{$key}; + printf "Found unknown SMBus adapter \%04x:\%04x at \%s.\n", + $device->{vendid}, $device->{devid}, pci_busid($device); + } + + print "Sorry, no supported PCI bus adapters found.\n" + unless $count; +} + +# $_[0]: Adapter description as found in sysfs +sub find_i2c_adapter_driver +{ + my $name = shift; + my $entry; + + foreach $entry (@i2c_adapter_names) { + return $entry->{driver} + if $name =~ $entry->{match}; + } +} + +############################# +# I2C AND SMBUS /DEV ACCESS # +############################# + +# This should really go into a separate module/package. + +# These are copied from + +use constant IOCTL_I2C_SLAVE => 0x0703; +use constant IOCTL_I2C_FUNCS => 0x0705; +use constant IOCTL_I2C_SMBUS => 0x0720; + +use constant SMBUS_READ => 1; +use constant SMBUS_WRITE => 0; + +use constant SMBUS_QUICK => 0; +use constant SMBUS_BYTE => 1; +use constant SMBUS_BYTE_DATA => 2; +use constant SMBUS_WORD_DATA => 3; + +use constant I2C_FUNC_SMBUS_QUICK => 0x00010000; +use constant I2C_FUNC_SMBUS_READ_BYTE => 0x00020000; +use constant I2C_FUNC_SMBUS_READ_BYTE_DATA => 0x00080000; + +# Get the i2c adapter's functionalities +# $_[0]: Reference to an opened filehandle +# Returns: -1 on failure, functionality bitfield on success. +sub i2c_get_funcs +{ + my $file = shift; + my $funcs = pack("L", 0); # Allocate space + + ioctl($file, IOCTL_I2C_FUNCS, $funcs) or return -1; + $funcs = unpack("L", $funcs); + + return $funcs; +} + +# Select the device to communicate with through its address. +# $_[0]: Reference to an opened filehandle +# $_[1]: Address to select +# Returns: 0 on failure, 1 on success. +sub i2c_set_slave_addr +{ + my ($file, $addr) = @_; + + # Reset register data cache + @i2c_byte_cache = (); + + $addr += 0; # Make sure it's a number not a string + ioctl($file, IOCTL_I2C_SLAVE, $addr) or return 0; + return 1; +} + +# i2c_smbus_access is based upon the corresponding C function (see +# ). You should not need to call this directly. +# $_[0]: Reference to an opened filehandle +# $_[1]: SMBUS_READ for reading, SMBUS_WRITE for writing +# $_[2]: Command (usually register number) +# $_[3]: Transaction kind (SMBUS_BYTE, SMBUS_BYTE_DATA, etc.) +# $_[4]: Reference to an array used for input/output of data +# Returns: 0 on failure, 1 on success. +# Note that we need to get back to Integer boundaries through the 'x2' +# in the pack. This is very compiler-dependent; I wish there was some other +# way to do this. +sub i2c_smbus_access +{ + my ($file, $read_write, $command, $size, $data) = @_; + my $data_array = pack("C32", @$data); + my $ioctl_data = pack("C2x2Ip", $read_write, $command, $size, + $data_array); + + ioctl($file, IOCTL_I2C_SMBUS, $ioctl_data) or return 0; + @{$_[4]} = unpack("C32", $data_array); + return 1; +} + +# $_[0]: Reference to an opened filehandle +# Returns: -1 on failure, the read byte on success. +sub i2c_smbus_read_byte +{ + my ($file) = @_; + my @data; + + i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE, \@data) + or return -1; + return $data[0]; +} + +# $_[0]: Reference to an opened filehandle +# $_[1]: Command byte (usually register number) +# Returns: -1 on failure, the read byte on success. +# Read byte data values are cached by default. As we keep reading the +# same registers over and over again in the detection functions, and +# SMBus can be slow, caching results in a big performance boost. +sub i2c_smbus_read_byte_data +{ + my ($file, $command, $nocache) = @_; + my @data; + + return $i2c_byte_cache[$command] + if !$nocache && exists $i2c_byte_cache[$command]; + + i2c_smbus_access($file, SMBUS_READ, $command, SMBUS_BYTE_DATA, \@data) + or return -1; + return ($i2c_byte_cache[$command] = $data[0]); +} + +# $_[0]: Reference to an opened filehandle +# $_[1]: Command byte (usually register number) +# Returns: -1 on failure, the read word on success. +# Use this function with care, some devices don't like word reads, +# so you should do as much of the detection as possible using byte reads, +# and only start using word reads when there is a good chance that +# the detection will succeed. +# Note: some devices use the wrong endianness. +sub i2c_smbus_read_word_data +{ + my ($file, $command) = @_; + my @data; + i2c_smbus_access($file, SMBUS_READ, $command, SMBUS_WORD_DATA, \@data) + or return -1; + return $data[0] + 256 * $data[1]; +} + +# $_[0]: Reference to an opened filehandle +# $_[1]: Address +# $_[2]: Functionalities of this i2c adapter +# Returns: 1 on successful probing, 0 else. +# This function is meant to prevent AT24RF08 corruption and write-only +# chips locks. This is done by choosing the best probing method depending +# on the address range. +sub i2c_probe +{ + my ($file, $addr, $funcs) = @_; + + if (($addr >= 0x50 && $addr <= 0x5F) + || ($addr >= 0x30 && $addr <= 0x37)) { + # This covers all EEPROMs we know of, including page protection + # addresses. Note that some page protection addresses will not + # reveal themselves with this, because they ack on write only, + # but this is probably better since some EEPROMs write-protect + # themselves permanently on almost any write to their page + # protection address. + return 0 unless ($funcs & I2C_FUNC_SMBUS_READ_BYTE); + return i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE, []); + } elsif ($addr == 0x73) { + # Special case for FSC chips, as at least the Syleus locks + # up with our regular probe code. Note that to our current + # knowledge only FSC chips live on this address, and for them + # this probe method is safe. + return 0 unless ($funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA); + return i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE_DATA, []); + } else { + return 0 unless ($funcs & I2C_FUNC_SMBUS_QUICK); + return i2c_smbus_access($file, SMBUS_WRITE, 0, SMBUS_QUICK, []); + } +} + +# $_[0]: Reference to an opened file handle +# Returns: 1 if the device is safe to access, 0 else. +# This function is meant to prevent access to 1-register-only devices, +# which are designed to be accessed with SMBus receive byte and SMBus send +# byte transactions (i.e. short reads and short writes) and treat SMBus +# read byte as a real write followed by a read. The device detection +# routines would write random values to the chip with possibly very nasty +# results for the hardware. Note that this function won't catch all such +# chips, as it assumes that reads and writes relate to the same register, +# but that's the best we can do. +sub i2c_safety_check +{ + my ($file) = @_; + my $data; + + # First we receive a byte from the chip, and remember it. + $data = i2c_smbus_read_byte($file); + return 1 if ($data < 0); + + # We receive a byte again; very likely to be the same for + # 1-register-only devices. + return 1 if (i2c_smbus_read_byte($file) != $data); + + # Then we try a standard byte read, with a register offset equal to + # the byte we received; we should receive the same byte value in return. + return 1 if (i2c_smbus_read_byte_data($file, $data) != $data); + + # Then we try a standard byte read, with a slightly different register + # offset; we should again receive the same byte value in return. + return 1 if (i2c_smbus_read_byte_data($file, $data ^ 1) != ($data ^ 1)); + + # Apprently this is a 1-register-only device, restore the original + # register value and leave it alone. + i2c_smbus_read_byte_data($file, $data); + return 0; +} + +#################### +# ADAPTER SCANNING # +#################### + +use vars qw(%chips_detected); + +# We will build a complicated structure %chips_detected here, being a hash +# where keys are driver names and values are detected chip information in +# the form of a list of hashes of type 'detect_data'. + +# Type detect_data: +# A hash +# with field 'i2c_devnr', contianing the /dev/i2c-* number of this +# adapter (if this is an I2C detection) +# with field 'i2c_addr', containing the I2C address of the detection; +# (if this is an I2C detection) +# with field 'i2c_sub_addrs', containing a reference to a list of +# other I2C addresses (if this is an I2C detection) +# with field 'isa_addr' containing the ISA address this chip is on +# (if this is an ISA detection) +# with field 'conf', containing the confidence level of this detection +# with field 'chipname', containing the chip name +# with optional field 'alias_detect', containing a reference to an alias +# detection function for this chip + +# This adds a detection to the above structure. +# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted. +# In all normal cases, it should be all right. +# $_[0]: chip driver +# $_[1]: reference to data hash +# Returns: Nothing +sub add_i2c_to_chips_detected +{ + my ($chipdriver, $datahash) = @_; + my ($i, $detected_ref, $detected_entry, $driver, + $put_in_detected, @hash_addrs, @entry_addrs); + + # Find out whether our new entry should go into the detected list + # or not. We compare all i2c addresses; if at least one matches, + # but our confidence value is lower, we assume this is a misdetection, + # in which case we simply discard our new entry. + @hash_addrs = ($datahash->{i2c_addr}); + push @hash_addrs, @{$datahash->{i2c_sub_addrs}} + if exists $datahash->{i2c_sub_addrs}; + $put_in_detected = 1; + FIND_LOOP: + foreach $detected_ref (values %chips_detected) { + foreach $detected_entry (@{$detected_ref}) { + next unless defined $detected_entry->{i2c_addr}; + @entry_addrs = ($detected_entry->{i2c_addr}); + push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}} + if exists $detected_entry->{i2c_sub_addrs}; + if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} && + any_list_match(\@entry_addrs, \@hash_addrs)) { + if ($detected_entry->{conf} >= $datahash->{conf}) { + $put_in_detected = 0; + } + last FIND_LOOP; + } + } + } + + return unless $put_in_detected; + + # Here, we discard all entries which match at least in one main or + # sub address. This may not be the best idea to do, as it may remove + # detections without replacing them with second-best ones. Too bad. + foreach $driver (keys %chips_detected) { + $detected_ref = $chips_detected{$driver}; + for ($i = @$detected_ref-1; $i >=0; $i--) { + next unless defined $detected_ref->[$i]->{i2c_addr}; + @entry_addrs = ($detected_ref->[$i]->{i2c_addr}); + push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}} + if exists $detected_ref->[$i]->{i2c_sub_addrs}; + if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} && + any_list_match(\@entry_addrs, \@hash_addrs)) { + splice @$detected_ref, $i, 1; + delete $chips_detected{$driver} + if (!@$detected_ref); + } + } + } + + # Now add the new entry to detected + $chips_detected{$chipdriver} = [] + unless exists $chips_detected{$chipdriver}; + push @{$chips_detected{$chipdriver}}, $datahash; +} + +# Fake i2c drivers such as "not-a-sensor" or "use-isa-instead" have to be +# inserted so that confidence comparison can be performed. But then we have +# to filter them out so that the user doesn't get confused. +sub filter_out_fake_i2c_drivers +{ + delete $chips_detected{"not-a-sensor"}; + delete $chips_detected{"use-isa-instead"}; +} + +# This adds a detection to the above structure. +# $_[0]: chip driver +# $_[1]: reference to data hash +sub add_isa_to_chips_detected +{ + my ($chipdriver, $datahash) = @_; + my ($i, $new_detected_ref, $detected_ref); + + # First determine where the hash has to be added. + $chips_detected{$chipdriver} = [] + unless exists $chips_detected{$chipdriver}; + $new_detected_ref = $chips_detected{$chipdriver}; + + # Find out whether our new entry should go into the detected list + # or not. We only compare main isa_addr here, of course. + foreach $detected_ref (values %chips_detected) { + for ($i = 0; $i < @{$detected_ref}; $i++) { + if (exists $detected_ref->[$i]->{isa_addr} and + exists $datahash->{isa_addr} and + $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) { + if ($detected_ref->[$i]->{conf} < $datahash->{conf}) { + splice @$detected_ref, $i, 1; + push @$new_detected_ref, $datahash; + } + return; + } + } + } + + # Not found? OK, put it in the detected list + push @$new_detected_ref, $datahash; +} + +# $_[0]: reference to an array of chips which may be aliases of each other +sub find_aliases +{ + my $detected = shift; + my ($isa, $i2c, $dev, $alias_detect, $is_alias); + + for ($isa = 0; $isa < @{$detected}; $isa++) { + # Look for chips with an ISA address but no I2C address + next unless defined $detected->[$isa]; + next unless $detected->[$isa]->{isa_addr}; + next if defined $detected->[$isa]->{i2c_addr}; + # Additionally, the chip must possibly have I2C aliases + next unless defined $detected->[$isa]->{alias_detect}; + + for ($i2c = 0; $i2c < @{$detected}; $i2c++) { + # Look for chips with an I2C address but no ISA address + next unless defined $detected->[$i2c]; + next unless defined $detected->[$i2c]->{i2c_addr}; + next if $detected->[$i2c]->{isa_addr}; + # Additionally, it must have the same chip name + next unless $detected->[$i2c]->{chipname} eq + $detected->[$isa]->{chipname}; + + # We have potential aliases, check if they actually are + $dev = $dev_i2c.$detected->[$i2c]->{i2c_devnr}; + open(local *FILE, $dev) or + print("Can't open $dev\n"), + next; + binmode(FILE); + i2c_set_slave_addr(\*FILE, $detected->[$i2c]->{i2c_addr}) or + print("Can't set I2C address for $dev\n"), + next; + + if (initialize_ioports()) { + $alias_detect = $detected->[$isa]->{alias_detect}; + $is_alias = &$alias_detect($detected->[$isa]->{isa_addr}, + \*FILE, + $detected->[$i2c]->{i2c_addr}); + close_ioports(); + } + close(FILE); + + next unless $is_alias; + # This is an alias: copy the I2C data into the ISA + # entry, then discard the I2C entry + $detected->[$isa]->{i2c_devnr} = $detected->[$i2c]->{i2c_devnr}; + $detected->[$isa]->{i2c_addr} = $detected->[$i2c]->{i2c_addr}; + $detected->[$isa]->{i2c_sub_addr} = $detected->[$i2c]->{i2c_sub_addr}; + undef $detected->[$i2c]; + last; + } + } + + # The loops above may have made the chip list sparse, make it + # compact again + for ($isa = 0; $isa < @{$detected}; ) { + if (defined($detected->[$isa])) { + $isa++; + } else { + splice @{$detected}, $isa, 1; + } + } +} + +# From the list of known I2C/SMBus devices, build a list of I2C addresses +# which are worth probing. There's no point in probing an address for which +# we don't know a single device, and probing some addresses has caused +# random trouble in the past. +sub i2c_addresses_to_scan +{ + my @used; + my @addresses; + my $addr; + + foreach my $chip (@chip_ids) { + next unless defined $chip->{i2c_addrs}; + foreach $addr (@{$chip->{i2c_addrs}}) { + $used[$addr]++; + } + } + + for ($addr = 0x03; $addr <= 0x77; $addr++) { + push @addresses, $addr if $used[$addr]; + } + return \@addresses; +} + +# $_[0]: The number of the adapter to scan +# $_[1]: Address +sub add_busy_i2c_address +{ + my ($adapter_nr, $addr) = @_; + # If the address is busy, we can normally find out which driver + # requested it (if the kernel is recent enough, at least 2.6.16 and + # later are known to work), and we assume it is the right one. + my ($device, $driver, $module, $new_hash); + + $device = sprintf("$sysfs_root/bus/i2c/devices/\%d-\%04x", + $adapter_nr, $addr); + $driver = sysfs_device_driver($device); + $module = sysfs_device_module($device); + + if (!defined($driver)) { + printf("Client at address 0x%02x can not be probed - ". + "unload all client drivers first!\n", $addr); + return; + } + + $new_hash = { + conf => 6, # Arbitrary confidence + i2c_addr => $addr, + chipname => sysfs_device_attribute($device, "name") + || "unknown", + i2c_devnr => $adapter_nr, + }; + + printf "Client found at address 0x\%02x\n", $addr; + if (defined($module)) { + printf "Handled by driver `\%s' (already loaded), chip type `\%s'\n", + $module, $new_hash->{chipname}; + } else { + printf "Handled by driver `\%s' (built-in), chip type `\%s'\n", + $driver, $new_hash->{chipname}; + # Let's hope that the driver name matches the module name + $module = $driver; + } + + # Only add it to the list if this is something we would have detected, + # else we end up with random i2c chip drivers listed (for example + # media/video drivers.) + if (exists $modules_supported{$module}) { + add_i2c_to_chips_detected($module, $new_hash); + } else { + print " (note: this is probably NOT a sensor chip!)\n"; + } +} + +# $_[0]: The number of the adapter to scan +# $_[1]: Address +# $_[2]: Chip being probed +sub probe_free_i2c_address +{ + my ($adapter_nr, $addr, $chip) = @_; + my ($conf, @other_addr, $new_hash); + + printf("\%-60s", sprintf("Probing for `\%s'... ", $chip->{name})); + if (($conf, @other_addr) = &{$chip->{i2c_detect}} (\*FILE, $addr)) { + if ($chip->{driver} eq "not-a-sensor") { + print "Yes\n", + " (confidence $conf, not a hardware monitoring chip"; + } else { + print "Success!\n", + " (confidence $conf, driver `$chip->{driver}'"; + } + if (@other_addr) { + print ", other addresses:"; + @other_addr = sort @other_addr; + foreach my $other_addr (@other_addr) { + printf(" 0x%02x", $other_addr); + } + } + print ")\n"; + + $new_hash = { + conf => $conf, + i2c_addr => $addr, + chipname => $chip->{name}, + i2c_devnr => $adapter_nr, + }; + if (@other_addr) { + my @other_addr_copy = @other_addr; + $new_hash->{i2c_sub_addrs} = \@other_addr_copy; + } + add_i2c_to_chips_detected($chip->{driver}, $new_hash); + } else { + print "No\n"; + } +} + +# $_[0]: The device to check (PCI or not) +# Returns: PCI class of the adapter if available, 0 if not +sub get_pci_class +{ + my ($device) = @_; + my ($subsystem, $class); + + $subsystem = sysfs_device_subsystem($device); + return 0 unless defined $subsystem; + return 0x0300 if $subsystem eq "drm"; # Graphics card + return 0 unless $subsystem eq "pci"; + + $class = sysfs_device_attribute($device, "class"); + return 0 unless defined $class; + $class = oct($class) if $class =~ /^0/; + return $class >> 8; +} + +# $_[0]: The number of the adapter to scan +sub scan_i2c_adapter +{ + my ($adapter_nr, $smbus_default) = @_; + my ($funcs, $chip, $addr, $class, $default, $input, @not_to_scan); + + $class = get_pci_class($i2c_adapters[$adapter_nr]->{parent}); + # Do not probe adapters on multimedia and graphics cards by default + if (($class & 0xff00) == 0x0400 || ($class & 0xff00) == 0x0300) { + $default = 0; + } elsif ($class == 0x0c01 || $class == 0x0c05 + || find_i2c_adapter_driver($i2c_adapters[$adapter_nr]->{name})) { + $default = $smbus_default; + } else { + $default = 1; + } + + printf "Next adapter: $i2c_adapters[$adapter_nr]->{name} (i2c-$adapter_nr)\n". + "Do you want to scan it? (\%s/selectively): ", + $default ? "YES/no" : "yes/NO"; + + $input = read_answer(); + if ($input =~ /^\s*n/i + || (!$default && $input !~ /^\s*[ys]/i)) { + print "\n"; + return; + } + + if ($input =~ /^\s*s/i) { + print "Please enter one or more addresses not to scan. Separate them with commas.\n", + "You can specify a range by using dashes. Example: 0x58-0x5f,0x69.\n", + "Addresses: "; + $input = read_answer(); + chomp($input); + @not_to_scan = parse_not_to_scan(0x03, 0x77, $input); + } elsif (($class & 0xff00) == 0x0300) { + # Skip EDID and DDC/CI addresses by default on graphics + # adapters. Also skip address 0x4f which was reported in a + # display corruption case. + @not_to_scan = parse_not_to_scan(0x03, 0x77, "0x37, 0x50-0x57, 0x4f"); + } + + open(local *FILE, "$dev_i2c$adapter_nr") or + (print "Can't open $dev_i2c$adapter_nr\n"), return; + binmode(FILE); + + # Can we probe this adapter? + $funcs = i2c_get_funcs(\*FILE); + if ($funcs < 0) { + print "Adapter failed to provide its functionalities, skipping.\n"; + return; + } + if (!($funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA))) { + print "Adapter cannot be probed, skipping.\n"; + return; + } + if (~$funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + print "Adapter doesn't support all probing functions.\n", + "Some addresses won't be probed.\n"; + } + + # Now scan each address in turn + foreach $addr (@{$i2c_addresses_to_scan}) { + # As the not_to_scan list is sorted, we can check it fast + shift @not_to_scan # User skipped an address which we didn't intend to probe anyway + while (@not_to_scan and $not_to_scan[0] < $addr); + if (@not_to_scan and $not_to_scan[0] == $addr) { + shift @not_to_scan; + next; + } + + if (!i2c_set_slave_addr(\*FILE, $addr)) { + add_busy_i2c_address($adapter_nr, $addr); + next; + } + + next unless i2c_probe(\*FILE, $addr, $funcs); + printf "Client found at address 0x%02x\n", $addr; + if (!i2c_safety_check(\*FILE)) { + print "Seems to be a 1-register-only device, skipping.\n"; + next; + } + + $| = 1; + foreach $chip (@chip_ids, @non_hwmon_chip_ids) { + next unless exists $chip->{i2c_addrs} + && contains($addr, @{$chip->{i2c_addrs}}); + probe_free_i2c_address($adapter_nr, $addr, $chip); + } + $| = 0; + } + print "\n"; +} + +sub scan_isa_bus +{ + my $chip_list_ref = shift; + my ($chip, $addr, $conf); + + $| = 1; + foreach $chip (@{$chip_list_ref}) { + next if not exists $chip->{isa_addrs} or not exists $chip->{isa_detect}; + foreach $addr (@{$chip->{isa_addrs}}) { + printf("\%-60s", sprintf("Probing for `\%s' at 0x\%x... ", + $chip->{name}, $addr)); + $conf = &{$chip->{isa_detect}} ($addr); + print("No\n"), next if not defined $conf; + print "Success!\n"; + printf " (confidence %d, driver `%s')\n", $conf, $chip->{driver}; + my $new_hash = { + conf => $conf, + isa_addr => $addr, + chipname => $chip->{name}, + alias_detect => $chip->{alias_detect}, + }; + add_isa_to_chips_detected($chip->{driver}, $new_hash); + } + } + $| = 0; +} + +use vars qw(%standard_superio); + +# The following are taken from the PNP ISA spec (so it's supposed +# to be common to all Super I/O chips): +# devidreg: The device ID register(s) +# logdevreg: The logical device register +# actreg: The activation register within the logical device +# actmask: The activation bit in the activation register +# basereg_*: The I/O base registers within the logical device +%standard_superio = ( + devidreg => 0x20, + logdevreg => 0x07, + actreg => 0x30, + actmask => 0x01, + basereg_msb => 0x60, + basereg_lsb => 0x61, +); + +sub exit_superio +{ + my ($addrreg, $datareg) = @_; + + # Some chips (SMSC, Winbond) want this + outb($addrreg, 0xaa); + + # Return to "Wait For Key" state (PNP-ISA spec) + outb($addrreg, 0x02); + outb($datareg, 0x02); +} + +# Guess if an unknown Super-I/O chip has sensors +sub guess_superio_ld +{ + my ($addrreg, $datareg, $typical_addr) = @_; + my ($oldldn, $ldn, $addr); + + # Save logical device number + outb($addrreg, $standard_superio{logdevreg}); + $oldldn = inb($datareg); + + for ($ldn = 0; $ldn < 16; $ldn++) { + # Select logical device + outb($addrreg, $standard_superio{logdevreg}); + outb($datareg, $ldn); + + # Read base I/O address + outb($addrreg, $standard_superio{basereg_msb}); + $addr = inb($datareg) << 8; + outb($addrreg, $standard_superio{basereg_lsb}); + $addr |= inb($datareg); + next unless ($addr & 0xfff8) == $typical_addr; + + printf " (logical device \%X has address 0x\%x, could be sensors)\n", + $ldn, $addr; + last; + } + + # Be nice, restore original logical device + outb($addrreg, $standard_superio{logdevreg}); + outb($datareg, $oldldn); +} + +# Returns: features bitmask if device added to chips_detected, 0 if not +sub probe_superio +{ + my ($addrreg, $datareg, $chip) = @_; + my ($val, $addr); + my %superio; + + # Use chip-specific registers if provided + if (exists $chip->{regs}) { + %superio = overlay_hash(\%standard_superio, $chip->{regs}); + } else { + %superio = %standard_superio; + } + + if (exists $chip->{check}) { + return 0 unless $chip->{check}($addrreg, $datareg); + } + + printf "\%-60s", "Found `$chip->{name}'"; + + # Does it have hardware monitoring capabilities? + if (!exists $chip->{driver}) { + print "\n (no information available)\n"; + return 0; + } + if ($chip->{driver} eq "not-a-sensor") { + print "\n (no hardware monitoring capabilities)\n"; + return 0; + } + if ($chip->{driver} eq "via-smbus-only") { + print "\n (hardware monitoring capabilities accessible via SMBus only)\n"; + return FEAT_SMBUS; + } + if (!exists $chip->{logdev}) { + print "\n (no support yet)\n"; + return 0; + } + + # Switch to the sensor logical device + outb($addrreg, $superio{logdevreg}); + outb($datareg, $chip->{logdev}); + + # Get the IO base address + outb($addrreg, $superio{basereg_msb}); + $addr = inb($datareg); + outb($addrreg, $superio{basereg_lsb}); + $addr = ($addr << 8) | inb($datareg); + + # Check the activation register and base address + outb($addrreg, $superio{actreg}); + $val = inb($datareg); + if (!($val & $superio{actmask})) { + if ($addr && $addr != 0xffff) { + printf "\n (address 0x\%x, but not activated)\n", $addr; + } else { + print "\n (but not activated)\n"; + } + return 0; + } + if ($addr == 0 || $addr == 0xffff) { + print "\n (but no address specified)\n"; + return 0; + } + + print "Success!\n"; + printf " (address 0x\%x, driver `%s')\n", $addr, $chip->{driver}; + my $new_hash = { + conf => 9, + isa_addr => $addr, + chipname => $chip->{name} + }; + add_isa_to_chips_detected($chip->{driver}, $new_hash); + return $chip->{features}; +} + +# Detection routine for non-standard SMSC Super I/O chips +# $_[0]: Super I/O LPC config/index port +# $_[1]: Super I/O LPC data port +# $_[2]: Reference to array of non-standard chips +# Return values: 1 if non-standard chip found, 0 otherwise +sub smsc_ns_detect_superio +{ + my ($addrreg, $datareg, $ns_chips) = @_; + my ($val, $chip); + + # read alternate device ID register + outb($addrreg, 0x0d); + $val = inb($datareg); + return 0 if $val == 0x00 || $val == 0xff; + + print "Yes\n"; + + foreach $chip (@{$ns_chips}) { + if ($chip->{devid} == $val) { + probe_superio($addrreg, $datareg, $chip); + return 1; + } + } + + printf("Found unknown non-standard chip with ID 0x%02x\n", $val); + return 1; +} + +# Returns: features supported by the device added, if any +sub scan_superio +{ + my ($addrreg, $datareg) = @_; + my ($val, $found); + my $features = 0; + + printf("Probing for Super-I/O at 0x\%x/0x\%x\n", $addrreg, $datareg); + + $| = 1; + # reset state to avoid false positives + exit_superio($addrreg, $datareg); + foreach my $family (@superio_ids) { + printf("\%-60s", "Trying family `$family->{family}'... "); + # write the password + foreach $val (@{$family->{enter}->{$addrreg}}) { + outb($addrreg, $val); + } + # call the non-standard detection routine first if it exists + if (defined($family->{ns_detect}) && + &{$family->{ns_detect}}($addrreg, $datareg, $family->{ns_chips})) { + last; + } + + # did it work? + outb($addrreg, $standard_superio{devidreg}); + $val = inb($datareg); + outb($addrreg, $standard_superio{devidreg} + 1); + $val = ($val << 8) | inb($datareg); + if ($val == 0x0000 || $val == 0xffff) { + print "No\n"; + next; + } + print "Yes\n"; + + $found = 0; + foreach my $chip (@{$family->{chips}}) { + if (($chip->{devid} > 0xff && + ($val & ($chip->{devid_mask} || 0xffff)) == $chip->{devid}) + || ($chip->{devid} <= 0xff && + ($val >> 8) == $chip->{devid})) { + $features |= probe_superio($addrreg, $datareg, $chip); + $found++; + } + } + + if (!$found) { + printf("Found unknown chip with ID 0x%04x\n", $val); + # Guess if a logical device could correspond to sensors + guess_superio_ld($addrreg, $datareg, $family->{guess}) + if defined $family->{guess}; + } + last; + } + exit_superio($addrreg, $datareg); + $| = 0; + return $features; +} + +sub scan_cpu +{ + my $entry = shift; + my $confidence; + + printf("\%-60s", "$entry->{name}... "); + if (defined ($confidence = $entry->{detect}())) { + print "Success!\n"; + printf " (driver `%s')\n", $entry->{driver}; + my $new_hash = { + conf => $confidence, + chipname => $entry->{name}, + }; + add_isa_to_chips_detected($entry->{driver}, $new_hash); + } else { + print "No\n"; + } +} + +################## +# CHIP DETECTION # +################## + +# This routine allows you to dynamically update the chip detection list. +# The most common use is to allow for different chip to driver mappings +# based on different linux kernels +sub chip_special_cases +{ + # Some chip to driver mappings depend on the environment + foreach my $chip (@chip_ids) { + if (ref($chip->{driver}) eq 'CODE') { + $chip->{driver} = $chip->{driver}->(); + } + } + + # Also fill the fake driver name of non-hwmon chips + foreach my $chip (@non_hwmon_chip_ids) { + $chip->{driver} = "not-a-sensor"; + } +} + +# Each function returns a confidence value. The higher this value, the more +# sure we are about this chip. This may help overrule false positives, +# although we also attempt to prevent false positives in the first place. + +# Each function returns a list. The first element is the confidence value; +# Each element after it is an SMBus address. In this way, we can detect +# chips with several SMBus addresses. The SMBus address for which the +# function was called is never returned. + +# All I2C detection functions below take at least 2 parameters: +# $_[0]: Reference to the file descriptor to access the chip +# $_[1]: Address +# Some of these functions which can detect more than one type of device, +# take a third parameter: +# $_[2]: Chip to detect + +# Registers used: 0x58 +sub mtp008_detect +{ + my ($file, $addr) = @_; + return if i2c_smbus_read_byte_data($file, 0x58) != 0xac; + return 3; +} + +# Chip to detect: 0 = LM78, 2 = LM79 +# Registers used: +# 0x40: Configuration +# 0x48: Full I2C Address +# 0x49: Device ID +sub lm78_detect +{ + my ($file, $addr, $chip) = @_; + my $reg; + + return unless i2c_smbus_read_byte_data($file, 0x48) == $addr; + return unless (i2c_smbus_read_byte_data($file, 0x40) & 0x80) == 0x00; + + $reg = i2c_smbus_read_byte_data($file, 0x49); + return if $chip == 0 && ($reg != 0x00 && $reg != 0x20 && $reg != 0x40); + return if $chip == 2 && ($reg & 0xfe) != 0xc0; + + # Explicitly prevent misdetection of Winbond chips + $reg = i2c_smbus_read_byte_data($file, 0x4f); + return if $reg == 0xa3 || $reg == 0x5c; + + return 6; +} + +# Chip to detect: 0 = LM75, 1 = DS75, 2 = LM75A +# Registers used: +# 0x00: Temperature +# 0x01: Configuration +# 0x02: Hysteresis +# 0x03: Overtemperature Shutdown +# 0x04-0x07: No registers +# 0x07: Device ID (LM75A only) +# The first detection step is based on the fact that the LM75 has only +# four registers, and cycles addresses over 8-byte boundaries. We use the +# 0x04-0x07 addresses (unused) to improve the reliability. These are not +# real registers and will always return the last returned value. This isn't +# documented. +# Note that register 0x00 may change, so we can't use the modulo trick on it. +# The DS75 is a bit different, it doesn't cycle over 8-byte boundaries, and +# all register addresses from 0x04 to 0x0f behave like 0x04-0x07 do for +# the LM75. +# And the LM75A is again different, it cycles over 8-byte boundaries, but +# registers 0x04-0x06 return 0xff. Thankfully it has a device ID register +# at 0x07. +# Not all devices enjoy SMBus read word transactions, so we use read byte +# transactions even for the 16-bit registers. The low bits aren't very +# useful for detection anyway. +sub lm75_detect +{ + my ($file, $addr, $chip) = @_; + my $i; + my $cur = i2c_smbus_read_byte_data($file, 0x00); + my $conf = i2c_smbus_read_byte_data($file, 0x01); + my ($maxreg, $hyst, $os, $dev_id); + + if ($chip == 2) { # LM75A + $dev_id = i2c_smbus_read_byte_data($file, 0x07); + return if $dev_id != 0xA1; + + $hyst = i2c_smbus_read_byte_data($file, 0x02); + $os = i2c_smbus_read_byte_data($file, 0x03); + + for $i (0x04 .. 0x06) { + return if i2c_smbus_read_byte_data($file, $i) != 0xff; + } + } else { # LM75 or DS75 + $maxreg = $chip == 1 ? 0x0f : 0x07; + $hyst = i2c_smbus_read_byte_data($file, 0x02, NO_CACHE); + for $i (0x04 .. $maxreg) { + return if i2c_smbus_read_byte_data($file, $i, NO_CACHE) != $hyst; + } + + $os = i2c_smbus_read_byte_data($file, 0x03, NO_CACHE); + for $i (0x04 .. $maxreg) { + return if i2c_smbus_read_byte_data($file, $i, NO_CACHE) != $os; + } + } + + if ($chip != 1) { # LM75 or LM75A + for ($i = 8; $i <= 248; $i += 40) { + return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf + or i2c_smbus_read_byte_data($file, $i + 0x02) != $hyst + or i2c_smbus_read_byte_data($file, $i + 0x03) != $os; + return if $chip == 2 + and i2c_smbus_read_byte_data($file, $i + 0x07) != $dev_id; + } + } + + # All registers hold the same value, obviously a misdetection + return if $conf == $cur and $cur == $hyst and $cur == $os; + + # Unused bits + return if $chip != 1 and ($conf & 0xe0); + return if $chip == 1 and ($conf & 0x80); + + # Most probable value ranges + return 6 if $cur <= 100 and ($hyst >= 10 && $hyst <= 125) + and ($os >= 20 && $os <= 127) and $hyst < $os; + return 3; +} + +# Registers used: +# 0x00: Temperature +# 0x01: Configuration +# 0x02: High Limit +# 0x03: Low Limit +# 0x04: Status +# 0x07: Manufacturer ID and Product ID +sub lm73_detect +{ + my ($file, $addr) = @_; + + my $conf = i2c_smbus_read_byte_data($file, 0x01); + my $status = i2c_smbus_read_byte_data($file, 0x04); + + # Bits that always return 0 + return if ($conf & 0x0c) or ($status & 0x10); + + # Test with byte read first to avoid confusing other chips + return if i2c_smbus_read_byte_data($file, 0x07) != 0x01 + or i2c_smbus_read_word_data($file, 0x07) != 0x9001; + + # Make sure the chip supports SMBus read word transactions + my $cur = i2c_smbus_read_word_data($file, 0x00); + return if $cur < 0; + my $high = i2c_smbus_read_word_data($file, 0x02); + return if $high < 0; + my $low = i2c_smbus_read_word_data($file, 0x03); + return if $low < 0; + return if ($cur & 0x0300) or (($high | $low) & 0x1f00); + + return 3; +} + +# Registers used: +# 0x00: Temperature +# 0x01: Configuration +# 0x02: Hysteresis +# 0x03: Overtemperature Shutdown +# 0x04: Low limit +# 0x05: High limit +# 0x06-0x07: No registers +# The first detection step is based on the fact that the LM77 has only +# six registers, and cycles addresses over 8-byte boundaries. We use the +# 0x06-0x07 addresses (unused) to improve the reliability. These are not +# real registers and will always return the last returned value. This isn't +# documented. +# Note that register 0x00 may change, so we can't use the modulo trick on it. +# Not all devices enjoy SMBus read word transactions, so we use read byte +# transactions even for the 16-bit registers at first. We only use read word +# transactions in the end when we are already almost certain that we have an +# LM77 chip. +sub lm77_detect +{ + my ($file, $addr) = @_; + my $i; + my $cur = i2c_smbus_read_byte_data($file, 0x00); + my $conf = i2c_smbus_read_byte_data($file, 0x01); + my $hyst = i2c_smbus_read_byte_data($file, 0x02); + my $os = i2c_smbus_read_byte_data($file, 0x03); + + my $low = i2c_smbus_read_byte_data($file, 0x04, NO_CACHE); + return if i2c_smbus_read_byte_data($file, 0x06, NO_CACHE) != $low; + return if i2c_smbus_read_byte_data($file, 0x07, NO_CACHE) != $low; + + my $high = i2c_smbus_read_byte_data($file, 0x05, NO_CACHE); + return if i2c_smbus_read_byte_data($file, 0x06, NO_CACHE) != $high; + return if i2c_smbus_read_byte_data($file, 0x07, NO_CACHE) != $high; + + for ($i = 8; $i <= 248; $i += 40) { + return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf; + return if i2c_smbus_read_byte_data($file, $i + 0x02) != $hyst; + return if i2c_smbus_read_byte_data($file, $i + 0x03) != $os; + return if i2c_smbus_read_byte_data($file, $i + 0x04) != $low; + return if i2c_smbus_read_byte_data($file, $i + 0x05) != $high; + } + + # All registers hold the same value, obviously a misdetection + return if $conf == $cur and $cur == $hyst + and $cur == $os and $cur == $low and $cur == $high; + + # Unused bits + return if ($conf & 0xe0) + or (($cur >> 4) != 0 && ($cur >> 4) != 0xf) + or (($hyst >> 4) != 0 && ($hyst >> 4) != 0xf) + or (($os >> 4) != 0 && ($os >> 4) != 0xf) + or (($low >> 4) != 0 && ($low >> 4) != 0xf) + or (($high >> 4) != 0 && ($high >> 4) != 0xf); + + # Make sure the chip supports SMBus read word transactions + foreach $i (0x00, 0x02, 0x03, 0x04, 0x05) { + return if i2c_smbus_read_word_data($file, $i) < 0; + } + + return 3; +} + +# Chip to detect: 0 = LM92, 1 = LM76, 2 = MAX6633/MAX6634/MAX6635 +# Registers used: +# 0x01: Configuration (National Semiconductor only) +# 0x02: Hysteresis +# 0x03: Critical Temp +# 0x04: Low Limit +# 0x05: High Limit +# 0x07: Manufacturer ID (LM92 only) +# One detection step is based on the fact that the LM92 and clones have a +# limited number of registers, which cycle modulo 16 address values. +# Note that register 0x00 may change, so we can't use the modulo trick on it. +# Not all devices enjoy SMBus read word transactions, so we use read byte +# transactions even for the 16-bit registers at first. We only use read +# word transactions in the end when we are already almost certain that we +# have an LM92 chip or compatible. +sub lm92_detect +{ + my ($file, $addr, $chip) = @_; + + my $conf = i2c_smbus_read_byte_data($file, 0x01); + my $hyst = i2c_smbus_read_byte_data($file, 0x02); + my $crit = i2c_smbus_read_byte_data($file, 0x03); + my $low = i2c_smbus_read_byte_data($file, 0x04); + my $high = i2c_smbus_read_byte_data($file, 0x05); + + return if $conf == 0 and $hyst == 0 and $crit == 0 + and $low == 0 and $high == 0; + + # Unused bits + return if ($chip == 0 || $chip == 1) + and ($conf & 0xE0); + + for (my $i = 0; $i <= 240; $i += 16) { + return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf; + return if i2c_smbus_read_byte_data($file, $i + 0x02) != $hyst; + return if i2c_smbus_read_byte_data($file, $i + 0x03) != $crit; + return if i2c_smbus_read_byte_data($file, $i + 0x04) != $low; + return if i2c_smbus_read_byte_data($file, $i + 0x05) != $high; + } + + return if $chip == 0 + and i2c_smbus_read_word_data($file, 0x07) != 0x0180; + + # Make sure the chip supports SMBus read word transactions + $hyst = i2c_smbus_read_word_data($file, 0x02); + return if $hyst < 0; + $crit = i2c_smbus_read_word_data($file, 0x03); + return if $crit < 0; + $low = i2c_smbus_read_word_data($file, 0x04); + return if $low < 0; + $high = i2c_smbus_read_word_data($file, 0x05); + return if $high < 0; + + foreach my $temp ($hyst, $crit, $low, $high) { + return if $chip == 2 and ($temp & 0x7F00); + return if $chip != 2 and ($temp & 0x0700); + } + + return ($chip == 0) ? 4 : 2; +} + +# Chip to detect: 0 = LM80, 1 = LM96080 +# Registers used: +# 0x00: Configuration register +# 0x02: Interrupt state register +# 0x07: Conversion rate register (LM96080 only) +# 0x2a-0x3d: Limits registers (LM80 only) +# 0x3e: Manufacturer's ID register (LM96080 only) +# 0x3f: Stepping/die revision ID register (LM96080 only) +# The LM80 is easily misdetected since it doesn't provide identification +# registers. So we have to use some tricks: +# - 6-bit addressing, so limits readings modulo 0x40 should be unchanged +# - positive temperature limits +# - limits order correctness +# Hopefully this should limit the rate of false positives, without increasing +# the rate of false negatives. +# Thanks to Lennard Klein for testing on a non-LM80 chip, which was +# previously misdetected, and isn't anymore. For reference, it scored +# a final confidence of 0, and changing from strict limit comparisons +# to loose comparisons did not change the score. +sub lm80_detect +{ + my ($file, $addr, $chip) = @_; + my ($i, $reg); + + return if (i2c_smbus_read_byte_data($file, 0x00) & 0x80) != 0; + return if (i2c_smbus_read_byte_data($file, 0x02) & 0xc0) != 0; + + if ($chip == 0) { + for ($i = 0x2a; $i <= 0x3d; $i++) { + $reg = i2c_smbus_read_byte_data($file, $i); + return if i2c_smbus_read_byte_data($file, $i+0x40) != $reg; + return if i2c_smbus_read_byte_data($file, $i+0x80) != $reg; + return if i2c_smbus_read_byte_data($file, $i+0xc0) != $reg; + } + + # Refine a bit by checking whether limits are in the correct order + # (min> 1) - 4; + # $confidence is now between -4 and 3 + + return unless $confidence > 0; + return $confidence; + } elsif ($chip == 1) { + return if (i2c_smbus_read_byte_data($file, 0x07) & 0xfe) != 0; + return if i2c_smbus_read_byte_data($file, 0x3e) != 0x01; + return if i2c_smbus_read_byte_data($file, 0x3f) != 0x08; + + return 6; + } +} + +# Registers used: +# 0x00: Configuration register +# 0x07: Conversion rate register +# 0x09: Oneshot register +# 0x0a: Shutdown register +# 0x0b: Advanced Configuration register +# 0x0c: Busy Status register +# 0x3e: Manufacturer's ID register +# 0x3f: Stepping/die revision ID register +sub adc128d818_detect +{ + my ($file, $addr) = @_; + + return if i2c_smbus_read_byte_data($file, 0x3e) != 0x01; + return if i2c_smbus_read_byte_data($file, 0x3f) != 0x09; + + return if (i2c_smbus_read_byte_data($file, 0x00) & 0xf4) != 0; + return if (i2c_smbus_read_byte_data($file, 0x07) & 0xfe) != 0; + return if (i2c_smbus_read_byte_data($file, 0x09) & 0xfe) != 0; + return if (i2c_smbus_read_byte_data($file, 0x0a) & 0xfe) != 0; + return if (i2c_smbus_read_byte_data($file, 0x0b) & 0xf8) != 0; + return if (i2c_smbus_read_byte_data($file, 0x0c) & 0xfc) != 0; + + return 7; +} + +# Registers used: +# 0x02: Status 1 +# 0x03: Configuration +# 0x04: Company ID of LM84 +# 0x35: Status 2 +# 0xfe: Manufacturer ID +# 0xff: Chip ID / die revision +# We can use the LM84 Company ID register because the LM83 and the LM82 are +# compatible with the LM84. +# The LM83 chip ID is missing from the datasheet and was contributed by +# Magnus Forsstrom: 0x03. +# At least some revisions of the LM82 seem to be repackaged LM83, so they +# have the same chip ID, and temp2/temp4 will be stuck in "OPEN" state. +# For this reason, we don't even try to distinguish between both chips. +# Thanks to Ben Gardner for reporting. +sub lm83_detect +{ + my ($file, $addr) = @_; + return if i2c_smbus_read_byte_data($file, 0xfe) != 0x01; + my $chipid = i2c_smbus_read_byte_data($file, 0xff); + return if $chipid != 0x01 && $chipid != 0x03; + + my $confidence = 4; + $confidence++ + if (i2c_smbus_read_byte_data($file, 0x02) & 0xa8) == 0x00; + $confidence++ + if (i2c_smbus_read_byte_data($file, 0x03) & 0x41) == 0x00; + $confidence++ + if i2c_smbus_read_byte_data($file, 0x04) == 0x00; + $confidence++ + if (i2c_smbus_read_byte_data($file, 0x35) & 0x48) == 0x00; + + return $confidence; +} + +# Chip to detect: 0 = MAX6680/81, 1 = MAX6695/96 +# Registers used: +# 0x03: Configuration +# 0x04: Conversion rate +# 0x12: Status2 +# 0x16: Overtemperature 2 +# 0xfe: Manufacturer ID +# 0xff: Chip ID / die revision +sub max6680_95_detect +{ + my ($file, $addr, $chip) = @_; + my $cid = i2c_smbus_read_byte_data($file, 0xff); + my $conf = i2c_smbus_read_byte_data($file, 0x03); + my $mid = i2c_smbus_read_byte_data($file, 0xfe, NO_CACHE); + my $emerg = i2c_smbus_read_byte_data($file, 0x16, NO_CACHE); + my $rate = i2c_smbus_read_byte_data($file, 0x04, NO_CACHE); + my $emerg2 = i2c_smbus_read_byte_data($file, 0x16, NO_CACHE); + + # Check common conditions + return if $rate > 0x07; + return if $mid != 0x4d; # Not Maxim + return if $cid != 0x01; # None of the chips we are looking for + + if ($chip == 0) { + return if ($conf & 0x03) != 0; + return 8 if $emerg != $emerg2; # MAX6680/MAX6681 + } + if ($chip == 1) { + my $status2 = i2c_smbus_read_byte_data($file, 0x12); + + return if ($conf & 0x10) != 0; + return if ($status2 & 0x01) != 0; + return 8 if $emerg == $emerg2; # MAX6695/MAX6696 + } + return; +} + +# Chip to detect: 0 = LM90, 1 = LM89/LM99, 2 = LM86, 3 = ADM1032, +# 4 = MAX6654, 5 = ADT7461, +# 6 = MAX6646/MAX6647/MAX6648/MAX6649/MAX6692, +# 8 = W83L771W/G, +# 11 = W83L771AWG/ASG, 12 = MAX6690, +# 13 = ADT7461A/NCT1008, 14 = SA56004, +# 15 = G781 +# Registers used: +# 0x03: Configuration +# 0x04: Conversion rate +# 0xbf: Configuration 2 (National Semiconductor, Winbond, and Philips only) +# 0xfe: Manufacturer ID +# 0xff: Chip ID / die revision +sub lm90_detect +{ + my ($file, $addr, $chip) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0xfe); + my $cid = i2c_smbus_read_byte_data($file, 0xff); + my $conf = i2c_smbus_read_byte_data($file, 0x03); + my $rate = i2c_smbus_read_byte_data($file, 0x04); + my $conf2 = i2c_smbus_read_byte_data($file, 0xbf); + + if ($chip == 0) { + return if ($conf & 0x2a) != 0; + return if ($conf2 & 0xf8) != 0; + return if $rate > 0x09; + return if $mid != 0x01; # National Semiconductor + return 8 if $cid == 0x21; # LM90 + return 6 if ($cid & 0x0f) == 0x20; + } + if ($chip == 1) { + return if ($conf & 0x2a) != 0; + return if ($conf2 & 0xf8) != 0; + return if $rate > 0x09; + return if $mid != 0x01; # National Semiconductor + return 8 if $addr == 0x4c and $cid == 0x31; # LM89/LM99 + return 8 if $addr == 0x4d and $cid == 0x34; # LM89-1/LM99-1 + return 6 if ($cid & 0x0f) == 0x30; + } + if ($chip == 2) { + return if ($conf & 0x2a) != 0; + return if ($conf2 & 0xf8) != 0; + return if $rate > 0x09; + return if $mid != 0x01; # National Semiconductor + return 8 if $cid == 0x11; # LM86 + return 6 if ($cid & 0xf0) == 0x10; + } + if ($chip == 3) { + return if ($conf & 0x3f) != 0; + return if $rate > 0x0a; + return if $mid != 0x41; # Analog Devices + return 6 if ($cid & 0xf0) == 0x40; # ADM1032 + } + if ($chip == 4) { + return if ($conf & 0x07) != 0; + return if $rate > 0x07; + return if $mid != 0x4d; # Maxim + return 8 if $cid == 0x08; # MAX6654 + } + if ($chip == 5) { + return if ($conf & 0x1b) != 0; + return if $rate > 0x0a; + return if $mid != 0x41; # Analog Devices + return 8 if $cid == 0x51; # ADT7461 + } + if ($chip == 6) { + return if ($conf & 0x3f) != 0; + return if $rate > 0x07; + return if $mid != 0x4d; # Maxim + return 8 if $cid == 0x59; # MAX6648/MAX6692 + } + if ($chip == 8) { + return if ($conf & 0x2a) != 0; + return if ($conf2 & 0xf8) != 0; + return if $rate > 0x09; + return if $mid != 0x5c; # Winbond + return 6 if ($cid & 0xfe) == 0x00; # W83L771W/G + } + if ($chip == 11) { + return if ($conf & 0x2a) != 0; + return if ($conf2 & 0xf8) != 0; + return if $rate > 0x08; + return if $mid != 0x5c; # Winbond + return 6 if ($cid & 0xfe) == 0x10; # W83L771AWG/ASG + } + if ($chip == 12) { + return if ($conf & 0x07) != 0; + return if $rate > 0x07; + return if $mid != 0x4d; # Maxim + return 8 if $cid == 0x09; # MAX6690 + } + if ($chip == 13) { + return if ($conf & 0x1b) != 0; + return if $rate > 0x0a; + return if $mid != 0x41; # Analog Devices + return 8 if $cid == 0x57; # ADT7461A, NCT1008 + } + if ($chip == 14) { + return if ($conf & 0x2a) != 0; + return if ($conf2 & 0xfe) != 0; + return if $rate > 0x09; + return if $mid != 0xa1; # NXP Semiconductor/Philips + return 6 if $cid == 0x00; # SA56004 + } + if ($chip == 15) { + return if ($conf & 0x3f) != 0; + return if $rate > 0x08; + return if $mid != 0x47; # GMT + return 8 if $cid == 0x01; # G781 + } + return; +} + +# Chip to detect: 0 = TMP400, 1 = TMP401, 2 = TMP411A, 3 = TMP411B, 4 = TMP411C, +# 5 = TMP431, 6 = TMP432, 7 = TMP435, 8 = TMP451 +# Registers used: +# 0x03: Configuration (4 unused bits) +# 0x04: Conversion rate (value 0x0f or lower, 0x09 or lower for TMP451) +# 0x10: Remote temperature low byte (4 unused bits) +# 0x13: Remote temperature low limit, low byte (4 unused bits) +# 0x14: Remote temperature high limit, low byte (4 unused bits) +# 0x22: Consecutive alert, 4 unused bits (TMP451 only) +# 0x24: Digital filter control, 6 unused bits (TMP451 only) +# 0xfe: Manufacturer ID +# 0xff: Device ID +sub tmp401_detect() +{ + my ($file, $addr, $chip) = @_; + + my $mid = i2c_smbus_read_byte_data($file, 0xfe); + return if ($mid != 0x55); + + my $cid = i2c_smbus_read_byte_data($file, 0xff); + my $conf = i2c_smbus_read_byte_data($file, 0x03); + my $rate = i2c_smbus_read_byte_data($file, 0x04); + my $rtemp = i2c_smbus_read_byte_data($file, 0x10); + my $rhigh = i2c_smbus_read_byte_data($file, 0x13); + my $rlow = i2c_smbus_read_byte_data($file, 0x14); + + return if ($conf & 0x1b); + return if ($rate > 0x0f); + return if ($rtemp & 0x0f); + return if ($rhigh & 0x0f); + return if ($rlow & 0x0f); + + return 8 if ($chip == 0 && $cid == 0x01); # TMP400 + return 8 if ($chip == 1 && $cid == 0x11); # TMP401 + return 8 if ($chip == 2 && $cid == 0x12); # TMP411A + return 8 if ($chip == 3 && $cid == 0x13); # TMP411B + return 8 if ($chip == 4 && $cid == 0x10); # TMP411C + return 8 if ($chip == 5 && $cid == 0x31); # TMP431 + return 8 if ($chip == 6 && $cid == 0x32); # TMP432 + return 8 if ($chip == 7 && $cid == 0x35); # TMP435 + + if ($chip == 8) { # TMP451 + return if $cid != 0x00; + return if $rate > 0x09; + + my $alert = i2c_smbus_read_byte_data($file, 0x22); + return if ($alert & 0x71) != 0x01; + + my $filter = i2c_smbus_read_byte_data($file, 0x24); + return if $filter & 0xfc; + + return 4; + } + + return; +} + +# Chip to detect: 0 = TMP421, 1 = TMP422, 2 = TMP423, 3 = TMP441, 4 = TMP442 +# Registers used: +# 0x08: Status (7 unused bits) +# 0x0b: Conversion rate (value 0x07 or lower) +# 0xfe: Manufacturer ID +# 0xff: Device ID +sub tmp42x_detect() +{ + my ($file, $addr, $chip) = @_; + + my $mid = i2c_smbus_read_byte_data($file, 0xfe); + my $cid = i2c_smbus_read_byte_data($file, 0xff); + my $status = i2c_smbus_read_byte_data($file, 0x08); + my $rate = i2c_smbus_read_byte_data($file, 0x0b); + + return if ($mid != 0x55); + return if ($status & 0x7f); + return if ($rate > 0x07); + + return 6 if ($chip == 0 && $cid == 0x21); # TMP421 + return 6 if ($chip == 1 && $cid == 0x22); # TMP422 + return 6 if ($chip == 2 && $cid == 0x23); # TMP423 + return 6 if ($chip == 3 && $cid == 0x41); # TMP441 + return 6 if ($chip == 4 && $cid == 0x42); # TMP442 + + return; +} + +# Registers used: +# 0x3d: Device ID +# 0x3e: Company ID +sub amc6821_detect() +{ + my ($file, $addr) = @_; + + my $dev_id = i2c_smbus_read_byte_data($file, 0x3d); + my $comp_id = i2c_smbus_read_byte_data($file, 0x3e); + + return if ($comp_id != 0x49); # Texas Instruments + + # Bit 7 of register address is ignored + return if i2c_smbus_read_byte_data($file, 0x80 | 0x3d) != $dev_id; + return if i2c_smbus_read_byte_data($file, 0x80 | 0x3e) != $comp_id; + + return 6 if ($dev_id == 0x21); # AMC6821 + + return; +} + +# Registers used: +# 0x03: Configuration (no low nibble, returns the previous low nibble) +# 0x04: Conversion rate +# 0xfe: Manufacturer ID +# 0xff: no register +sub max6657_detect +{ + my ($file, $addr) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0xfe, NO_CACHE); + my $cid = i2c_smbus_read_byte_data($file, 0xff, NO_CACHE); + my $conf = i2c_smbus_read_byte_data($file, 0x03, NO_CACHE); + + return if $mid != 0x4d; # Maxim + return if ($conf & 0x1f) != 0x0d; + return if $cid != 0x4d; # No register, returns previous value + + my $rate = i2c_smbus_read_byte_data($file, 0x04, NO_CACHE); + return if $rate > 0x09; + + $cid = i2c_smbus_read_byte_data($file, 0xff, NO_CACHE); + $conf = i2c_smbus_read_byte_data($file, 0x03, NO_CACHE); + return if ($conf & 0x0f) != $rate; + return if $cid != $rate; # No register, returns previous value + + return 5; +} + +# Chip to detect: 0 = LM95231, 1 = LM95241, 2 = LM95245, 3 = LM95234, +# 4 = LM95235, 5 = LM95233 +# Registers used: +# 0x02: Status (3 unused bits) +# 0x03: Configuration (3 unused bits) +# 0x04: Conversion rate (6 unused bits, LM95234) +# 0x06: Remote diode filter control (6 unused bits, LM95231 and LM95241) +# 0x30: Remote diode model type select (6 unused bits, LM95231 and LM95241) +# 0x30: Local Temperature LSB (5 unused bits, LM95245) +# 0x30: Diode model (4 unused bits, LM95234) +# 0x33: Status register 2 (6 unused bits, LM95245) +# 0x38: Diode model status (4 unused bits, LM95234) +# 0xfe: Manufacturer ID +# 0xff: Revision ID +sub lm95231_detect +{ + my ($file, $addr, $chip) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0xfe); + my $cid = i2c_smbus_read_byte_data($file, 0xff); + + return if $mid != 0x01; # National Semiconductor + + if ($chip == 0 || $chip == 1) { + return if $chip == 0 && $cid != 0xa1; # LM95231 + return if $chip == 1 && $cid != 0xa4; # LM95241 + return if i2c_smbus_read_byte_data($file, 0x02) & 0x70; + return if i2c_smbus_read_byte_data($file, 0x03) & 0x89; + return if i2c_smbus_read_byte_data($file, 0x06) & 0xfa; + return if i2c_smbus_read_byte_data($file, 0x30) & 0xfa; + } elsif ($chip == 2 || $chip == 4) { + return if $chip == 4 && $cid != 0xb1; # LM95235 + return if $chip == 2 && $cid != 0xb3; # LM95245 + return if i2c_smbus_read_byte_data($file, 0x02) & 0x68; + return if i2c_smbus_read_byte_data($file, 0x03) & 0xa1; + return if i2c_smbus_read_byte_data($file, 0x30) & 0x1f; + return if i2c_smbus_read_byte_data($file, 0x33) & 0x3f; + } elsif ($chip == 3) { + return if $cid != 0x79; # LM95234 + return if i2c_smbus_read_byte_data($file, 0x02) & 0x30; + return if i2c_smbus_read_byte_data($file, 0x03) & 0xbc; + return if i2c_smbus_read_byte_data($file, 0x04) & 0xfc; + return if i2c_smbus_read_byte_data($file, 0x30) & 0xe1; + return if i2c_smbus_read_byte_data($file, 0x38) & 0xe1; + } elsif ($chip == 5) { + return if $cid != 0x89; # LM95233 + return if i2c_smbus_read_byte_data($file, 0x02) & 0x30; + return if i2c_smbus_read_byte_data($file, 0x03) & 0xbf; + return if i2c_smbus_read_byte_data($file, 0x04) & 0xfc; + return if i2c_smbus_read_byte_data($file, 0x30) & 0xf9; + return if i2c_smbus_read_byte_data($file, 0x38) & 0xf9; + } + + return 6; +} + +# Registers used: +# 0x03: Configuration 1 +# 0x24: Configuration 2 +# 0x3d: Manufacturer ID +# 0x3e: Device ID +sub adt7481_detect +{ + my ($file, $addr) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0x3d); + my $cid = i2c_smbus_read_byte_data($file, 0x3e); + my $conf1 = i2c_smbus_read_byte_data($file, 0x03); + my $conf2 = i2c_smbus_read_byte_data($file, 0x24); + + return if ($conf1 & 0x10) != 0; + return if ($conf2 & 0x7f) != 0; + return if $mid != 0x41; # Analog Devices + return if $cid != 0x81; # ADT7481 + + return 6; +} + +# Chip to detect: 1 = LM63, 2 = F75363SG, 3 = LM64, 4 = LM96163 +# Registers used: +# 0xfe: Manufacturer ID +# 0xff: Chip ID / die revision +# 0x03: Configuration (two or three unused bits) +# 0x16: Alert mask (two or three unused bits) +sub lm63_detect +{ + my ($file, $addr, $chip) = @_; + + my $mid = i2c_smbus_read_byte_data($file, 0xfe); + my $cid = i2c_smbus_read_byte_data($file, 0xff); + my $conf = i2c_smbus_read_byte_data($file, 0x03); + my $mask = i2c_smbus_read_byte_data($file, 0x16); + + if ($chip == 1) { + return if $mid != 0x01 # National Semiconductor + || $cid != 0x41; # LM63 + return if ($conf & 0x18) != 0x00 + || ($mask & 0xa4) != 0xa4; + } elsif ($chip == 2) { + return if $mid != 0x23 # Fintek + || $cid != 0x20; # F75363SG + return if ($conf & 0x1a) != 0x00 + || ($mask & 0x84) != 0x00; + } elsif ($chip == 3) { + return if $mid != 0x01 # National Semiconductor + || $cid != 0x51; # LM64 + return if ($conf & 0x18) != 0x00 + || ($mask & 0xa4) != 0xa4; + } elsif ($chip == 4) { + return if $mid != 0x01 # National Semiconductor + || $cid != 0x49; # LM96163 + return if ($conf & 0x18) != 0x00 + || ($mask & 0xa4) != 0xa4; + } + + return 6; +} + +# Registers used: +# 0x02, 0x03: Fan support +# 0x06: Temperature support +# 0x07, 0x08, 0x09: Fan config +# 0x0d: Manufacturer ID +# 0x0e: Chip ID / die revision +sub adm1029_detect +{ + my ($file, $addr) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0x0d); + my $cid = i2c_smbus_read_byte_data($file, 0x0e); + my $cfg; + + return unless $mid == 0x41; # Analog Devices + return unless ($cid & 0xF0) == 0x00; # ADM1029 + + # Extra check on unused bits + $cfg = i2c_smbus_read_byte_data($file, 0x02); + return unless $cfg == 0x03; + $cfg = i2c_smbus_read_byte_data($file, 0x06); + return unless ($cfg & 0xF9) == 0x01; + foreach my $reg (0x03, 0x07, 0x08, 0x09) { + $cfg = i2c_smbus_read_byte_data($file, $reg); + return unless ($cfg & 0xFC) == 0x00; + } + + return 7; +} + +# Chip to detect: 0 = ADM1030, 1 = ADM1031 +# Registers used: +# 0x01: Config 2 +# 0x03: Status 2 +# 0x0d, 0x0e, 0x0f: Temperature offsets +# 0x22: Fan speed config +# 0x3d: Chip ID +# 0x3e: Manufacturer ID +# 0x3f: Die revision +sub adm1031_detect +{ + my ($file, $addr, $chip) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0x3e); + my $cid = i2c_smbus_read_byte_data($file, 0x3d); + my $drev = i2c_smbus_read_byte_data($file, 0x3f); + my $conf2 = i2c_smbus_read_byte_data($file, 0x01); + my $stat2 = i2c_smbus_read_byte_data($file, 0x03); + my $fsc = i2c_smbus_read_byte_data($file, 0x22); + my $lto = i2c_smbus_read_byte_data($file, 0x0d); + my $r1to = i2c_smbus_read_byte_data($file, 0x0e); + my $r2to = i2c_smbus_read_byte_data($file, 0x0f); + my $confidence = 3; + + if ($chip == 0) { + return if $mid != 0x41; # Analog Devices + return if $cid != 0x30; # ADM1030 + $confidence++ if ($drev & 0x70) == 0x00; + $confidence++ if ($conf2 & 0x4A) == 0x00; + $confidence++ if ($stat2 & 0x3F) == 0x00; + $confidence++ if ($fsc & 0xF0) == 0x00; + $confidence++ if ($lto & 0x70) == 0x00; + $confidence++ if ($r1to & 0x70) == 0x00; + return $confidence; + } + if ($chip == 1) { + return if $mid != 0x41; # Analog Devices + return if $cid != 0x31; # ADM1031 + $confidence++ if ($drev & 0x70) == 0x00; + $confidence++ if ($lto & 0x70) == 0x00; + $confidence++ if ($r1to & 0x70) == 0x00; + $confidence++ if ($r2to & 0x70) == 0x00; + return $confidence; + } +} + +# Chip to detect: 0 = ADM1033, 1 = ADM1034 +# Registers used: +# 0x3d: Chip ID +# 0x3e: Manufacturer ID +# 0x3f: Die revision +sub adm1034_detect +{ + my ($file, $addr, $chip) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0x3e); + my $cid = i2c_smbus_read_byte_data($file, 0x3d); + my $drev = i2c_smbus_read_byte_data($file, 0x3f); + + if ($chip == 0) { + return if $mid != 0x41; # Analog Devices + return if $cid != 0x33; # ADM1033 + return if ($drev & 0xf8) != 0x00; + return 6 if $drev == 0x02; + return 4; + } + if ($chip == 1) { + return if $mid != 0x41; # Analog Devices + return if $cid != 0x34; # ADM1034 + return if ($drev & 0xf8) != 0x00; + return 6 if $drev == 0x02; + return 4; + } +} + +# Chip to detect: 0 = ADT7467/ADT7468, 1 = ADT7476, 2 = ADT7462, 3 = ADT7466, +# 4 = ADT7470 +# Registers used: +# 0x3d: Chip ID +# 0x3e: Manufacturer ID +# 0x3f: Die revision +sub adt7467_detect +{ + my ($file, $addr, $chip) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0x3e); + my $cid = i2c_smbus_read_byte_data($file, 0x3d); + my $drev = i2c_smbus_read_byte_data($file, 0x3f); + + return if $mid != 0x41; # Analog Devices + + if ($chip == 0) { + return if $cid != 0x68; # ADT7467/ADT7468 + return if ($drev & 0xf0) != 0x70; + return 7 if $drev == 0x71 || $drev == 0x72; + return 5; + } + if ($chip == 1) { + return if $cid != 0x76; # ADT7476 + return if ($drev & 0xf0) != 0x60; + return 7 if $drev >= 0x69 && $drev <= 0x6b; + return 5; + } + if ($chip == 2) { + return if $cid != 0x62; # ADT7462 + return if ($drev & 0xf0) != 0x00; + return 7 if $drev == 0x04; + return 5; + } + if ($chip == 3) { + return if $cid != 0x66; # ADT7466 + return if ($drev & 0xf0) != 0x00; + return 7 if $drev == 0x02; + return 5; + } + if ($chip == 4) { + return if $cid != 0x70; # ADT7470 + return if ($drev & 0xf0) != 0x00; + return 7 if $drev == 0x00; + return 5; + } +} + +# Chip to detect: 0 = ADT7473, 1 = ADT7475 +# Registers used: +# 0x3d: Chip ID +# 0x3e: Manufacturer ID +sub adt7473_detect +{ + my ($file, $addr, $chip) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0x3e); + my $cid = i2c_smbus_read_byte_data($file, 0x3d); + + return if $mid != 0x41; # Analog Devices + + return if $chip == 0 && $cid != 0x73; # ADT7473 + return if $chip == 1 && $cid != 0x75; # ADT7475 + return 5; +} + +# Registers used: +# 0x3e: Manufacturer ID +# 0x3f: Chip ID +sub adt7490_detect +{ + my ($file, $addr) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0x3e); + my $cid = i2c_smbus_read_byte_data($file, 0x3f); + + return if $mid != 0x41; # Analog Devices + return if ($cid & 0xfc) != 0x6c; # ADT7490 + return 5; +} + +# Registers used: +# 0x02: Status +# 0x0a: Thyst +# 0x0b: ID +# We also rely on the fact that only the 5 LSB of the address pointer +# are considered, so registers cycle over 32 byte boundaries. +sub adt7410_detect +{ + my ($file, $addr) = @_; + my $status = i2c_smbus_read_byte_data($file, 0x02); + my $thyst = i2c_smbus_read_byte_data($file, 0x0a); + my $id = i2c_smbus_read_byte_data($file, 0x0b); + + # Unused bits + return if ($status & 0x0f); + return if ($thyst & 0xf0); + + # ID register + return if $id != 0xcb; + + # Cycling registers + for (my $i = 2; $i < 16; $i *= 2) { + return if i2c_smbus_read_byte_data($file, 0x0a + $i * 16) != $thyst; + return if i2c_smbus_read_byte_data($file, 0x0b + $i * 16) != $id; + } + + # Non-existent registers (other devices tend to have ID registers there) + return if i2c_smbus_read_byte_data($file, 0x03e) != 0; + return if i2c_smbus_read_byte_data($file, 0x03f) != 0; + return if i2c_smbus_read_byte_data($file, 0x0fe) != 0; + return if i2c_smbus_read_byte_data($file, 0x0ff) != 0; + + return 3; +} + +# Registers used: +# 0x4d: Device ID +# 0x4e: Manufacturer ID +# 0x4e: Silicon revision +sub adt7411_detect +{ + my ($file, $addr) = @_; + my $dev_id = i2c_smbus_read_byte_data($file, 0x4d); + my $man_id = i2c_smbus_read_byte_data($file, 0x4e); + my $revision = i2c_smbus_read_byte_data($file, 0x4f); + + return if $man_id != 0x41; # Analog Devices + return if $dev_id != 0x02; # ADT7411 + # The datasheet suggests that the version is in the high nibble, but + # a dump from a real ADT7411 chip shows that it is in the low nibble. + return if ($revision & 0x0f) != 0x04; # ADT7411 + return 5; +} + +# Chip to detect: 0 = aSC7512, 1 = aSC7611, 2 = aSC7621 +# Registers used: +# 0x3e: Manufacturer ID +# 0x3f: Version +sub andigilog_detect +{ + my ($file, $addr, $chip) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0x3e); + my $cid = i2c_smbus_read_byte_data($file, 0x3f); + + return if $mid != 0x61; # Andigilog + + return if $chip == 0 && $cid != 0x62; + return if $chip == 1 && $cid != 0x69; + return if $chip == 2 && ($cid != 0x6C && $cid != 0x6D); + return 5; +} + +# Registers used: +# 0xfe: Manufacturer ID +# 0xff: Die Code +sub andigilog_aSC7511_detect +{ + my ($file, $addr) = @_; + my $mid = i2c_smbus_read_byte_data($file, 0xfe); + my $die = i2c_smbus_read_byte_data($file, 0xff); + + return if $mid != 0x61; # Andigilog + return if $die != 0x00; + return 3; +} + +# Chip to detect: 0 = LM85, 1 = LM96000, 2 = ADM1027, 3 = ADT7463, +# 4 = EMC6D100/101, 5 = EMC6D102, 6 = EMC6D103, +# 7 = WPCD377I (no sensors), 8 = EMC6D103S/EMC2300 +# Registers used: +# 0x3e: Vendor register +# 0x3d: Device ID register (Analog Devices only) +# 0x3f: Version/Stepping register +sub lm85_detect +{ + my ($file, $addr, $chip) = @_; + my $vendor = i2c_smbus_read_byte_data($file, 0x3e); + my $verstep = i2c_smbus_read_byte_data($file, 0x3f); + + if ($chip == 0) { + return if $vendor != 0x01; # National Semiconductor + return if $verstep != 0x60 # LM85 C + && $verstep != 0x62; # LM85 B + } elsif ($chip == 1 || $chip == 7) { + return if $vendor != 0x01; # National Semiconductor + return if $verstep != 0x68 # LM96000 + && $verstep != 0x69; # LM96000 + } elsif ($chip == 2) { + return if $vendor != 0x41; # Analog Devices + return if $verstep != 0x60; # ADM1027 + } elsif ($chip == 3) { + return if $vendor != 0x41; # Analog Devices + return if $verstep != 0x62 # ADT7463 + && $verstep != 0x6a; # ADT7463 C + } elsif ($chip == 4) { + return if $vendor != 0x5c; # SMSC + return if $verstep != 0x60 # EMC6D100/101 A0 + && $verstep != 0x61; # EMC6D100/101 A1 + } elsif ($chip == 5) { + return if $vendor != 0x5c; # SMSC + return if $verstep != 0x65; # EMC6D102 + } elsif ($chip == 6) { + return if $vendor != 0x5c; # SMSC + return if $verstep != 0x68 # EMC6D103 A0 + && $verstep != 0x69; # EMC6D103 A1 + } elsif ($chip == 8) { + return if $vendor != 0x5c; # SMSC + return if $verstep != 0x6a; # EMC6D103S/EMC2300 + } + + if ($vendor == 0x41) { # Analog Devices + return if i2c_smbus_read_byte_data($file, 0x3d) != 0x27; + return 8; + } + + if ($chip == 1 || $chip == 7) { + # Differenciate between real LM96000 and Winbond WPCD377I. + # The latter emulate the former except that it has no + # hardware monitoring function so the readings are always + # 0. + my ($in_temp, $fan, $i); + + for ($i = 0; $i < 8; $i++) { + $in_temp = i2c_smbus_read_byte_data($file, 0x20 + $i); + $fan = i2c_smbus_read_byte_data($file, 0x28 + $i); + if ($in_temp != 0x00 or $fan != 0xff) { + return 7 if $chip == 1; + return; + } + } + return 7 if $chip == 7; + return; + } + + return 7; +} + +# Registers used: +# 0x3e: Vendor register +# 0x3f: Version/Stepping register +# 0x40: Configuration register (reserved bits + ready) +sub emc6w201_detect +{ + my ($file, $addr) = @_; + my $vendor = i2c_smbus_read_byte_data($file, 0x3e); + my $verstep = i2c_smbus_read_byte_data($file, 0x3f); + my $conf = i2c_smbus_read_byte_data($file, 0x40); + my $stepping; + + return if $vendor != 0x5c; # SMSC + return if ($verstep & 0xf0) != 0xb0; # EMC6W201 + return if ($conf & 0xf4) != 0x04; + + $stepping = $verstep & 0x0f; + return if $stepping > 3; + + # So far we've only seen stepping 1 chips + return $stepping <= 1 ? 6 : 3; +} + +# Chip to detect: 0 = LM87, 1 = ADM1024 +# Registers used: +# 0x3e: Company ID +# 0x3f: Revision +# 0x40: Configuration +sub lm87_detect +{ + my ($file, $addr, $chip) = @_; + my $cid = i2c_smbus_read_byte_data($file, 0x3e); + my $rev = i2c_smbus_read_byte_data($file, 0x3f); + + if ($chip == 0) { + return if $cid != 0x02; # National Semiconductor + return if ($rev & 0xfc) != 0x04; # LM87 + } + if ($chip == 1) { + return if $cid != 0x41; # Analog Devices + return if ($rev & 0xf0) != 0x10; # ADM1024 + } + + my $cfg = i2c_smbus_read_byte_data($file, 0x40); + return if ($cfg & 0x80) != 0x00; + + return 7; +} + +# Chip to detect: 0 = W83781D, 1 = W83782D, 2 = W83783S, 3 = W83627HF, +# 4 = AS99127F (rev.1), 5 = AS99127F (rev.2), 6 = ASB100, +# 7 = W83791D, 8 = W83792D, 9 = W83627EHF, +# 10 = W83627DHG/W83667HG/W83677HG +# Registers used: +# 0x48: Full I2C Address +# 0x4a: I2C addresses of emulated LM75 chips +# 0x4e: Vendor ID byte selection, and bank selection +# 0x4f: Vendor ID +# 0x58: Device ID (only when in bank 0) +# Note: Fails if the W8378xD is not in bank 0! +# Note: Asus chips do not have their I2C address at register 0x48? +# AS99127F rev.1 and ASB100 have 0x00, confirmation wanted for +# AS99127F rev.2. +sub w83781d_detect +{ + my ($file, $addr, $chip) = @_; + my ($reg1, $reg2, @res); + + return unless (i2c_smbus_read_byte_data($file, 0x48) == $addr) + or ($chip >= 4 && $chip <= 6); + + $reg1 = i2c_smbus_read_byte_data($file, 0x4e); + $reg2 = i2c_smbus_read_byte_data($file, 0x4f); + if ($chip == 4) { # Asus AS99127F (rev.1) + return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or + (($reg1 & 0x80) == 0x80 and $reg2 == 0x12); + } elsif ($chip == 6) { # Asus ASB100 + return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0x94) or + (($reg1 & 0x80) == 0x80 and $reg2 == 0x06); + } else { # Winbond and Asus AS99127F (rev.2) + return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or + (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c); + } + + return unless ($reg1 & 0x07) == 0x00; + + $reg1 = i2c_smbus_read_byte_data($file, 0x58); + return if $chip == 0 and ($reg1 != 0x10 && $reg1 != 0x11); + return if $chip == 1 and $reg1 != 0x30; + return if $chip == 2 and $reg1 != 0x40; + return if $chip == 3 and $reg1 != 0x21; + return if $chip == 4 and $reg1 != 0x31; + return if $chip == 5 and $reg1 != 0x31; + return if $chip == 6 and $reg1 != 0x31; + return if $chip == 7 and $reg1 != 0x71; + return if $chip == 8 and $reg1 != 0x7a; + return if $chip == 9 and ($reg1 != 0x88 && $reg1 != 0xa1); + return if $chip == 10 and $reg1 != 0xc1; + # Default address is 0x2d + @res = ($addr != 0x2d) ? (7) : (8); + return @res if $chip >= 9; # No subclients + + $reg1 = i2c_smbus_read_byte_data($file, 0x4a); + push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08; + push @res, (($reg1 & 0x70) >> 4) + 0x48 + unless ($reg1 & 0x80 or $chip == 2); + return @res; +} + +# Registers used: +# 0x0b: Full I2C Address +# 0x0c: I2C addresses of emulated LM75 chips +# 0x00: Vendor ID byte selection, and bank selection(Bank 0, 1, 2) +# 0x0d: Vendor ID(Bank 0, 1, 2) +# 0x0e: Device ID(Bank 0, 1, 2) +sub w83793_detect +{ + my ($file, $addr) = @_; + my ($bank, $reg, @res); + + $bank = i2c_smbus_read_byte_data($file, 0x00); + $reg = i2c_smbus_read_byte_data($file, 0x0d); + + return unless (($bank & 0x80) == 0x00 and $reg == 0xa3) or + (($bank & 0x80) == 0x80 and $reg == 0x5c); + + $reg = i2c_smbus_read_byte_data($file, 0x0e); + return if $reg != 0x7b; + + # If bank 0 is selected, we can do more checks + return 6 unless ($bank & 0x07) == 0; + $reg = i2c_smbus_read_byte_data($file, 0x0b); + return unless ($reg == ($addr << 1)); + + $reg = i2c_smbus_read_byte_data($file, 0x0c); + @res = (8); + push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08; + push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80; + return @res; +} + +# Registers used: +# 0xfc: Full I2C Address +# 0x00: Vendor ID byte selection, and bank selection(Bank 0, 1, 2) +# 0xfd: Vendor ID(Bank 0, 1, 2) +# 0xfe: Device ID(Bank 0, 1, 2) +sub w83795_detect +{ + my ($bank, $reg); + my ($file, $addr) = @_; + + $bank = i2c_smbus_read_byte_data($file, 0x00); + $reg = i2c_smbus_read_byte_data($file, 0xfd); + + return unless (($bank & 0x80) == 0x00 and $reg == 0xa3) or + (($bank & 0x80) == 0x80 and $reg == 0x5c); + + $reg = i2c_smbus_read_byte_data($file, 0xfe); + return if $reg != 0x79; + + # If bank 0 is selected, we can do more checks + return 6 unless ($bank & 0x07) == 0; + $reg = i2c_smbus_read_byte_data($file, 0xfc) & 0x7f; + return unless ($reg == $addr); + + return 8; +} + +# Registers used: +# 0x00: Bank selection (Bank 0, 1) +# 0x05: Temperature readout register LSB (Bank 0) +# 0x08: PECI temperature readout register LSB (Bank 0) +# 0x0f: Voltage readout register LSB (Bank 0) +# 0xfd: Vendor ID (Bank 0) +# 0xfe: Device ID (Bank 0) +# 0xff: Device Revision (Bank 0) +# +# Note that identification registers are not accessible in bank 1, +# and there is no usable other means to identify the chip if bank 1 +# is selected. Only detect chip if bank 0 is selected. +sub nct7802_detect +{ + my ($bank, $reg); + my ($file, $addr) = @_; + + $bank = i2c_smbus_read_byte_data($file, 0x00); + return unless $bank == 0x00; + + $reg = i2c_smbus_read_byte_data($file, 0xfd); + return unless $reg == 0x50; + + $reg = i2c_smbus_read_byte_data($file, 0xfe); + return unless $reg == 0xc3; + + $reg = i2c_smbus_read_byte_data($file, 0xff); + return unless ($reg & 0xf0) == 0x20; + + $reg = i2c_smbus_read_byte_data($file, 0x05); + return unless ($reg & 0x1f) == 0x00; + + $reg = i2c_smbus_read_byte_data($file, 0x08); + return unless ($reg & 0x3f) == 0x00; + + $reg = i2c_smbus_read_byte_data($file, 0x0f); + return unless ($reg & 0x3f) == 0x00; + + return 8; +} + +# Registers used: +# 0x7a: Vendor ID +# 0x7b: Chip ID +# 0x7c: Device ID +# 0xff: Bank Select +# +sub nct7904_detect +{ + my ($reg); + my ($file, $addr) = @_; + + $reg = i2c_smbus_read_byte_data($file, 0x7a); + return unless $reg == 0x50; + + $reg = i2c_smbus_read_byte_data($file, 0x7b); + return unless $reg == 0xc5; + + $reg = i2c_smbus_read_byte_data($file, 0x7c); + return unless ($reg & 0xf0) == 0x50; + + $reg = i2c_smbus_read_byte_data($file, 0xff); + return unless ($reg & 0xf8) == 0x00; + + return 8; +} + +# Registers used: +# 0x48: Full I2C Address +# 0x4e: Vendor ID byte selection +# 0x4f: Vendor ID +# 0x58: Device ID +# Note that the datasheet was useless and this detection routine +# is based on dumps we received from users. Also, the W83781SD is *NOT* +# a hardware monitoring chip as far as we know, but we still want to +# detect it so that people won't keep reporting it as an unknown chip +# we should investigate about. +sub w83791sd_detect +{ + my ($file, $addr) = @_; + my ($reg1, $reg2); + + return unless (i2c_smbus_read_byte_data($file, 0x48) == $addr); + + $reg1 = i2c_smbus_read_byte_data($file, 0x4e); + $reg2 = i2c_smbus_read_byte_data($file, 0x4f); + return unless (!($reg1 & 0x80) && $reg2 == 0xa3) + || (($reg1 & 0x80) && $reg2 == 0x5c); + + $reg1 = i2c_smbus_read_byte_data($file, 0x58); + return unless $reg1 == 0x72; + + return 3; +} + +# Registers used: +# 0x4e: Vendor ID high byte +# 0x4f: Vendor ID low byte +# 0x58: Device ID +# Note: The values were given by Alex van Kaam, we don't have datasheets +# to confirm. +sub mozart_detect +{ + my ($file, $addr) = @_; + my ($vid, $dev); + + $vid = (i2c_smbus_read_byte_data($file, 0x4e) << 8) + + i2c_smbus_read_byte_data($file, 0x4f); + $dev = i2c_smbus_read_byte_data($file, 0x58); + + return unless ($dev == 0x56 && $vid == 0x9436) # ASM58 + || ($dev == 0x56 && $vid == 0x9406) # AS2K129R + || ($dev == 0x10 && $vid == 0x5ca3); + + return 5; +} + +# Chip to detect: 0 = GL518SM, 1 = GL520SM +# Registers used: +# 0x00: Device ID +# 0x01: Revision ID +# 0x03: Configuration +sub gl518sm_detect +{ + my ($file, $addr, $chip) = @_; + my $reg; + + $reg = i2c_smbus_read_byte_data($file, 0x00); + return if $chip == 0 && $reg != 0x80; + return if $chip == 1 && $reg != 0x20; + + return unless (i2c_smbus_read_byte_data($file, 0x03) & 0x80) == 0x00; + $reg = i2c_smbus_read_byte_data($file, 0x01); + return unless $reg == 0x00 or $reg == 0x80; + return 6; +} + +# Registers used: +# 0x00: Device ID +# 0x03: Configuration +# Mediocre detection +sub gl525sm_detect +{ + my ($file, $addr) = @_; + return unless i2c_smbus_read_byte_data($file, 0x00) == 0x25; + return unless (i2c_smbus_read_byte_data($file, 0x03) & 0x80) == 0x00; + return 5; +} + +# Chip to detect: 0 = ADM9240, 1 = DS1780, 2 = LM81 +# Registers used: +# 0x3e: Company ID +# 0x40: Configuration +# 0x48: Full I2C Address +sub adm9240_detect +{ + my ($file, $addr, $chip) = @_; + my $reg; + $reg = i2c_smbus_read_byte_data($file, 0x3e); + return unless ($chip == 0 and $reg == 0x23) or + ($chip == 1 and $reg == 0xda) or + ($chip == 2 and $reg == 0x01); + return unless (i2c_smbus_read_byte_data($file, 0x40) & 0x80) == 0x00; + return unless i2c_smbus_read_byte_data($file, 0x48) == $addr; + + return 7; +} + +# Chip to detect: 0 = ADM1022, 1 = THMC50, 2 = ADM1028, 3 = THMC51 +# Registers used: +# 0x3e: Company ID +# 0x3f: Revision +# 0x40: Configuration +sub adm1022_detect +{ + my ($file, $addr, $chip) = @_; + my $reg; + $reg = i2c_smbus_read_byte_data($file, 0x3e); + return unless ($chip == 0 and $reg == 0x41) or + ($chip == 1 and $reg == 0x49) or + ($chip == 2 and $reg == 0x41) or + ($chip == 3 and $reg == 0x49); + $reg = i2c_smbus_read_byte_data($file, 0x40); + return if ($reg & 0x10); # Soft Reset always reads 0 + return if ($chip != 0 and ($reg & 0x80)); # Reserved on THMC50 and ADM1028 + $reg = i2c_smbus_read_byte_data($file, 0x3f) & 0xf0; + return unless ($chip == 0 and $reg == 0xc0) or + ($chip == 1 and $reg == 0xc0) or + ($chip == 2 and $reg == 0xd0) or + ($chip == 3 and $reg == 0xd0); + return 8; +} + +# Chip to detect: 0 = ADM1025, 1 = NE1619 +# Registers used: +# 0x3e: Company ID +# 0x3f: Revision +# 0x40: Configuration +# 0x41: Status 1 +# 0x42: Status 2 +sub adm1025_detect +{ + my ($file, $addr, $chip) = @_; + my $reg; + + $reg = i2c_smbus_read_byte_data($file, 0x3e); + return if ($chip == 0) and ($reg != 0x41); + return if ($chip == 1) and ($reg != 0xA1); + + return unless (i2c_smbus_read_byte_data($file, 0x40) & 0x80) == 0x00; + return unless (i2c_smbus_read_byte_data($file, 0x41) & 0xC0) == 0x00; + return unless (i2c_smbus_read_byte_data($file, 0x42) & 0xBC) == 0x00; + return unless (i2c_smbus_read_byte_data($file, 0x3f) & 0xf0) == 0x20; + + return 8; +} + +# Registers used: +# 0x16: Company ID +# 0x17: Revision +sub adm1026_detect +{ + my ($file, $addr) = @_; + my $reg; + $reg = i2c_smbus_read_byte_data($file, 0x16); + return unless ($reg == 0x41); + return unless (i2c_smbus_read_byte_data($file, 0x17) & 0xf0) == 0x40; + return 8; +} + +# Chip to detect: 0 = ADM1021, 1 = ADM1021A/ADM1023, 2 = MAX1617, 3 = MAX1617A, +# 4 = THMC10, 5 = LM84, 6 = GL523, 7 = MC1066 +# Registers used: +# 0x04: Company ID (LM84 only) +# 0xfe: Company ID (all but LM84 and MAX1617) +# 0xff: Revision (ADM1021, ADM1021A/ADM1023 and MAX1617A) +# 0x02: Status +# 0x03: Configuration +# 0x04: Conversion rate +# 0x00-0x01, 0x05-0x08: Temperatures (MAX1617 and LM84) +# Note: Especially the MAX1617 has very bad detection; we give it a low +# confidence value. +sub adm1021_detect +{ + my ($file, $addr, $chip) = @_; + my $man_id = i2c_smbus_read_byte_data($file, 0xfe); + my $rev = i2c_smbus_read_byte_data($file, 0xff); + my $conf = i2c_smbus_read_byte_data($file, 0x03); + my $status = i2c_smbus_read_byte_data($file, 0x02); + my $convrate = i2c_smbus_read_byte_data($file, 0x04); + + # Check manufacturer IDs and product revisions when available + return if $chip == 0 and $man_id != 0x41 || ($rev & 0xf0) != 0x00; + return if $chip == 1 and $man_id != 0x41 || ($rev & 0xf0) != 0x30; + return if $chip == 3 and $man_id != 0x4d || $rev != 0x01; + return if $chip == 4 and $man_id != 0x49; + return if $chip == 5 and $convrate != 0x00; + return if $chip == 6 and $man_id != 0x23; + return if $chip == 7 and $man_id != 0x54; + + # Check unused bits + if ($chip == 5) { # LM84 + return if ($status & 0xab) != 0; + return if ($conf & 0x7f) != 0; + } else { + return if ($status & 0x03) != 0; + return if ($conf & 0x3f) != 0; + return if ($convrate & 0xf8) != 0; + } + + # Extra checks for MAX1617 and LM84, since those are often misdetected. + # We verify several assertions (6 for the MAX1617, 4 for the LM84) and + # discard the chip if any fail. + if ($chip == 2 || $chip == 5) { + my $lte = i2c_smbus_read_byte_data($file, 0x00); + my $rte = i2c_smbus_read_byte_data($file, 0x01); + my $lhi = i2c_smbus_read_byte_data($file, 0x05); + my $rhi = i2c_smbus_read_byte_data($file, 0x07); + my $llo = i2c_smbus_read_byte_data($file, 0x06); + my $rlo = i2c_smbus_read_byte_data($file, 0x08); + + # If all registers hold the same value, it has to be a misdetection + return if $lte == $rte and $lte == $lhi and $lte == $rhi + and $lte == $llo and $lte == $rlo; + + # Negative temperatures + return if ($lte & 0x80) or ($rte & 0x80); + # Negative high limits + return if ($lhi & 0x80) or ($rhi & 0x80); + # Low limits over high limits + if ($chip == 2) { + $llo -= 256 if ($llo & 0x80); + $rlo -= 256 if ($rlo & 0x80); + return if ($llo > $lhi) or ($rlo > $rhi); + } + return 3; + } + + return ($chip <= 3) ? 7 : 5; +} + +# Chip to detect: 0 = MAX1668, 1 = MAX1805, 2 = MAX1989 +# Registers used: +# 0xfe: Company ID +# 0xff: Device ID +sub max1668_detect +{ + my ($file, $addr, $chip) = @_; + my $man_id = i2c_smbus_read_byte_data($file, 0xfe); + my $dev_id = i2c_smbus_read_byte_data($file, 0xff); + + return if $man_id != 0x4d; + return if $chip == 0 and $dev_id != 0x03; + return if $chip == 1 and $dev_id != 0x05; + return if $chip == 2 and $dev_id != 0x0b; + + return 7; +} + +# Chip to detect: 0 = MAX1619, 1 = MAX1618 +# Registers used: +# 0xfe: Company ID +# 0xff: Device ID +# 0x02: Status +# 0x03: Configuration +# 0x04: Conversion rate +sub max1619_detect +{ + my ($file, $addr, $chip) = @_; + my $man_id = i2c_smbus_read_byte_data($file, 0xfe); + my $dev_id = i2c_smbus_read_byte_data($file, 0xff); + my $conf = i2c_smbus_read_byte_data($file, 0x03); + my $status = i2c_smbus_read_byte_data($file, 0x02); + my $convrate = i2c_smbus_read_byte_data($file, 0x04); + + return if $man_id != 0x4D; # Maxim + + if ($chip == 0) { # MAX1619 + return if $dev_id != 0x04 + or ($conf & 0x03) + or ($status & 0x61) + or $convrate >= 8; + } + if ($chip == 1) { # MAX1618 + return if $dev_id != 0x02 + or ($conf & 0x07) + or ($status & 0x63); + } + + return 7; +} + +# Registers used: +# 0x28: User ID +# 0x29: User ID2 +sub ite_overclock_detect +{ + my ($file, $addr) = @_; + + my $uid1 = i2c_smbus_read_byte_data($file, 0x28); + my $uid2 = i2c_smbus_read_byte_data($file, 0x29); + return if $uid1 != 0x83 || $uid2 != 0x12; + + return 6; +} + +# Registers used: +# 0x00: Configuration +# 0x48: Full I2C Address +# 0x58: Mfr ID +# 0x5b: Device ID +sub it8712_i2c_detect +{ + my ($file, $addr) = @_; + my $reg; + return unless i2c_smbus_read_byte_data($file, 0x48) == $addr; + return unless (i2c_smbus_read_byte_data($file, 0x00) & 0x90) == 0x10; + return unless i2c_smbus_read_byte_data($file, 0x58) == 0x90; + return if i2c_smbus_read_byte_data($file, 0x5b) != 0x12; + return 7 + ($addr == 0x2d); +} + +# Registers used: +# 0-63: SPD Data and Checksum (up to DDR2) +# 0-127: SPD data and CRC (DDR3) +sub eeprom_detect +{ + my ($file, $addr) = @_; + my $device_type = i2c_smbus_read_byte_data($file, 2); + my $checksum = 0; + + # Check the checksum or CRC16 for validity + if ($device_type >= 1 and $device_type <= 8) { + for (my $i = 0; $i < 63; $i++) { + $checksum += i2c_smbus_read_byte_data($file, $i); + } + $checksum &= 0xff; + + return 8 if $checksum == i2c_smbus_read_byte_data($file, 63); + } elsif ($device_type >= 9 && $device_type <= 12) { + # see JEDEC 21-C 4.1.2.11 2.4 + my $crc_coverage = i2c_smbus_read_byte_data($file, 0); + $crc_coverage = ($crc_coverage & 0x80) ? 117 : 126; + for (my $i = 0; $i < $crc_coverage; $i++) { + $checksum ^= i2c_smbus_read_byte_data($file, $i) << 8; + for (my $bit = 0; $bit < 8; $bit++) { + if ($checksum & 0x8000) { + $checksum = ($checksum << 1) ^ 0x1021; + } else { + $checksum <<= 1; + } + } + } + $checksum &= 0xffff; + + return 8 if ($checksum & 0xff) == i2c_smbus_read_byte_data($file, 126) and + ($checksum >> 8) == i2c_smbus_read_byte_data($file, 127); + + # note: if bit 7 of byte 32 is set, a jc42 sensor is at $addr-0x38 + } + + return; +} + +# Registers used: +# 0x00..0x07: DDC signature +sub ddcmonitor_detect +{ + my ($file, $addr) = @_; + + return unless + i2c_smbus_read_byte_data($file, 0x00) == 0x00 and + i2c_smbus_read_byte_data($file, 0x01) == 0xFF and + i2c_smbus_read_byte_data($file, 0x02) == 0xFF and + i2c_smbus_read_byte_data($file, 0x03) == 0xFF and + i2c_smbus_read_byte_data($file, 0x04) == 0xFF and + i2c_smbus_read_byte_data($file, 0x05) == 0xFF and + i2c_smbus_read_byte_data($file, 0x06) == 0xFF and + i2c_smbus_read_byte_data($file, 0x07) == 0x00; + + return 8; +} + +# Chip to detect: 0 = Poseidon I, 1 = Poseidon II, 2 = Scylla, +# 3 = Hermes, 4 = Heimdal, 5 = Heracles +# Registers used: +# 0x00-0x02: Identification (3 capital ASCII letters) +sub fsc_detect +{ + my ($file, $addr, $chip) = @_; + my $id; + + $id = chr(i2c_smbus_read_byte_data($file, 0x00)) + . chr(i2c_smbus_read_byte_data($file, 0x01)) + . chr(i2c_smbus_read_byte_data($file, 0x02)); + + return if $chip == 0 and $id ne 'PEG'; # Pegasus? aka Poseidon I + return if $chip == 1 and $id ne 'POS'; # Poseidon II + return if $chip == 2 and $id ne 'SCY'; # Scylla + return if $chip == 3 and $id ne 'HER'; # Hermes + return if $chip == 4 and $id ne 'HMD'; # Heimdal + return if $chip == 5 and $id ne 'HRC'; # Heracles + return if $chip == 6 and $id ne 'HDS'; # Hades + return if $chip == 7 and $id ne 'SYL'; # Syleus + + return 8; +} + +# Chip to detect: 0 = LM93, 1 = LM94 +# Registers used: +# 0x3E: Manufacturer ID +# 0x3F: Version/Stepping +sub lm93_detect +{ + my ($file, $addr, $chip) = @_; + my ($man_id, $dev_id); + + $man_id = i2c_smbus_read_byte_data($file, 0x3E); + $dev_id = i2c_smbus_read_byte_data($file, 0x3F); + + if ($chip == 0) { + return unless $man_id == 0x01 # National Semiconductor + and $dev_id == 0x73; # LM93 + } + if ($chip == 1) { + return unless $man_id == 0x01 # National Semiconductor + and $dev_id >= 0x79 + and $dev_id <= 0x7A; # LM94 + } + return 5; +} + +# Registers used: +# 0x3F: Revision ID +# 0x48: Address +# 0x4A, 0x4B, 0x4F, 0x57, 0x58: Reserved bits. +# We do not use 0x49's reserved bits on purpose. The register is named +# "VID4/Device ID" so it is doubtful bits 7-1 are really unused. +sub m5879_detect +{ + my ($file, $addr) = @_; + + return unless i2c_smbus_read_byte_data($file, 0x3F) == 0x01; + return unless i2c_smbus_read_byte_data($file, 0x48) == $addr; + + return unless (i2c_smbus_read_byte_data($file, 0x4A) & 0x06) == 0 + and (i2c_smbus_read_byte_data($file, 0x4B) & 0xFC) == 0 + and (i2c_smbus_read_byte_data($file, 0x4F) & 0xFC) == 0 + and (i2c_smbus_read_byte_data($file, 0x57) & 0xFE) == 0 + and (i2c_smbus_read_byte_data($file, 0x58) & 0xEF) == 0; + + return 7; +} + +# Registers used: +# 0x3E: Manufacturer ID +# 0x3F: Version/Stepping +# 0x47: VID (3 reserved bits) +# 0x49: VID4 (7 reserved bits) +sub smsc47m192_detect +{ + my ($file, $addr) = @_; + return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x55 + and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF0) == 0x20 + and (i2c_smbus_read_byte_data($file, 0x47) & 0x70) == 0x00 + and (i2c_smbus_read_byte_data($file, 0x49) & 0xFE) == 0x80; + return ($addr == 0x2d ? 6 : 5); +} + +# Chip to detect: 1 = DME1737, 2 = SCH5027 +# Registers used: +# 0x3E: Manufacturer ID +# 0x3F: Version/Stepping +# 0x73: Read-only test register (4 test bits) +# 0x8A: Read-only test register (7 test bits) +# 0xBA: Read-only test register (8 test bits) +sub dme1737_detect +{ + my ($file, $addr, $chip) = @_; + my $vendor = i2c_smbus_read_byte_data($file, 0x3E); + my $verstep = i2c_smbus_read_byte_data($file, 0x3F); + + return unless $vendor == 0x5C; # SMSC + + if ($chip == 1) { # DME1737 + return unless ($verstep & 0xF8) == 0x88 and + (i2c_smbus_read_byte_data($file, 0x73) & 0x0F) == 0x09 and + (i2c_smbus_read_byte_data($file, 0x8A) & 0x7F) == 0x4D; + } elsif ($chip == 2) { # SCH5027 + return unless $verstep >= 0x69 and $verstep <= 0x6F and + i2c_smbus_read_byte_data($file, 0xBA) == 0x0F; + } + + return ($addr == 0x2e ? 6 : 5); +} + +# Chip to detect: 1 = F75111R/RG/N, 2 = F75121R/F75122R/RG, 3 = F75373S/SG, +# 4 = F75375S/SP, 5 = F75387SG/RG, 6 = F75383M/S/F75384M/S, +# 7 = custom power control IC +# Registers used: +# 0x5A-0x5B: Chip ID +# 0x5D-0x5E: Vendor ID +sub fintek_detect +{ + my ($file, $addr, $chip) = @_; + my $chipid = (i2c_smbus_read_byte_data($file, 0x5A) << 8) + | i2c_smbus_read_byte_data($file, 0x5B); + my $vendid = (i2c_smbus_read_byte_data($file, 0x5D) << 8) + | i2c_smbus_read_byte_data($file, 0x5E); + + return unless $vendid == 0x1934; # Fintek ID + + if ($chip == 1) { # F75111R/RG/N + return unless $chipid == 0x0300; + } elsif ($chip == 2) { # F75121R/F75122R/RG + return unless $chipid == 0x0301; + } elsif ($chip == 3) { # F75373S/SG + return unless $chipid == 0x0204; + } elsif ($chip == 4) { # F75375S/SP + return unless $chipid == 0x0306; + } elsif ($chip == 5) { # F75387SG/RG + return unless $chipid == 0x0410; + } elsif ($chip == 6) { # F75383M/S/F75384M/S + # The datasheet has 0x0303, but Fintek say 0x0413 is also + # possible + return unless $chipid == 0x0303 || $chipid == 0x0413; + } elsif ($chip == 7) { # custom power control IC + return unless $chipid == 0x0302; + } + + return 7; +} + +# Chips to detect: 0 = EMC1023, 1 = EMC1043, 2 = EMC1053, 3 = EMC1063 +# Registers used: +# 0xed: Device ID register +# 0xfe: Vendor ID register +# 0xff: Revision register +sub emc1023_detect +{ + my ($file, $addr, $chip) = @_; + my $dev_id = i2c_smbus_read_byte_data($file, 0xed); + my $man_id = i2c_smbus_read_byte_data($file, 0xfe); + my $rev = i2c_smbus_read_byte_data($file, 0xff); + + return unless $man_id == 0x5d; # SMSC + return unless $rev <= 1; + + if ($chip == 0) { + return if ($addr == 0x4c) && ($dev_id != 0x04); # EMC1023-1 + return if ($addr == 0x4d) && ($dev_id != 0x05); # EMC1023-2 + return if ($addr == 0x48) && ($dev_id != 0x06); # EMC1023-3 + return if ($addr == 0x49) && ($dev_id != 0x07); # EMC1023-4 + } elsif ($chip == 1) { + if ($addr == 0x4c) { # EMC1043-1, EMC1043-5 + return unless ($dev_id == 0x0c) || ($dev_id == 0x2c); + } + return if ($addr == 0x4d) && ($dev_id != 0x0d); # EMC1043-2 + return if ($addr == 0x48) && ($dev_id != 0x0e); # EMC1043-3 + return if ($addr == 0x49) && ($dev_id != 0x0f); # EMC1043-4 + } elsif ($chip == 2) { + return if ($addr == 0x4c) && ($dev_id != 0x3c); # EMC1053-1 + return if ($addr == 0x4d) && ($dev_id != 0x3d); # EMC1053-2 + return if ($addr == 0x48) && ($dev_id != 0x3e); # EMC1053-3 + return if ($addr == 0x49) && ($dev_id != 0x3f); # EMC1053-4 + } elsif ($chip == 3) { + return if ($addr == 0x4c) && ($dev_id != 0x30); # EMC1063-1 + return if ($addr == 0x4d) && ($dev_id != 0x31); # EMC1063-2 + return if ($addr == 0x48) && ($dev_id != 0x32); # EMC1063-3 + return if ($addr == 0x49) && ($dev_id != 0x33); # EMC1063-4 + } + + return 7; +} + +# Chip to detect: 0 = EMC1403, 1 = EMC1404, 2 = EMC2103, 3 = EMC1423, +# 4 = EMC1002, 5 = EMC1033, 6 = EMC1046, 7 = EMC1047, 8 = EMC1072, +# 9 = EMC1073, 10 = EMC1074, 11 = EMC1402, 12 = EMC1424, +# 13 = EMC2104, 14 = EMC1422 +# Registers used: +# 0xfd: Device ID register +# 0xfe: Vendor ID register +# 0xff: Revision register +sub emc1403_detect +{ + my ($file, $addr, $chip) = @_; + my $dev_id = i2c_smbus_read_byte_data($file, 0xfd); + my $man_id = i2c_smbus_read_byte_data($file, 0xfe); + my $rev = i2c_smbus_read_byte_data($file, 0xff); + + return unless $man_id == 0x5d; # SMSC + + if ($chip == 0) { # EMC1403 + return unless $dev_id == 0x21; + return unless $rev == 0x01 || $rev == 0x04; + } elsif ($chip == 1) { # EMC1404 + return unless $dev_id == 0x25; + return unless $rev == 0x01 || $rev == 0x04; + } elsif ($chip == 2) { # EMC2103 + return unless ($dev_id == 0x24) || ($dev_id == 0x26); + return unless $rev == 0x01; + } elsif ($chip == 3) { # EMC1423 + return unless $dev_id == 0x23; + return unless $rev == 0x01 || $rev == 0x04; + } elsif ($chip == 4) { # EMC1002 + return unless ($dev_id == 0x02) || ($dev_id == 0x03); + return unless $rev == 0x01; + } elsif ($chip == 5) { # EMC1033 + return unless ($dev_id == 0x0a) || ($dev_id == 0x0b); + return unless $rev == 0x01; + } elsif ($chip == 6) { # EMC1046 + return unless $dev_id == 0x1a; + return unless $rev == 0x01; + } elsif ($chip == 7) { # EMC1047 + return unless $dev_id == 0x1c; + return unless $rev == 0x01; + } elsif ($chip == 8) { # EMC1072 + return unless $dev_id == 0x20; + return unless $rev == 0x03; + } elsif ($chip == 9) { # EMC1073 + return unless $dev_id == 0x21; + return unless $rev == 0x03; + } elsif ($chip == 10) { # EMC1074 + return unless $dev_id == 0x25; + return unless $rev == 0x03; + } elsif ($chip == 11) { # EMC1402 + return unless $dev_id == 0x20; + return unless $rev == 0x01 || $rev == 0x04; + } elsif ($chip == 12) { # EMC1424 + return unless $dev_id == 0x27; + return unless $rev == 0x01 || $rev == 0x04; + } elsif ($chip == 13) { # EMC2104 + return unless $dev_id == 0x1d; + return unless $rev == 0x02; + } elsif ($chip == 14) { # EMC1422 + return unless $dev_id == 0x22; + return unless $rev == 0x01 || $rev == 0x04; + } + + return 6; +} + +# Chip to detect: 0 = W83L784R/AR/G, 1 = W83L785R/G, 2 = W83L786NR/NG/R/G, +# 3 = W83L785TS-S +# Registers used: +# 0x40: Configuration +# 0x4a: Full I2C Address (W83L784R only) +# 0x4b: I2C addresses of emulated LM75 chips (W83L784R only) +# 0x4c: Winbond Vendor ID (Low Byte) +# 0x4d: Winbond Vendor ID (High Byte) +# 0x4e: Chip ID +sub w83l784r_detect +{ + my ($file, $addr, $chip) = @_; + my ($reg, @res); + + return unless (i2c_smbus_read_byte_data($file, 0x40) & 0x80) == 0x00; + return if $chip == 0 + and i2c_smbus_read_byte_data($file, 0x4a) != $addr; + return unless i2c_smbus_read_byte_data($file, 0x4c) == 0xa3; + return unless i2c_smbus_read_byte_data($file, 0x4d) == 0x5c; + + $reg = i2c_smbus_read_byte_data($file, 0x4e); + return if $chip == 0 and $reg != 0x50; + return if $chip == 1 and $reg != 0x60; + return if $chip == 2 and $reg != 0x80; + return if $chip == 3 and $reg != 0x70; + + return 8 if $chip != 0; # No subclients + + @res = (8); + $reg = i2c_smbus_read_byte_data($file, 0x4b); + push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08; + push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80; + return @res; +} + +# Chip to detect: MAX6639 +# Registers used: +# 0x3d: Device ID +# 0x3e: Manufacturer ID +# 0x3f: Chip revision +sub max6639_detect +{ + my ($file, $addr) = @_; + my ($man_id, $dev_id, $rev); + + $dev_id = i2c_smbus_read_byte_data($file, 0x3d); + $man_id = i2c_smbus_read_byte_data($file, 0x3e); + $rev = i2c_smbus_read_byte_data($file, 0x3f); + + return unless $man_id == 0x4d; # Maxim + return unless $dev_id == 0x58; # MAX6639 + return unless $rev == 0x00; + + return 6; +} + +# Chip to detect: MAX6642 +# Registers used: +# 0x02: Status register +# 0x03: Configuration register +# 0xfe: Manufacturer ID +# 0x04, 0x06, 0xff: No registers +# We use the 0x04, 0x06 and 0xff addresses (unused) to improve reliability. +# These are not real registers and will always return the last returned value. +# This isn't documented. +sub max6642_detect +{ + my ($file, $addr) = @_; + my ($man_id, $conf, $status); + + $man_id = i2c_smbus_read_byte_data($file, 0xfe); + return unless $man_id == 0x4d; # Maxim + return if i2c_smbus_read_byte_data($file, 0x04, NO_CACHE) != $man_id; + return if i2c_smbus_read_byte_data($file, 0x06, NO_CACHE) != $man_id; + return if i2c_smbus_read_byte_data($file, 0xff, NO_CACHE) != $man_id; + + $status = i2c_smbus_read_byte_data($file, 0x02); + # Bit 5, 3, 1 and 0 should be zero + return unless ($status & 0x2b) == 0x00; + return if i2c_smbus_read_byte_data($file, 0x04, NO_CACHE) != $status; + return if i2c_smbus_read_byte_data($file, 0x06, NO_CACHE) != $status; + return if i2c_smbus_read_byte_data($file, 0xff, NO_CACHE) != $status; + + $conf = i2c_smbus_read_byte_data($file, 0x03); + # The 4 lower bits should be zero + return unless ($conf & 0x0f) == 0x00; + + return 5; +} + +sub max6655_detect +{ + my ($file, $addr) = @_; + + # checking RDID (Device ID) + return unless i2c_smbus_read_byte_data($file, 0xfe) == 0x0a; + # checking RDRV (Manufacturer ID) + return unless i2c_smbus_read_byte_data($file, 0xff) == 0x4d; + # checking unused bits (conversion rate, extended temperature) + return unless i2c_smbus_read_byte_data($file, 0x04) & 0xf8; + return unless i2c_smbus_read_byte_data($file, 0x10) & 0x1f; + return unless i2c_smbus_read_byte_data($file, 0x11) & 0x1f; + return unless i2c_smbus_read_byte_data($file, 0x12) & 0x1f; + + return 6; +} + +# Chip to detect: 0 = STTS424, 1 = SE97/SE97B, 2 = SE98, 3 = ADT7408, +# 4 = TS3000/TSE2002, 5 = MAX6604, 6 = MCP98242, +# 7 = MCP98243, 8 = MCP9843, 9 = CAT6095 / CAT34TS02, +# 10 = STTS424E, 11 = STTS2002, 12 = STTS3000 +# 13 = MCP9804, 14 = AT30TS00, 15 = MCP98244, +# 16 = TSE2004, 17 = TS3001, 18 = MCP9808, +# 19 = CAT34TS02C, 20 = Giantec GT30TS00, +# 21 = CAT34TS04 +# Registers used: +# 0x00: Capabilities +# 0x01: Configuration +# 0x06: Manufacturer ID +# 0x07: Device ID +sub jedec_JC42_4_detect +{ + my ($file, $addr, $chip) = @_; + my ($reg, $manid, $devid); + + # We test the MSB only at first, because not all chips enjoy + # word access. + + # Check for unused bits + $reg = i2c_smbus_read_byte_data($file, 0x00); + return if $reg & 0xff; + $reg = i2c_smbus_read_byte_data($file, 0x01); + return if $reg & 0xf8; + + # Check for manufacturer and device ID + $manid = i2c_smbus_read_byte_data($file, 0x06); + $devid = i2c_smbus_read_byte_data($file, 0x07); + + if ($chip == 0) { + return unless $manid == 0x10; # STMicrolectronics + return unless $devid == 0x01; # STTS424 + } elsif ($chip == 1) { + return unless $manid == 0x11; # NXP + return unless $devid == 0xa2; # SE97 + } elsif ($chip == 2) { + return unless $manid == 0x11; # NXP + return unless $devid == 0xa1; # SE98 + } elsif ($chip == 3) { + return unless $manid == 0x11; # ADT + return unless $devid == 0x08; # ADT7408 + } elsif ($chip == 4) { + return unless $manid == 0x00; # IDT + return unless $devid == 0x29; # TS3000/TSE2002 + } elsif ($chip == 5) { + return unless $manid == 0x00; # MAXIM + return unless $devid == 0x3e; # MAX6604 + } elsif ($chip == 6) { + return unless $manid == 0x00; # MCP + return unless $devid == 0x20; # MCP98242 + } elsif ($chip == 7) { + return unless $manid == 0x00; # MCP + return unless $devid == 0x21; # MCP98243 + } elsif ($chip == 8) { + return unless $manid == 0x00; # MCP + return unless $devid == 0x00; # MCP9843 + } elsif ($chip == 9) { + return unless $manid == 0x1b; # ONS + return unless $devid == 0x08; # CAT6095 / CAT34TS02 + } elsif ($chip == 10) { + return unless $manid == 0x10; # STMicrolectronics + return unless $devid == 0x00; # STTS424E02 + } elsif ($chip == 11) { + return unless $manid == 0x10; # STMicrolectronics + return unless $devid == 0x03; # STTS2002 + } elsif ($chip == 12) { + return unless $manid == 0x10; # STMicrolectronics + return unless $devid == 0x02; # STTS3000 + } elsif ($chip == 13) { + return unless $manid == 0x00; # MCP + return unless $devid == 02; # MCP9804 + } elsif ($chip == 14) { + return unless $manid == 0x00; # Atmel + return unless $devid == 0x82; # AT30TS00 + } elsif ($chip == 15) { + return unless $manid == 0x00; # MCP + return unless $devid == 0x22; # MCP98244 + } elsif ($chip == 18) { + return unless $manid == 0x00; # MCP + return unless $devid == 0x04; # MCP9808 + } elsif ($chip == 19) { + return unless $manid == 0x1b; # ON + return unless $devid == 0x0a; # CAT34TS02C + } elsif ($chip == 20) { + return unless $manid == 0x1c || $manid == 0x13; # Giantec + return unless $devid == 0x22; # GT30TS00 + } elsif ($chip == 21) { + return unless $manid == 0x1b; # ONS + return unless $devid == 0x22; # CAT34TS04 + } + + # Now, do it all again with words. Note that we get + # the MSB first, so all value checks are byte-swapped. + + # Check for unused bits + $reg = i2c_smbus_read_word_data($file, 0x00); + return if $reg < 0 || $reg & 0x00ff; + + $manid = i2c_smbus_read_word_data($file, 0x06); + $devid = i2c_smbus_read_word_data($file, 0x07); + return if $manid < 0 || $devid < 0; + if ($chip == 0) { + return unless $manid == 0x4a10; # STMicrolectronics + return unless ($devid & 0xfeff) == 0x0001; # STTS424 + } elsif ($chip == 1) { + return unless $manid == 0x3111; # NXP + return unless ($devid & 0xfcff) == 0x00a2; # SE97 + } elsif ($chip == 2) { + return unless $manid == 0x3111; # NXP + return unless ($devid & 0xfcff) == 0x00a1; # SE98 + } elsif ($chip == 3) { + return unless $manid == 0xd411; # ADT + return unless $devid == 0x0108; # ADT7408 + } elsif ($chip == 4) { + return unless $manid == 0xb300; # IDT + return unless ($devid & 0x00ff) == 0x0029; # TS3000/TSE2002 + } elsif ($chip == 5) { + return unless $manid == 0x4d00; # MAXIM + return unless $devid == 0x003e; # MAX6604 + } elsif ($chip == 6) { + return unless $manid == 0x5400; # MCP + return unless ($devid & 0xfcff) == 0x0020; # MCP98242 + } elsif ($chip == 7) { + return unless $manid == 0x5400; # MCP + return unless ($devid & 0xfcff) == 0x0021; # MCP98243 + } elsif ($chip == 8) { + return unless $manid == 0x5400; # MCP + return unless ($devid & 0xfcff) == 0x0000; # MCP9843 + } elsif ($chip == 9) { + return unless $manid == 0x091b; # ONS + return unless ($devid & 0xe0ff) == 0x0008; # CAT6095 / CAT34TS02 + } elsif ($chip == 10) { + return unless $manid == 0x4a10; # STMicrolectronics + return unless ($devid & 0xfeff) == 0x0000; # STTS424E02 + } elsif ($chip == 11) { + return unless $manid == 0x4a10; # STMicrolectronics + return unless ($devid & 0xfeff) == 0x0003; # STTS2002 + } elsif ($chip == 12) { + return unless $manid == 0x4a10; # STMicrolectronics + return unless ($devid & 0xfeff) == 0x0002; # STTS3000 + } elsif ($chip == 13) { + return unless $manid == 0x5400; # MCP + return unless ($devid & 0xfcff) == 0x0002; # MCP9804 + } elsif ($chip == 14) { + return unless $manid == 0x1f00; # Atmel + return unless ($devid & 0xfeff) == 0x0082; # AT30TS00 + } elsif ($chip == 15) { + return unless $manid == 0x5400; # MCP + return unless ($devid & 0xfcff) == 0x0022; # MCP98244 + } elsif ($chip == 16) { + return unless $manid == 0xb300; # IDT + return unless ($devid & 0x00ff) == 0x0022; # TSE2004 + } elsif ($chip == 17) { + return unless $manid == 0xb300; # IDT + return unless ($devid & 0x00ff) == 0x0030; # TS3001 + } elsif ($chip == 18) { + return unless $manid == 0x5400; # MCP + return unless ($devid & 0xfcff) == 0x0004; # MCP9808 + } elsif ($chip == 19) { + return unless $manid == 0x091b; # ONS + return unless ($devid & 0xf0ff) == 0x000a; # CAT34TS02C + } elsif ($chip == 20) { + return unless $manid == 0x681c || $manid == 0x2d13; # Giantec + return unless ($devid & 0x00ff) == 0x0022; # GT30TS00 + } elsif ($chip == 21) { + return unless $manid == 0x091b; # ONS + return unless ($devid & 0xf0ff) == 0x0022; # CAT34TS04 + } + + return 5; +} + +# This isn't very good detection. +# Verify the i2c address, and the stepping ID (which is 0xb0 on +# my chip but could be different for others... +sub vt1211_i2c_detect +{ + my ($file, $addr) = @_; + return unless (i2c_smbus_read_byte_data($file, 0x48) & 0x7f) == $addr; + return unless i2c_smbus_read_byte_data($file, 0x3f) == 0xb0; + return 2; +} + +# All ISA detection functions below take at least 1 parameter: +# $_[0]: Address +# Some of these functions which can detect more than one type of device, +# take a second parameter: +# $_[1]: Chip to detect + +# Chip to detect: 0 = LM78, 2 = LM79 +sub lm78_isa_detect +{ + my ($addr, $chip) = @_; + my $val = inb($addr + 1); + return if inb($addr + 2) != $val or inb($addr + 3) != $val or + inb($addr + 7) != $val; + + $val = inb($addr + 5); + outb($addr + 5, ~$val & 0x7f); + if ((inb($addr+5) & 0x7f) != (~ $val & 0x7f)) { + outb($addr+5, $val); + return; + } + + return unless (isa_read_i5d6($addr, 0x40) & 0x80) == 0x00; + my $reg = isa_read_i5d6($addr, 0x49); + return if $chip == 0 && ($reg != 0x00 && $reg != 0x20 && $reg != 0x40); + return if $chip == 2 && ($reg & 0xfe) != 0xc0; + + # Explicitly prevent misdetection of Winbond chips + $reg = isa_read_i5d6($addr, 0x4f); + return if $reg == 0xa3 || $reg == 0x5c; + + # Explicitly prevent misdetection of ITE chips + $reg = isa_read_i5d6($addr, 0x58); + return if $reg == 0x90; + + return 6; +} + +# Chip to detect: 0 = W83781D, 1 = W83782D +sub w83781d_isa_detect +{ + my ($addr, $chip) = @_; + my ($reg1, $reg2); + my $val = inb($addr + 1); + return if inb($addr + 2) != $val or inb($addr + 3) != $val or + inb($addr + 7) != $val; + + $val = inb($addr + 5); + outb($addr+5, ~$val & 0x7f); + if ((inb($addr+5) & 0x7f) != (~ $val & 0x7f)) { + outb($addr+5, $val); + return; + } + + $reg1 = isa_read_i5d6($addr, 0x4e); + $reg2 = isa_read_i5d6($addr, 0x4f); + return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or + (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c); + return unless ($reg1 & 0x07) == 0x00; + $reg1 = isa_read_i5d6($addr, 0x58); + return if $chip == 0 && ($reg1 & 0xfe) != 0x10; + return if $chip == 1 && ($reg1 & 0xfe) != 0x30; + + return 8; +} + +######## +# IPMI # +######## + +# Returns: number of IPMI interfaces found +sub ipmi_from_smbios +{ + my ($version, $if, @ipmi_if); + my $ipmi_driver = "to-be-written"; # ipmisensors + + return 0 unless check_dmidecode_version(); + + # Parse the output of dmidecode into an array of IPMI interfaces. + # Each entry is a hash with the following keys: type and addr. + $if = -1; + open(local *DMIDECODE, "dmidecode -t 38 2>/dev/null |") or return 0; + while () { + if (m/^IPMI Device Information/) { + $if++; + next; + } + next unless $if >= 0; + + if (m/^\tInterface Type: (.*)$/) { + $ipmi_if[$if]->{type} = "IPMI BMC $1"; + $ipmi_if[$if]->{type} =~ s/ \(.*//; + next; + } + if (m/^\tBase Address: (0x[0-9A-Fa-f]+) \(I\/O\)$/) { + $ipmi_if[$if]->{addr} = oct($1); + next; + } + } + close(DMIDECODE); + + foreach $if (@ipmi_if) { + if (exists $if->{addr}) { + printf("\%-60s", sprintf("Found `\%s' at 0x\%x... ", + $if->{type}, $if->{addr})); + } else { + printf("\%-60s", sprintf("Found `\%s'... ", + $if->{type})); + } + print "Success!\n". + " (confidence 8, driver `$ipmi_driver')\n"; + my $new_hash = { + conf => 8, + isa_addr => $if->{addr} || 0, + chipname => $if->{type}, + }; + add_isa_to_chips_detected($ipmi_driver, $new_hash); + } + + return scalar @ipmi_if; +} + +# We simply look for a register at standard locations. +# For KCS, use the STATUS register. For SMIC, use the FLAGS register. +# Incidentally they live at the same offset. +sub ipmi_detect +{ + my ($addr) = @_; + return if inb($addr + 3) == 0xff; + return 4; +} + +################### +# ALIAS DETECTION # +################### + +# These functions take at least 3 parameters: +# $_[0]: ISA/LPC address +# $_[1]: I2C file handle +# $_[2]: I2C address +# Some of these functions may take extra parameters. +# They return 1 if both devices are the same, 0 if not. + +# Extra parameters: +# $_[3]: First limit register to compare +# $_[4]: Last limit register to compare +sub winbond_alias_detect +{ + my ($isa_addr, $file, $i2c_addr, $first, $last) = @_; + my $i; + + return 0 unless isa_read_i5d6($isa_addr, 0x48) == $i2c_addr; + for ($i = $first; $i <= $last; $i++) { + return 0 unless isa_read_i5d6($isa_addr, $i) == + i2c_smbus_read_byte_data($file, $i); + } + return 1; +} + +############################ +# PCI CHIP / CPU DETECTION # +############################ + +sub sis5595_pci_detect +{ + return unless exists $pci_list{'1039:0008'}; + return 9; +} + +sub via686a_pci_detect +{ + return unless exists $pci_list{'1106:3057'}; + return 9; +} + +sub via8231_pci_detect +{ + return unless exists $pci_list{'1106:8235'}; + return 9; +} + +sub amd_pci_detect +{ + my $dev_id; + while (defined($dev_id = shift)) { + return 9 if exists $pci_list{"1022:$dev_id"}; + } + return undef; +} + +sub fam10h_pci_detect +{ + return unless exists $pci_list{'1022:1203'}; + + # Errata 319 (Inaccurate Temperature Measurement) affects + # revisions DR-BA, DR-B2 and DR-B3, all have model number = 2. + # Revisions RB-C2 and HY-D0 are also affected. + my $probecpu; + foreach $probecpu (@cpu) { + next unless $probecpu->{vendor_id} eq 'AuthenticAMD' && + $probecpu->{'cpu family'} == 0x10; + + next if $probecpu->{model} < 4; # DR-B* + next if $probecpu->{model} == 8; # HY-D0 + if ($probecpu->{model} == 4 && $probecpu->{stepping} <= 2) { # RB-C2 + my @dram_cfg = split /\n/, `setpci -d 1022:1202 94.L 2>/dev/null`; + next unless @dram_cfg >= 1; + next unless hex($dram_cfg[0]) & 0x00000100; # DDR3 + } + + return 9; + } + + return; +} + +sub intel_amb_detect +{ + if ((exists $pci_list{'8086:25f0'}) || # Intel 5000 + (exists $pci_list{'8086:4030'})) { # Intel 5400 + return 9; + } + return; +} + +sub intel_5500_detect +{ + return unless exists $pci_list{'8086:3438'}; + return 5; +} + +sub cpuid +{ + my ($cpu_nr, $eax) = @_; + + sysopen(CPUID, "/dev/cpu/$cpu_nr/cpuid", O_RDONLY) or return; + binmode CPUID; + sysseek(CPUID, $eax, SEEK_SET) + or die "Cannot seek /dev/cpu/$cpu_nr/cpuid"; + sysread(CPUID, my $data, 16) + or die "Cannot read /dev/cpu/$cpu_nr/cpuid"; + close CPUID; + + return unpack("L4", $data); +} + +sub coretemp_detect +{ + my $probecpu; + + foreach $probecpu (@cpu) { + next unless $probecpu->{vendor_id} eq 'GenuineIntel' && + $probecpu->{'cpuid level'} >= 6; + + # Now we check for the DTS flag + my @regs = cpuid($probecpu->{nr}, 6); + return unless @regs == 4; + return 9 if ($regs[0] & (1 << 0)); # eax, bit 0 + } + return; +} + +sub via_c7_detect +{ + my $probecpu; + foreach $probecpu (@cpu) { + if ($probecpu->{vendor_id} eq 'CentaurHauls' && + $probecpu->{'cpu family'} == 6 && + ($probecpu->{model} == 0xa || + $probecpu->{model} == 0xd)) { + return 9; + } + } + return; +} + +sub via_nano_detect +{ + my $probecpu; + foreach $probecpu (@cpu) { + if ($probecpu->{vendor_id} eq 'CentaurHauls' && + $probecpu->{'cpu family'} == 6 && + $probecpu->{model} == 0xf) { + return 9; + } + } + return; +} + +################# +# SPECIAL MODES # +################# + +sub show_i2c_stats +{ + my ($chip, $addr, %histo, $chips); + + # Gather the data + foreach $chip (@chip_ids) { + next unless defined $chip->{i2c_addrs}; + $chips++; + foreach my $addr (@{$chip->{i2c_addrs}}) { + $histo{$addr}++; + } + } + + # Display the data + printf "\%d I2C chips known, \%d I2C addresses probed\n\n", + $chips, scalar keys %histo; + print " 0 1 2 3 4 5 6 7 8 9 a b c d e f\n". + "00: "; + for (my $addr = 0x03; $addr <= 0x77; $addr++) { + printf("\n\%02x:", $addr) if ($addr % 16) == 0; + if (defined $histo{$addr}) { + printf ' %02d', $histo{$addr}; + } else { + print ' --'; + } + } + print "\n"; +} + +################ +# MAIN PROGRAM # +################ + +# $_[0]: reference to a list of chip hashes +sub print_chips_report +{ + my ($listref) = @_; + my $data; + + foreach $data (@$listref) { + my $is_i2c = exists $data->{i2c_addr}; + my $is_isa = exists $data->{isa_addr}; + print " * "; + if ($is_i2c) { + printf "Bus `%s'\n", $i2c_adapters[$data->{i2c_devnr}]->{name}; + printf " Busdriver `%s', I2C address 0x%02x", + $i2c_adapters[$data->{i2c_devnr}]->{driver}, $data->{i2c_addr}; + if (exists $data->{i2c_sub_addrs}) { + print " (and"; + my $sub_addr; + foreach $sub_addr (@{$data->{i2c_sub_addrs}}) { + printf " 0x%02x", $sub_addr; + } + print ")" + } + print "\n "; + } + if ($is_isa) { + print "ISA bus"; + if ($data->{isa_addr}) { + printf ", address 0x%x", $data->{isa_addr}; + } + print " (Busdriver `i2c-isa')" + unless kernel_version_at_least(2, 6, 18); + print "\n "; + } + printf "Chip `%s' (confidence: %d)\n", + $data->{chipname}, $data->{conf}; + } +} + +sub generate_modprobes +{ + my ($driver, $detection, $adap); + my ($configfile, %bus_modules, %hwmon_modules); + + foreach $driver (keys %chips_detected) { + foreach $detection (@{$chips_detected{$driver}}) { + # Tag adapters which host hardware monitoring chips we want to access + if (exists $detection->{i2c_devnr} + && !exists $detection->{isa_addr}) { + $i2c_adapters[$detection->{i2c_devnr}]->{used}++; + } + + # i2c-isa is loaded automatically (as a dependency) + # since 2.6.14, and will soon be gone. + if (exists $detection->{isa_addr} + && !kernel_version_at_least(2, 6, 18)) { + $bus_modules{"i2c-isa"}++ + } + } + if ($driver eq "ipmisensors") { + $bus_modules{"ipmi-si"}++; + } + } + + # Handle aliases + # As of kernel 2.6.28, alias detection is handled by kernel drivers + # directly, so module options are no longer needed. + unless (kernel_version_at_least(2, 6, 28)) { + foreach $driver (keys %chips_detected) { + my @optionlist = (); + foreach $detection (@{$chips_detected{$driver}}) { + next unless exists $detection->{i2c_addr} + && exists $detection->{isa_addr} + && $i2c_adapters[$detection->{i2c_devnr}]->{used}; + + push @optionlist, sprintf("%d,0x%02x", + $detection->{i2c_devnr}, + $detection->{i2c_addr}); + } + + next if not @optionlist; + $configfile = "# hwmon module options\n" + unless defined $configfile; + $configfile .= "options $driver ignore=". + (join ",", @optionlist)."\n"; + } + } + + # If we added any module option to handle aliases, we need to load all + # the adapter drivers so that the numbers will be the same. If not, then + # we only load the adapter drivers which are useful. + foreach $adap (@i2c_adapters) { + next unless defined $adap; + next if $adap->{autoload}; + next if $adap->{driver} eq 'UNKNOWN'; + next if not defined $configfile and not $adap->{used}; + $bus_modules{$adap->{driver}}++; + } + + # Now determine the chip probe lines + foreach $driver (keys %chips_detected) { + next if not @{$chips_detected{$driver}}; + if ($driver eq "to-be-written") { + print "Note: there is no driver for ${$chips_detected{$driver}}[0]{chipname} yet.\n". + "Check http://www.lm-sensors.org/wiki/Devices for updates.\n\n"; + } elsif (!is_module_builtin($driver)) { + open(local *INPUTFILE, "modprobe -l $driver 2>/dev/null |"); + local $_; + my $modulefound = 0; + while () { + if (m@/@) { + $modulefound = 1; + last; + } + } + close(INPUTFILE); + # Check return value from modprobe in case modprobe -l + # isn't supported + if ((($? >> 8) == 0) && ! $modulefound) { + print "Warning: the required module $driver is not currently installed\n". + "on your system. Check http://www.lm-sensors.org/wiki/Devices for\n". + "driver availability.\n\n"; + } else { + $hwmon_modules{$driver}++ + unless hwmon_is_autoloaded($driver); + } + } + } + + my @bus_modules = sort keys %bus_modules; + my @hwmon_modules = sort keys %hwmon_modules; + return ($configfile, \@bus_modules, \@hwmon_modules); +} + +sub write_config +{ + my ($configfile, $bus_modules, $hwmon_modules) = @_; + + if (defined $configfile) { + my $have_modprobe_d = -d '/etc/modprobe.d'; + printf "Do you want to \%s /etc/modprobe.d/lm_sensors.conf? (\%s): ", + (-e '/etc/modprobe.d/lm_sensors.conf' ? 'overwrite' : 'generate'), + ($have_modprobe_d ? 'YES/no' : 'yes/NO'); + $_ = read_answer(); + if (($have_modprobe_d and not m/^\s*n/i) or m/^\s*y/i) { + unless ($have_modprobe_d) { + mkdir('/etc/modprobe.d', 0777) + or die "Sorry, can't create /etc/modprobe.d ($!)"; + } + open(local *MODPROBE_D, ">/etc/modprobe.d/lm_sensors.conf") + or die "Sorry, can't create /etc/modprobe.d/lm_sensors.conf ($!)"; + print MODPROBE_D "# Generated by sensors-detect on " . scalar localtime() . "\n"; + print MODPROBE_D $configfile; + close(MODPROBE_D); + } else { + print "To make the sensors modules behave correctly, add these lines to\n". + "/etc/modprobe.conf:\n\n"; + print "#----cut here----\n". + $configfile. + "#----cut here----\n\n"; + } + } + + my $have_sysconfig = -d '/etc/sysconfig'; + printf "Do you want to \%s /etc/sysconfig/lm_sensors? (\%s): ", + (-e '/etc/sysconfig/lm_sensors' ? 'overwrite' : 'generate'), + ($have_sysconfig ? 'YES/no' : 'yes/NO'); + $_ = read_answer(); + if (($have_sysconfig and not m/^\s*n/i) or m/^\s*y/i) { + unless ($have_sysconfig) { + mkdir('/etc/sysconfig', 0777) + or die "Sorry, can't create /etc/sysconfig ($!)"; + } + open(local *SYSCONFIG, ">/etc/sysconfig/lm_sensors") + or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)"; + print SYSCONFIG "# Generated by sensors-detect on " . scalar localtime() . "\n"; + print SYSCONFIG <<'EOT'; +# This file is sourced by /etc/init.d/lm_sensors and defines the modules to +# be loaded/unloaded. +# +# The format of this file is a shell script that simply defines variables: +# HWMON_MODULES for hardware monitoring driver modules, and optionally +# BUS_MODULES for any required bus driver module (for example for I2C or SPI). + +EOT + print SYSCONFIG "BUS_MODULES=\"", join(" ", @{$bus_modules}), "\"\n" + if @{$bus_modules}; + print SYSCONFIG "HWMON_MODULES=\"", join(" ", @{$hwmon_modules}), "\"\n"; + close(SYSCONFIG); + + if ($systemd_systemctl && $systemd_system_dir) { + if (-f "$systemd_system_dir/lm_sensors.service") { + system($systemd_systemctl, "enable", "lm_sensors.service"); + system($systemd_systemctl, "start", "lm_sensors.service"); + # All done, don't check for /etc/init.d/lm_sensors + } else { + print "Copy prog/init/lm_sensors.service to $systemd_system_dir\n". + "and run 'systemctl enable lm_sensors.service'\n". + "for initialization at boot time.\n"; + } + return; + } + + print "Copy prog/init/lm_sensors.init to /etc/init.d/lm_sensors\n". + "for initialization at boot time.\n" + unless -f "/etc/init.d/lm_sensors"; + + if (-x "/sbin/insserv" && -f "/etc/init.d/lm_sensors") { + system("/sbin/insserv", "/etc/init.d/lm_sensors"); + } elsif (-x "/sbin/chkconfig" && -f "/etc/init.d/lm_sensors") { + system("/sbin/chkconfig", "lm_sensors", "on"); + if (-x "/sbin/service") { + system("/sbin/service", "lm_sensors", "start"); + } + } else { + print "You should now start the lm_sensors service to load the required\n". + "kernel modules.\n\n"; + } + } else { + print "To load everything that is needed, add this to one of the system\n". + "initialization scripts (e.g. /etc/rc.d/rc.local):\n\n"; + print "#----cut here----\n"; + if (@{$bus_modules}) { + print "# Adapter drivers\n"; + print "modprobe $_\n" foreach (@{$bus_modules}); + } + print "# Chip drivers\n"; + print "modprobe $_\n" foreach (@{$hwmon_modules}); + print((-e '/usr/bin/sensors' ? + "/usr/bin/sensors -s\n" : + "/usr/local/bin/sensors -s\n"). + "#----cut here----\n\n"); + + print "You really should try these commands right now to make sure everything\n". + "is working properly. Monitoring programs won't work until the needed\n". + "modules are loaded.\n\n"; + } +} + +sub main +{ + my ($input, $superio_features); + + # Parse command line options + while (defined $ARGV[0]) { + if ($ARGV[0] eq "--stat") { + $opt{stat} = 1; + } elsif ($ARGV[0] eq "--auto") { + $opt{auto} = 1; + } else { + print STDERR "Error: unknown option $ARGV[0]\n"; + exit 1; + } + shift @ARGV; + } + + if ($opt{stat}) { + show_i2c_stats(); + exit 0; + } + + # We won't go very far if not root + unless ($> == 0) { + print "You need to be root to run this script.\n"; + exit -1; + } + + initialize_kernel_version(); + initialize_conf(); + initialize_pci(); + initialize_modules_list(); + # Make sure any special case chips are added to the chip_ids list + # before making the support modules list + chip_special_cases(); + initialize_modules_supported(); + initialize_cpu_list(); + + if ($systemd_systemctl && $systemd_system_dir && + -f "$systemd_system_dir/lm_sensors.service") { + system("$systemd_systemctl", "stop", "lm_sensors.service"); + } elsif (-x "/sbin/service" && -f "/etc/init.d/lm_sensors" && + -f "/var/lock/subsys/lm_sensors") { + system("/sbin/service", "lm_sensors", "stop"); + } + + print "# sensors-detect revision $revision\n"; + initialize_dmi_data(); + print_dmi_summary(); + print_kernel_version(); + print_cpu_info(); + print "\n"; + + if ($opt{auto}) { + print "Running in automatic mode, default answers to all questions\n", + "are assumed.\n\n"; + } else { + print "This program will help you determine which kernel modules you need\n", + "to load to use lm_sensors most effectively. It is generally safe\n", + "and recommended to accept the default answers to all questions,\n", + "unless you know what you're doing.\n\n"; + } + + print "Some south bridges, CPUs or memory controllers contain embedded sensors.\n". + "Do you want to scan for them? This is totally safe. (YES/no): "; + $input = read_answer(); + unless ($input =~ /^\s*n/i) { + # Load the cpuid driver if needed + unless (-e "$sysfs_root/class/cpuid") { + load_module("cpuid"); + udev_settle(); + } + + $| = 1; + foreach my $entry (@cpu_ids) { + scan_cpu($entry); + } + $| = 0; + } + print "\n"; + + $superio_features = 0; + # Skip "random" I/O port probing on non-x86 machines + if ($kernel_arch =~ m/^i[3456]86$/ + || $kernel_arch eq 'x86_64') { + print "Some Super I/O chips contain embedded sensors. We have to write to\n". + "standard I/O ports to probe them. This is usually safe.\n"; + print "Do you want to scan for Super I/O sensors? (YES/no): "; + $input = read_answer(); + unless ($input =~ /^\s*n/i) { + if (initialize_ioports()) { + $superio_features |= scan_superio(0x2e, 0x2f); + $superio_features |= scan_superio(0x4e, 0x4f); + close_ioports(); + } + } + print "\n"; + + unless (is_laptop()) { + print "Some systems (mainly servers) implement IPMI, a set of common interfaces\n". + "through which system health data may be retrieved, amongst other things.\n". + "We first try to get the information from SMBIOS. If we don't find it\n". + "there, we have to read from arbitrary I/O ports to probe for such\n". + "interfaces. This is normally safe. Do you want to scan for IPMI\n". + "interfaces? (YES/no): "; + $input = read_answer(); + unless ($input =~ /^\s*n/i) { + if (!ipmi_from_smbios()) { + if (initialize_ioports()) { + scan_isa_bus(\@ipmi_ifs); + close_ioports(); + } + } + } + print "\n"; + } + + printf "Some hardware monitoring chips are accessible through the ISA I/O ports.\n". + "We have to write to arbitrary I/O ports to probe them. This is usually\n". + "safe though. Yes, you do have ISA I/O ports even if you do not have any\n". + "ISA slots! Do you want to scan the ISA I/O ports? (\%s): ", + $superio_features ? "yes/NO" : "YES/no"; + $input = read_answer(); + unless ($input =~ /^\s*n/i + || ($superio_features && $input !~ /^\s*y/i)) { + if (initialize_ioports()) { + scan_isa_bus(\@chip_ids); + close_ioports(); + } + } + print "\n"; + } + + print "Lastly, we can probe the I2C/SMBus adapters for connected hardware\n". + "monitoring devices. This is the most risky part, and while it works\n". + "reasonably well on most systems, it has been reported to cause trouble\n". + "on some systems.\n". + "Do you want to probe the I2C/SMBus adapters now? (YES/no): "; + + $input = read_answer(); + unless ($input =~ /^\s*n/i) { + adapter_pci_detection(); + load_module("i2c-dev") unless -e "$sysfs_root/class/i2c-dev"; + initialize_i2c_adapters_list(); + $i2c_addresses_to_scan = i2c_addresses_to_scan(); + print "\n"; + + # Skip SMBus probing by default if Super-I/O has all the features + my $by_default = ~$superio_features & (FEAT_IN | FEAT_FAN | FEAT_TEMP); + # Except on Asus and Tyan boards which often have more than + # one hardware monitoring chip + $by_default = 1 if dmi_match('board_vendor', 'asustek', 'tyan', + 'supermicro'); + + udev_settle(); + for (my $dev_nr = 0; $dev_nr < @i2c_adapters; $dev_nr++) { + next unless exists $i2c_adapters[$dev_nr]; + scan_i2c_adapter($dev_nr, $by_default); + } + filter_out_fake_i2c_drivers(); + } + + if (!keys %chips_detected) { + print "Sorry, no sensors were detected.\n"; + if (is_laptop() && -d "$sysfs_root/firmware/acpi") { + print "This is relatively common on laptops, where thermal management is\n". + "handled by ACPI rather than the OS.\n"; + } else { + print "Either your system has no sensors, or they are not supported, or\n". + "they are connected to an I2C or SMBus adapter that is not\n". + "supported. If you find out what chips are on your board, check\n". + "http://www.lm-sensors.org/wiki/Devices for driver status.\n"; + } + exit; + } + + print "\nNow follows a summary of the probes I have just done.\n"; + unless ($opt{auto}) { + print "Just press ENTER to continue: "; + ; + } + + initialize_hwmon_autoloaded(); + foreach my $driver (keys %chips_detected) { + next unless @{$chips_detected{$driver}}; + find_aliases($chips_detected{$driver}); + print "\nDriver `$driver'"; + print " (autoloaded)" if hwmon_is_autoloaded($driver); + print " (built-in)" if is_module_builtin($driver); + print ":\n"; + print_chips_report($chips_detected{$driver}); + } + print "\n"; + + my ($configfile, $bus_modules, $hwmon_modules) = generate_modprobes(); + + if (@{$hwmon_modules}) { + write_config($configfile, $bus_modules, $hwmon_modules); + } else { + print "No modules to load, skipping modules configuration.\n\n"; + } + + unload_modules(); + + # Check if running non-interactively without --auto + if (!$opt{auto} && ! -t STDIN) { + print "***************************************************************\n". + "Warning: the preferred way to run this script non-interactively\n". + "is with option --auto. Other methods are discouraged and may\n". + "stop working at some point in the future.\n". + "***************************************************************\n\n"; + } +} + +sub cleanup_on_int +{ + print "\n"; + unload_modules(); + exit; +} + +$SIG{INT} = \&cleanup_on_int; + +main; diff --git a/prog/detect/sensors-detect.8 b/prog/detect/sensors-detect.8 new file mode 100644 index 0000000..df5139f --- /dev/null +++ b/prog/detect/sensors-detect.8 @@ -0,0 +1,61 @@ +.TH SENSORS-DETECT 8 "September 2013" "lm-sensors 3" +.SH NAME +sensors-detect \- detect hardware monitoring chips + +.SH SYNOPSIS +.B sensors-detect [ +.I --auto +.B ] + +.SH DESCRIPTION +sensors-detect is an interactive program that will walk you through the +process of scanning your system for various hardware monitoring chips, +or sensors, supported by libsensors(3), or more generally by the lm_sensors +tool suite. + +sensors-detect will look for the following devices, in order: +.IP \(bu +Sensors embedded in CPUs, south bridges and memory controllers. +.IP \(bu +Sensors embedded in Super I/O chips. +.IP \(bu +Hardware monitoring chips accessed through ISA I/O ports. +.IP \(bu +Hardware monitoring chips reachable over the SMBus or more generally +any I2C bus on your system. +.PP +As the last two detection steps can cause trouble on some systems, they +are normally not attempted if the second detection step led to the +discovery of a Super I/O chip with complete hardware monitoring features. +However, the user is always free to ask for all detection steps if so is +his/her wish. This can be useful if a given system has more than one +hardware monitoring chip. Some vendors are known to do this, most notably +Asus and Tyan. + +.SH OPTIONS +.IP "--auto" +Run in automatic, non-interactive mode. Assume default answers to all +questions. Note that this isn't necessarily safe as the internal logic may +lead to potentially dangerous probes being attempted. See the WARNING section +below. + +.SH WARNING +sensors-detect needs to access the hardware for most of the chip detections. +By definition, it doesn't know which chips are there before it manages to +identify them. This means that it can access chips in a way these chips do +not like, causing problems ranging from SMBus lockup to permanent hardware +damage (a rare case, thankfully.) + +The authors made their best to make the detection as safe as possible, and +it turns out to work just fine in most cases, however it is impossible to +guarantee that sensors-detect will not lock or kill a specific system. So, +as a rule of thumb, you should not run sensors-detect on production servers, +and you should not run sensors-detect if can't afford replacing a random +part of your system. Also, it is recommended to not force a detection step +which would have been skipped by default, unless you know what you are doing. + +.SH SEE ALSO +sensors(1), libsensors(3) + +.SH AUTHOR +Frodo Looijaard and Jean Delvare diff --git a/prog/dump/Module.mk b/prog/dump/Module.mk new file mode 100644 index 0000000..5e522e3 --- /dev/null +++ b/prog/dump/Module.mk @@ -0,0 +1,63 @@ +# Module.mk - Makefile for a Linux module for reading sensor data. +# Copyright (c) 1998, 1999 Frodo Looijaard +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. + +# Note that MODULE_DIR (the directory in which this file resides) is a +# 'simply expanded variable'. That means that its value is substituted +# verbatim in the rules, until it is redefined. +MODULE_DIR := prog/dump +PROGDUMPDIR := $(MODULE_DIR) + +PROGDUMPMAN8DIR := $(MANDIR)/man8 +PROGDUMPMAN8FILES := $(MODULE_DIR)/isadump.8 $(MODULE_DIR)/isaset.8 + +# Regrettably, even 'simply expanded variables' will not put their currently +# defined value verbatim into the command-list of rules... +PROGDUMPTARGETS := $(MODULE_DIR)/isadump $(MODULE_DIR)/isaset +PROGDUMPSOURCES := $(MODULE_DIR)/util.c $(MODULE_DIR)/isadump.c \ + $(MODULE_DIR)/isaset.c $(MODULE_DIR)/superio.c +PROGDUMPBININSTALL := $(MODULE_DIR)/isadump $(MODULE_DIR)/isaset + +# Include all dependency files. We use '.rd' to indicate this will create +# executables. +INCLUDEFILES += $(PROGDUMPSOURCES:.c=.rd) + +REMOVEDUMPBIN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(SBINDIR)/%,$(PROGDUMPBININSTALL)) +REMOVEDUMPMAN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(PROGDUMPMAN8DIR)/%,$(PROGDUMPMAN8FILES)) + +all-prog-dump: $(PROGDUMPTARGETS) +user :: all-prog-dump + +$(MODULE_DIR)/isadump: $(MODULE_DIR)/isadump.ro $(MODULE_DIR)/superio.ro $(MODULE_DIR)/util.ro + $(CC) $(EXLDFLAGS) -o $@ $^ + +$(MODULE_DIR)/isaset: $(MODULE_DIR)/isaset.ro $(MODULE_DIR)/util.ro + $(CC) $(EXLDFLAGS) -o $@ $^ + +install-prog-dump: all-prog-dump + $(MKDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(PROGDUMPMAN8DIR) + $(INSTALL) -m 755 $(PROGDUMPBININSTALL) $(DESTDIR)$(SBINDIR) + $(INSTALL) -m 644 $(PROGDUMPMAN8FILES) $(DESTDIR)$(PROGDUMPMAN8DIR) +user_install :: install-prog-dump + +user_uninstall:: + $(RM) $(REMOVEDUMPBIN) + $(RM) $(REMOVEDUMPMAN) + +clean-prog-dump: + $(RM) $(PROGDUMPDIR)/*.rd $(PROGDUMPDIR)/*.ro $(PROGDUMPTARGETS) +clean :: clean-prog-dump diff --git a/prog/dump/isadump.8 b/prog/dump/isadump.8 new file mode 100644 index 0000000..6bf5ea4 --- /dev/null +++ b/prog/dump/isadump.8 @@ -0,0 +1,114 @@ +.TH ISADUMP 8 "April 2011" +.SH NAME +isadump \- examine ISA registers + +.SH SYNOPSIS +.B isadump +.RB [ -y ] +.RB [ -W | -L ] +.RB [ "-k V1,V2..." ] +.I addrreg +.I datareg +.RI [ "bank " [ bankreg ]] +#for I2C-like access +.br +.B isadump +.B -f +.RB [ -y ] +.RB [ -W | -L ] +.I address +.RI [ "range " [ "bank " [ bankreg ]]] +#for flat address space + +.SH DESCRIPTION +isadump is a small helper program to examine registers visible through the ISA +bus. It is intended to probe any chip that lives on the ISA bus working with an +address register and a data register (I2C-like access) or a flat range (of up +to 256 bytes). + +.SH OPTIONS +.TP +.B -f +Enable flat address space mode. +.TP +.B -y +Disable interactive mode. By default, isadump will wait for a confirmation +from the user before messing with the ISA bus. When this flag is used, it +will perform the operation directly. This is mainly meant to be used in +scripts. +.TP +.B -k V1,V2... +Specify a comma-separated list of bytes to send as the key sequence to enter +the chip configuration mode. Most Super-I/O chips need this. +Known key sequences are: 0x87,0x01,0x55,0x55 for ITE, 0x55 for SMSC, 0x87,0x87 +for Winbond and VIA, none needed for National Semiconductor. +.TP +.B -W +Perform 16-bit reads. +.TP +.B -L +Perform 32-bit reads. + +.SH OPTIONS (I2C-like access mode) +At least two options must be provided to isadump. \fIaddrreg\fR contains the +ISA address of the address register for the chip to probe; \fIdatareg\fR +contains the address of the data register. Both addresses are integers between +0x0000 and 0x3FFF. Usually, if the chip's base address is 0x0nn0, the +address register is at 0x0nn5 and the data register is at 0x0nn6. The most +common base address for hardware monitoring chips is 0x0290. +.PP +For Super-I/O chips, address register is typically at 0x2E with data +register at 0x2F. +.PP +The \fIbank\fR and \fIbankreg\fR parameters are useful on the Winbond chips +as well as on Super-I/O chips. +\fIbank\fR is an integer between 0 and 31, and \fIbankreg\fR is an integer +between 0x00 and 0xFF (default value: 0x4E for Winbond chips, 0x07 +for Super-I/O chips). The W83781D datasheet has more information on bank +selection. + +.SH OPTIONS (flat address space mode) +In flat mode, only one parameter is +mandatory. \fIaddress\fR contains the ISA address of the chip to probe; +it is an integer between 0x0000 and 0xFFFF. +If provided, \fIrange\fR is how many bytes should be read (must be a +multiple of 16). If the range isn't provided, it defaults to 256 bytes +and the address is forcibly aligned on a 256-byte boundary. +.PP +The \fIbank\fR and \fIbankreg\fR parameters are useful on the National +Semiconductor PC87365 and PC87366 Super-I/O chips. +\fIbank\fR is an integer between 0 and 31, and \fIbankreg\fR is an integer +between 0x00 and 0xFF (default value: 0x09; must fit in the specified +range). See the PC87365 datasheet for more information on bank selection. + +.SH NOTES +If no bank is specified, no bank change operation is performed. +.PP +If a bank is specified, the original value is restored before isadump exits. +.PP +Dumping Super-I/O chips is typically a two-step process. First, you will have +to access the main Super-I/O address using a command like: +isadump 0x2e 0x2f 0x09. +This will select logical device 9 (correct value depend on the chip). At 0x60 +you will find the logical device address word, for example "ec c0". +Then you can use a command like: +isadump -f 0xecc0 16. +This will dump the logical device registers. The correct range depends on +the chip. + +.SH WARNING +Poking around in ISA data space is extremely dangerous. +Running isadump with random parameters can cause system +crashes, data loss, and worse! Be extremely careful when using +this program. + +.SH SEE ALSO +i2cdump(8), isaset(8) + +.SH AUTHOR +Frodo Looijaard, Mark D. Studebaker, and the lm_sensors group +(http://www.lm-sensors.org/) +.PP +This manual page was originally written by David Z Maze for +the Debian GNU/Linux system. It was then reviewed and augmented by the lm_sensors +team and is now part of the lm_sensors source distribution. diff --git a/prog/dump/isadump.c b/prog/dump/isadump.c new file mode 100644 index 0000000..ef3dd0a --- /dev/null +++ b/prog/dump/isadump.c @@ -0,0 +1,322 @@ +/* + isadump.c - isadump, a user-space program to dump ISA registers + Copyright (C) 2000 Frodo Looijaard , and + Mark D. Studebaker + Copyright (C) 2004-2011 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* + Typical usage: + isadump 0x295 0x296 Basic winbond dump using address/data registers + isadump 0x295 0x296 2 Winbond dump, bank 2 + isadump 0x2e 0x2f 0x09 Super-I/O, logical device 9 + isadump -f 0x5000 Flat address space dump like for Via 686a + isadump -f 0xecf0 0x10 1 PC87366, temperature channel 2 +*/ + +#include +#include +#include +#include +#include +#include "util.h" +#include "superio.h" + +#ifdef __powerpc__ +unsigned long isa_io_base = 0; /* XXX for now */ +#endif /* __powerpc__ */ + +static void help(void) +{ + fprintf(stderr, + "Syntax for I2C-like access:\n" + " isadump [OPTIONS] [-k V1,V2...] ADDRREG DATAREG [BANK [BANKREG]]\n" + "Syntax for flat address space:\n" + " isadump -f [OPTIONS] ADDRESS [RANGE [BANK [BANKREG]]]\n" + "Options:\n" + " -k Super-I/O configuration access key\n" + " -f Enable flat address space mode\n" + " -y Assume affirmative answer to all questions\n" + " -W Read and display word (16-bit) values\n" + " -L Read and display long (32-bit) values\n"); +} + +static int default_bankreg(int flat, int addrreg, int datareg) +{ + if (flat) { + return 0x09; /* Works for National Semiconductor + Super-IO chips */ + } + + if ((addrreg == 0x2e && datareg == 0x2f) + || (addrreg == 0x4e && datareg == 0x4f)) { + return 0x07; /* Works for all Super-I/O chips */ + } + + return 0x4e; /* Works for Winbond ISA chips, default */ +} + +static int set_bank(int flat, int addrreg, int datareg, int bank, int bankreg) +{ + int oldbank; + + if (flat) { + oldbank = inb(addrreg+bankreg); + outb(bank, addrreg+bankreg); + } else { + outb(bankreg, addrreg); + oldbank = inb(datareg); + outb(bank, datareg); + } + + return oldbank; +} + +int main(int argc, char *argv[]) +{ + int addrreg; /* address in flat mode */ + int datareg = 0; /* unused in flat mode */ + int range = 256; /* can be changed only in flat mode */ + int bank = -1; /* -1 means no bank operation */ + int bankreg; + int oldbank = 0; + int i, j; + unsigned long res; + int flags = 0; + int flat = 0, yes = 0, width = 1; + char *end; + unsigned char enter_key[SUPERIO_MAX_KEY+1]; + + enter_key[0] = 0; + + /* handle (optional) flags first */ + while (1+flags < argc && argv[1+flags][0] == '-') { + switch (argv[1+flags][1]) { + case 'f': flat = 1; break; + case 'y': yes = 1; break; + case 'k': + if (2+flags >= argc + || superio_parse_key(enter_key, argv[2+flags]) < 0) { + fprintf(stderr, "Invalid or missing key\n"); + help(); + exit(1); + } + flags++; + break; + case 'W': width = 2; break; + case 'L': width = 4; break; + default: + fprintf(stderr, "Warning: Unsupported flag " + "\"-%c\"!\n", argv[1+flags][1]); + help(); + exit(1); + } + flags++; + } + + /* key is never needed in flat mode */ + if (flat && enter_key[0]) { + fprintf(stderr, "Error: Cannot use key in flat mode\n"); + exit(1); + } + + /* verify that the argument count is correct */ + if ((!flat && argc < 1+flags+2) + || (flat && argc < 1+flags+1)) { + help(); + exit(1); + } + + addrreg = strtol(argv[1+flags], &end, 0); + if (*end) { + fprintf(stderr, "Error: Invalid address!\n"); + help(); + exit(1); + } + if (addrreg < 0 || addrreg > (flat?0xffff:0x3fff)) { + fprintf(stderr, "Error: Address out of range " + "(0x0000-0x%04x)!\n", flat?0xffff:0x3fff); + help(); + exit(1); + } + + if (flat) { + if (1+flags+1 < argc) { + range = strtol(argv[1+flags+1], &end, 0); + if (*end || range <= 0 || range > 0x100 + || range & 0xf) { + fprintf(stderr, "Error: Invalid range!\n" + "Hint: Must be a multiple of 16 no " + "greater than 256.\n"); + help(); + exit(1); + } + } else { + addrreg &= 0xff00; /* Force alignment */ + } + } else { + datareg = strtol(argv[1+flags+1], &end, 0); + if (*end) { + fprintf(stderr, "Error: Invalid data register!\n"); + help(); + exit(1); + } + if (datareg < 0 || datareg > 0x3fff) { + fprintf(stderr, "Error: Data register out of range " + "(0x0000-0x3fff)!\n"); + help(); + exit(1); + } + } + + bankreg = default_bankreg(flat, addrreg, datareg); + + if (1+flags+2 < argc) { + bank = strtol(argv[1+flags+2], &end, 0); + if (*end) { + fprintf(stderr, "Error: Invalid bank number!\n"); + help(); + exit(1); + } + if ((bank < 0) || (bank > 31)) { + fprintf(stderr, "Error: bank out of range (0-31)!\n"); + help(); + exit(1); + } + + if (1+flags+3 < argc) { + bankreg = strtol(argv[1+flags+3], &end, 0); + if (*end) { + fprintf(stderr, "Error: Invalid bank " + "register!\n"); + help(); + exit(1); + } + if (bankreg < 0 || bankreg >= range) { + fprintf(stderr, "Error: bank out of range " + "(0x00-0x%02x)!\n", range-1); + help(); + exit(1); + } + } + } + + if (geteuid()) { + fprintf(stderr, "Error: Can only be run as root (or make it " + "suid root)\n"); + exit(1); + } + + if (!yes) { + fprintf(stderr, "WARNING! Running this program can cause " + "system crashes, data loss and worse!\n"); + + if (flat) + fprintf(stderr, "I will probe address range 0x%x to " + "0x%x.\n", addrreg, addrreg + range - 1); + else + fprintf(stderr, "I will probe address register 0x%x " + "and data register 0x%x.\n", addrreg, datareg); + + if (bank>=0) + fprintf(stderr, "Probing bank %d using bank register " + "0x%02x.\n", bank, bankreg); + + fprintf(stderr, "Continue? [Y/n] "); + fflush(stderr); + if (!user_ack(1)) { + fprintf(stderr, "Aborting on user request.\n"); + exit(0); + } + } + +#ifndef __powerpc__ + if ((datareg < 0x400) && (addrreg < 0x400) && !flat) { + if (ioperm(datareg, 1, 1)) { + fprintf(stderr, "Error: Could not ioperm() data " + "register!\n"); + exit(1); + } + if (ioperm(addrreg, 1, 1)) { + fprintf(stderr, "Error: Could not ioperm() address " + "register!\n"); + exit(1); + } + } else { + if (iopl(3)) { + fprintf(stderr, "Error: Could not do iopl(3)!\n"); + exit(1); + } + } +#endif + + /* Enter Super-I/O configuration mode */ + if (enter_key[0]) + superio_write_key(addrreg, enter_key); + + if (bank >= 0) + oldbank = set_bank(flat, addrreg, datareg, bank, bankreg); + + /* print column headers */ + printf("%*s", flat ? 5 : 3, ""); + for (j = 0; j < 16; j += width) + printf(" %*x", width * 2, j); + printf("\n"); + + for (i = 0; i < range; i += 16) { + if (flat) + printf("%04x: ", addrreg + i); + else + printf("%02x: ", i); + + /* It was noticed that Winbond Super-I/O chips + would leave the configuration mode after + an arbitrary number of register reads, + causing any subsequent read attempt to + silently fail. Repeating the key every 16 reads + prevents that. */ + if (enter_key[0]) + superio_write_key(addrreg, enter_key); + + for (j = 0; j < 16; j += width) { + fflush(stdout); + if (flat) { + res = inx(addrreg + i + j, width); + } else { + outb(i+j, addrreg); + if (i+j == 0 && inb(addrreg) == 0x80) { + /* Bit 7 appears to be a busy flag */ + range = 128; + } + res = inx(datareg, width); + } + printf("%0*lx ", width * 2, res); + } + printf("\n"); + } + + /* Restore the original bank value */ + if (bank >= 0) + set_bank(flat, addrreg, datareg, oldbank, bankreg); + + /* Exit Super-I/O configuration mode */ + if (enter_key[0]) + superio_reset(addrreg, datareg); + + exit(0); +} diff --git a/prog/dump/isaset.8 b/prog/dump/isaset.8 new file mode 100644 index 0000000..e7bcd5d --- /dev/null +++ b/prog/dump/isaset.8 @@ -0,0 +1,83 @@ +.TH ISASET 8 "April 2011" +.SH "NAME" +isaset \- set ISA registers + +.SH SYNOPSIS +.B isaset +.RB [ -y ] +.RB [ -W | -L ] +.I addrreg +.I datareg +.I address +.I value +.RI [ mask ] +#for I2C-like access +.br +.B isaset +.B -f +.RB [ -y ] +.RB [ -W | -L ] +.I address +.I value +.RI [ mask ] +#for flat address space + +.SH DESCRIPTION +isaset is a small helper program to set registers visible through the ISA +bus. + +.SH OPTIONS +.TP +.B -f +Enable flat address space mode. +.TP +.B -y +Disable interactive mode. By default, isaset will wait for a confirmation +from the user before messing with the ISA bus. When this flag is used, it +will perform the operation directly. This is mainly meant to be used in +scripts. +.TP +.B -W +Perform a 16-bit write. +.TP +.B -L +Perform a 32-bit write. + +.SH OPTIONS (I2C-like access mode) +Four options must be provided to isaset. \fIaddrreg\fR contains the +ISA address of the address register for the chip to probe; \fIdatareg\fR +contains the address of the data register. Both addresses are integers between +0x0000 and 0x3FFF. Usually, if the chip's base address is 0x0nn0, the +address register is at 0x0nn5 and the data register is at 0x0nn6. The most +common base address for hardware monitoring chips is 0x0290. +For Super-I/O chips, address register is typically at 0x2E with data +register at 0x2F. +The \fIaddress\fR and \fIvalue\fR parameters are two integers between +0x00 and 0xFF. isaset will write value \fIvalue\fR to address \fIaddress\fR. +An optional \fImask\fR can be provided as a fifth parameter, preserving +unmasked bits at the written location. + +.SH OPTIONS (flat address space mode) +In flat mode, two parameters must +be provided. \fIaddress\fR contains the ISA address of the register to +write to; it is an integer between 0x0000 and 0xFFFF. Basically, it is +the sum of the chip's base address and the chip register's address. isaset +will write value \fIvalue\fR at this address. +An optional \fImask\fR can be provided as a third parameter, preserving +unmasked bits at the written location. + +.SH WARNING +Poking around in ISA data space is extremely dangerous. +Running isaset with random parameters can cause system +crashes, data loss, and worse! Be extremely careful when using +this program. + +.SH SEE ALSO +i2cset(8), isadump(8) + +.SH AUTHOR +Mark D. Studebaker, and the lm_sensors group +(http://www.lm-sensors.org/) +.PP +This manual page was shamelessly ripped from the i2cset and isadump manual +pages by Jean Delvare. diff --git a/prog/dump/isaset.c b/prog/dump/isaset.c new file mode 100644 index 0000000..590f75c --- /dev/null +++ b/prog/dump/isaset.c @@ -0,0 +1,261 @@ +/* + isaset.c - isaset, a user-space program to write ISA registers + Copyright (C) 2000 Frodo Looijaard , and + Mark D. Studebaker + Copyright (C) 2004-2011 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* + Typical usage: + isaset 0x295 0x296 0x10 0x12 Write 0x12 to address 0x10 using address/data registers + isaset -f 0x5010 0x12 Write 0x12 to location 0x5010 +*/ + +#include +#include +#include +#include +#include +#include "util.h" + +#ifdef __powerpc__ +unsigned long isa_io_base = 0; /* XXX for now */ +#endif /* __powerpc__ */ + +static void help(void) +{ + fprintf(stderr, + "Syntax for I2C-like access:\n" + " isaset [OPTIONS] ADDRREG DATAREG ADDRESS VALUE [MASK]\n" + "Syntax for flat address space:\n" + " isaset -f [OPTIONS] ADDRESS VALUE [MASK]\n" + "Options:\n" + " -f Enable flat address space mode\n" + " -y Assume affirmative answer to all questions\n" + " -W Write a word (16-bit) value\n" + " -L Write a long (32-bit) value\n"); +} + +int main(int argc, char *argv[]) +{ + int addrreg, datareg = 0, addr = 0; + unsigned long value, vmask = 0, maxval = 0xff, res; + int flags = 0; + int flat = 0, yes = 0, width = 1; + char *end; + + /* handle (optional) flags first */ + while (1+flags < argc && argv[1+flags][0] == '-') { + switch (argv[1+flags][1]) { + case 'f': flat = 1; break; + case 'y': yes = 1; break; + case 'W': width = 2; maxval = 0xffff; break; + case 'L': width = 4; maxval = 0xffffffff; break; + default: + fprintf(stderr, "Warning: Unsupported flag " + "\"-%c\"!\n", argv[1+flags][1]); + help(); + exit(1); + } + flags++; + } + + /* verify that the argument count is correct */ + if ((!flat && (argc < 1+flags+4 || argc > 1+flags+5)) + || (flat && (argc < 1+flags+2 || argc > 1+flags+3))) { + help(); + exit(1); + } + + addrreg = strtol(argv[1+flags], &end, 0); + if (*end) { + fprintf(stderr, "Error: Invalid address!\n"); + help(); + exit(1); + } + if (addrreg < 0 || addrreg > (flat?0xffff:0x3fff)) { + fprintf(stderr, + "Error: Address out of range (0x0000-0x%04x)!\n", + flat?0xffff:0x3fff); + help(); + exit(1); + } + + if (!flat) { + datareg = strtol(argv[1+flags+1], &end, 0); + if (*end) { + fprintf(stderr, "Error: Invalid data register!\n"); + help(); + exit(1); + } + if (datareg < 0 || datareg > 0x3fff) { + fprintf(stderr, "Error: Data register out of range " + "(0x0000-0x3fff)!\n"); + help(); + exit(1); + } + + addr = strtol(argv[1+flags+2], &end, 0); + if (*end) { + fprintf(stderr, "Error: Invalid address!\n"); + help(); + exit(1); + } + if (addr < 0 || addr > 0xff) { + fprintf(stderr, "Error: Address out of range " + "(0x00-0xff)!\n"); + help(); + exit(1); + } + } + + /* rest is the same for both modes so we cheat on flags */ + if (!flat) + flags += 2; + + value = strtoul(argv[flags+2], &end, 0); + if (*end) { + fprintf(stderr, "Error: Invalid value!\n"); + help(); + exit(1); + } + if (value > maxval) { + fprintf(stderr, "Error: Value out of range " + "(0x%0*u-%0*lu)!\n", width * 2, 0, width * 2, maxval); + help(); + exit(1); + } + + if (flags+3 < argc) { + vmask = strtoul(argv[flags+3], &end, 0); + if (*end) { + fprintf(stderr, "Error: Invalid mask!\n"); + help(); + exit(1); + } + if (vmask > maxval) { + fprintf(stderr, "Error: Mask out of range " + "(0x%0*u-%0*lu)!\n", width * 2, 0, + width * 2, maxval); + help(); + exit(1); + } + } + + if (geteuid()) { + fprintf(stderr, "Error: Can only be run as root " + "(or make it suid root)\n"); + exit(1); + } + + if (!yes) { + fprintf(stderr, "WARNING! Running this program can cause " + "system crashes, data loss and worse!\n"); + + if (flat) + fprintf(stderr, + "I will write value 0x%0*lx%s to address " + "0x%x.\n", width * 2, value, + vmask ? " (masked)" : "", addrreg); + else + fprintf(stderr, + "I will write value 0x%0*lx%s to address " + "0x%02x of chip with address register 0x%x\n" + "and data register 0x%x.\n", width * 2, + value, vmask ? " (masked)" : "", addr, + addrreg, datareg); + + fprintf(stderr, "Continue? [Y/n] "); + fflush(stderr); + if (!user_ack(1)) { + fprintf(stderr, "Aborting on user request.\n"); + exit(0); + } + } + +#ifndef __powerpc__ + if (!flat && datareg < 0x400 && addrreg < 0x400) { + if (ioperm(datareg, 1, 1)) { + fprintf(stderr, "Error: Could not ioperm() data " + "register!\n"); + exit(1); + } + if (ioperm(addrreg, 1, 1)) { + fprintf(stderr, "Error: Could not ioperm() address " + "register!\n"); + exit(1); + } + } else { + if (iopl(3)) { + fprintf(stderr, "Error: Could not do iopl(3)!\n"); + exit(1); + } + } +#endif + + if (vmask) { + unsigned long oldvalue; + + if (flat) { + oldvalue = inx(addrreg, width); + } else { + outb(addr, addrreg); + oldvalue = inx(datareg, width); + } + + value = (value & vmask) | (oldvalue & ~vmask); + + if (!yes) { + fprintf(stderr, "Old value 0x%0*lx, write mask " + "0x%0*lx: Will write 0x%0*lx to %s " + "0x%02x\n", width * 2, oldvalue, + width * 2, vmask, width * 2, value, + flat ? "address" : "register", + flat ? addrreg : addr); + + fprintf(stderr, "Continue? [Y/n] "); + fflush(stderr); + if (!user_ack(1)) { + fprintf(stderr, "Aborting on user request.\n"); + exit(0); + } + } + } + + /* do the real thing */ + if (flat) { + /* write */ + outx(value, addrreg, width); + /* readback */ + res = inx(addrreg, width); + } else { + /* write */ + outb(addr, addrreg); + outx(value, datareg, width); + /* readback */ + res = inx(datareg, width); + } + + if (res != value) { + fprintf(stderr, "Data mismatch, wrote 0x%0*lx, " + "read 0x%0*lx back.\n", width * 2, value, + width * 2, res); + } + + exit(0); +} diff --git a/prog/dump/superio.c b/prog/dump/superio.c new file mode 100644 index 0000000..dbcde7b --- /dev/null +++ b/prog/dump/superio.c @@ -0,0 +1,70 @@ +/* + superio: Handle special I/O operations needed by most Super-I/O chips + + Copyright (C) 2005-2008 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#include +#include +#include "superio.h" + +int superio_parse_key(unsigned char *key, const char *s) +{ + char *end; + int tmp; + key[0] = 0; + + while (*s != '\0') { + tmp = strtol(s, &end, 0); + if ((*end != '\0' && *end != ',') + || (tmp < 0x00 || tmp > 0xff)) + return -1; + + /* Byte is valid, store it */ + key[++key[0]] = tmp; + + /* Last byte? */ + if (key[0] == SUPERIO_MAX_KEY + || *end == '\0') + return 0; + + /* Skip comma */ + s = end + 1; + } + + /* Unexpected end of string */ + return -1; +} + +void superio_write_key(int addrreg, unsigned char *key) +{ + int i; + + for (i = 1; i <= key[0]; i++) + outb(key[i], addrreg); +} + +void superio_reset(int addrreg, int datareg) +{ + /* Some chips (SMSC, Winbond) want this */ + outb(0xaa, addrreg); + + /* Return to "Wait For Key" state (PNP-ISA spec) */ + outb(0x02, addrreg); + outb(0x02, datareg); +} diff --git a/prog/dump/superio.h b/prog/dump/superio.h new file mode 100644 index 0000000..06065be --- /dev/null +++ b/prog/dump/superio.h @@ -0,0 +1,31 @@ +/* + superio: Handle special I/O operations needed by most Super-I/O chips + + Copyright (C) 2005-2008 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef _SUPERIO_H +#define _SUPERIO_H + +#define SUPERIO_MAX_KEY 8 + +int superio_parse_key(unsigned char *key, const char *s); +void superio_write_key(int addrreg, unsigned char *key); +void superio_reset(int addrreg, int datareg); + +#endif /* _SUPERIO_H */ diff --git a/prog/dump/util.c b/prog/dump/util.c new file mode 100644 index 0000000..908b373 --- /dev/null +++ b/prog/dump/util.c @@ -0,0 +1,78 @@ +/* + util.c - helper functions + Copyright (C) 2006-2011 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include +#include +#include "util.h" + +/* Return 1 if we should continue, 0 if we should abort */ +int user_ack(int def) +{ + char s[2]; + int ret; + + if (!fgets(s, 2, stdin)) + return 0; /* Nack by default */ + + switch (s[0]) { + case 'y': + case 'Y': + ret = 1; + break; + case 'n': + case 'N': + ret = 0; + break; + default: + ret = def; + } + + /* Flush extra characters */ + while (s[0] != '\n') { + int c = fgetc(stdin); + if (c == EOF) { + ret = 0; + break; + } + s[0] = c; + } + + return ret; +} + +/* I/O read of specified size */ +unsigned long inx(int addr, int width) +{ + switch (width) { + case 2: + return inw(addr); + break; + case 4: + return inl(addr); + break; + default: + return inb(addr); + } +} + +/* I/O write of specified size */ +void outx(unsigned long value, int addr, int width) +{ + switch (width) { + case 2: + outw(value, addr); + break; + case 4: + outl(value, addr); + break; + default: + outb(value, addr); + } +} diff --git a/prog/dump/util.h b/prog/dump/util.h new file mode 100644 index 0000000..b6f870c --- /dev/null +++ b/prog/dump/util.h @@ -0,0 +1,18 @@ +/* + util - helper functions + Copyright (C) 2006-2011 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#ifndef _UTIL_H +#define _UTIL_H + +extern int user_ack(int def); +extern unsigned long inx(int addr, int width); +extern void outx(unsigned long value, int addr, int width); + +#endif /* _UTIL_H */ diff --git a/prog/hotplug/README.p4b b/prog/hotplug/README.p4b new file mode 100644 index 0000000..bb180c8 --- /dev/null +++ b/prog/hotplug/README.p4b @@ -0,0 +1,38 @@ +What is it? +----------- + +It unhides the SMBus of Intel ICH southbridges hidden on Asus P4B series +and some other Asus and non-Asus systems. It is implemented as a shell +script for kernel 2.6.5 and later: unhide_ICH_SMBus. + +It works with the following chips: + * ICH2 (82801BA) + * ICH2-M (82801BAM) + * ICH3 (82801CA) + * ICH3-M (82801CAM) + * ICH4 (82801DB) + * ICH4-M (82801DBM) + * ICH5 (82801EB) + +ASUS switches off the SMBus PCI Device in the i801 ICH chip. I spoke twice +with the German support and learned that: "We do not want the users to be +irritated by just another PCI Device in the Win98 device manager." +Really funny :-). + +Activation is normally handled by the code in drivers/pci/quirks.c in the +kernel source. If the quirks code does not activate your SMBus, you may: + + * first of all, read the paragraph "Hidden ICH SMBus" in + Documentation/i2c/busses/i2c-i801 in the kernel source. + + * check if you have kernel version from 2.6.16 to 2.6.19 + If so, you need to disable ACPI sleep support and recompile kernel. + If you don't use suspend try below instead of recompilation. + + * run as root the ./unhide_ICH_SMBus script. It will unhide the bus + and load the i2c-i801 driver. Beware that you should then no longer + use system suspend as bad things might happen on resume. + + * if above script works and you have latest kernel, you may + try to fix the quirks.c, recompile and test your new kernel, + and then submit a patch to us. Contact us if you need assistance. diff --git a/prog/hotplug/unhide_ICH_SMBus b/prog/hotplug/unhide_ICH_SMBus new file mode 100755 index 0000000..13fccc9 --- /dev/null +++ b/prog/hotplug/unhide_ICH_SMBus @@ -0,0 +1,72 @@ +#!/bin/bash +# (C) Rudolf Marek , +# Copyright (C) 2007-2011 Jean Delvare +# +# Thanks Jean Delvare and Oliver Dreier for testing. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 +# as published by the Free Software Foundation +# +# Supports the following Intel ICH chipsets: +# PCI ID +# ICH 8086:2410 +# ICH2 8086:2440 +# ICH2-M 8086:244C +# ICH3 8086:2480 +# ICH3-M 8086:248C +# ICH4 8086:24C0 +# ICH4-M 8086:24CC +# ICH5 8086:24D0 + +pcibus="/sys/bus/pci/slots" +device="00:1f" + +if [ "$UID" -ne 0 ] ; then + echo "You need to be root to run this script!" + exit 252 +fi + +smbus=`lspci -n -s $device.3 | grep -i '0c05: *8086'` +if [ -n "$smbus" ] ; then + echo "ICH SMBus is already there!" + lspci -s $device.3 + exit +fi + +intel=`lspci -n -s $device.0 | grep -i '8086:24[148CD][0C]'` +if [ -z "$intel" ] ; then + echo "Not for your chipset - Intel (ICH) only" + echo "Supported: ICH, ICH2, ICH2-M, ICH3, ICH3-M, ICH4, ICH4-M, ICH5" + exit 255; +fi +modprobe fakephp &> /dev/null + +if [ ! -d "$pcibus" ] ; then + echo "You need the fake PCI hotplug driver! (fakephp.ko, kernel 2.6.5 or later)" + exit 255; +fi + +echo "Enabling SMBus PCI device ..." + +newval=$( printf '%x' $((0x$(setpci -s $device.0 f2.w) & 0xfff7))) +setpci -s $device.0 f2.w=$newval + +echo "Rescanning the bus ..." +echo 1 > $pcibus/0000:$device.0/power 2>/dev/null +if [ ! -d "$pcibus/0000:$device.3" ] ; then + echo "Failed to enable the SMBUS" + exit 253; +fi + +if [ ! -d "/sys/bus/pci/drivers/i801_smbus" ] ; then + echo "Loading i2c-i801 ..." + modprobe i2c-i801 + if [ $? -ne 0 ] ; then + exit 251 + fi +fi + +lspci -s $device.3 +echo "Done!" +echo "Remember: system suspend/resume is no longer safe to use." diff --git a/prog/init/README b/prog/init/README new file mode 100644 index 0000000..7552a67 --- /dev/null +++ b/prog/init/README @@ -0,0 +1,33 @@ +This directory contains files useful for initialization +scripts, especially for RedHat. + +There are two choices, lm_sensors.init and sensord.init. +Use one or the other but not both! + +---------------- + +The script lm_sensors.init is a nice startup/shutdown script. +On RH and other RH-based systems (MDK, notably) use this sort of startup +mechanism (i.e. SVR4-based), as opposed to the everything-in-one-script +(/etc/rc or /etc/rc.local) like the BSD-based systems do. +The lm_sensors.init file should be copied to /etc/rc.d/init.d/lm_sensors. +For more information see the top of the file. +It requires the /etc/sysconfig/lm_sensors file, which identifies +the correct modules. + +The /etc/sysconfig/lm_sensors file is generated by running sensors-detect. +Once the script is done detecting the hardware monitoring devices, it will +list all the required modules in that file, so that they can be loaded +automatically at boot time. + +---------------- + +The script sensord.init also loads the modules, and then +starts the sensord daemon. See the manual page sensord(8) for +more information on the daemon. + +The sensord.init file should be copied to /etc/rc.d/init.d/sensord. +For more information see the top of the file. + +To configure this service one should put appropriate "alias i2c-bus-0 xxx" +and "alias i2c-sensors-chip-0 xxx" in /etc/modules.conf. diff --git a/prog/init/fancontrol.init b/prog/init/fancontrol.init new file mode 100755 index 0000000..eabe734 --- /dev/null +++ b/prog/init/fancontrol.init @@ -0,0 +1,100 @@ +#!/bin/sh +# +# $Id$ +# +# fancontrol +# +# chkconfig: 2345 90 01 +# description: start/stop fancontrol +# pidfile: /var/run/fancontrol.pid +# + +PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +export PATH + +# Source function library. +. /etc/rc.d/init.d/functions + +FANCONTROL="/usr/local/sbin/fancontrol" +PIDFILE="/var/run/fancontrol.pid" + +RETVAL=0 + +start() +{ + echo -n "Starting fancontrol daemon" + daemon $FANCONTROL -d + RETVAL=$? + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/fancontrol + echo +} + +stop() +{ + echo -n "Stopping fancontrol daemon" + killproc $FANCONTROL + RETVAL=$? + rm -f /var/lock/subsys/fancontrol + echo +} + +status() +{ + if [ -f $PIDFILE ] ; then + pid=`cat $PIDFILE` + else + echo -n "$FANCONTROL does not appear to be running" + echo + exit + fi + + if [ -n "$pid" ] ; then + ps -p $pid > /dev/null + if [ $? ] ; then + echo -n "$FANCONTROL appears to be running" + else + echo -n "$FANCONTROL does not appear to be running" + fi + echo + fi +} + +condrestart() +{ + [ -e /var/lock/subsys/fancontrol ] && restart || : +} + +if [ ! -x $FANCONTROL ] ; then + echo "Cannot run $FANCONTROL" + exit 0 +fi + +case "$1" in + start) + start + ;; + + stop) + stop + ;; + + status) + status + ;; + + restart) + stop + start + ;; + + condrestart) + condrestart + ;; + + *) + echo "Usage: /etc/init.d/fancontrol +{start|stop|status|restart|condrestart}" + RETVAL=1 +esac + +exit $RETVAL diff --git a/prog/init/fancontrol.service b/prog/init/fancontrol.service new file mode 100644 index 0000000..3ac1ed0 --- /dev/null +++ b/prog/init/fancontrol.service @@ -0,0 +1,12 @@ +[Unit] +Description=Start fan control, if configured +ConditionFileNotEmpty=/etc/fancontrol +After=lm_sensors.service + +[Service] +Type=simple +PIDFile=/var/run/fancontrol.pid +ExecStart=/usr/sbin/fancontrol + +[Install] +WantedBy=multi-user.target diff --git a/prog/init/lm_sensors.init b/prog/init/lm_sensors.init new file mode 100755 index 0000000..77172d2 --- /dev/null +++ b/prog/init/lm_sensors.init @@ -0,0 +1,138 @@ +#!/bin/sh +# +# chkconfig: - 26 74 +# description: sensors is used for monitoring motherboard sensor values. +# config: /etc/sysconfig/lm_sensors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. + +# See also the lm_sensors homepage at: +# http://www.lm-sensors.org + +# It uses a config file /etc/sysconfig/lm_sensors that contains the modules +# to be loaded/unloaded. That file is sourced into this one. + +# The format of this file is a shell script that simply defines variables: +# HWMON_MODULES for hardware monitoring driver modules, and optionally +# BUS_MODULES for any required bus driver module (for example for I2C or SPI). + +PSENSORS=/usr/local/bin/sensors + +if [ ! -x $PSENSORS ]; then + PSENSORS=/usr/bin/sensors +fi + +# Source function library. +. /etc/init.d/functions + +RETVAL=0 +prog="lm_sensors" + +# This functions checks if sensor support is compiled into the kernel, if +# sensors are configured, and loads the config file +check_sensors() { + CONFIG=/etc/sysconfig/lm_sensors + if ! [ -r "$CONFIG" ] || ! grep '^HWMON_MODULES' $CONFIG >/dev/null 2>&1; then + echo -n "$1 $prog: not configured, run sensors-detect" + echo_warning + echo + exit 6 + fi + + # Load config file + . "$CONFIG" +} + +start() { + check_sensors "Starting" + + echo -n "Starting $prog: loading module " + + for module in $BUS_MODULES $HWMON_MODULES ; do + echo -n "${module} " + /sbin/modprobe $module >/dev/null 2>&1 + done + $PSENSORS -s + + RETVAL=$? + if [ $RETVAL -eq 0 ] && touch /var/lock/subsys/lm_sensors ; then + echo_success + echo + else + echo_failure + echo + fi +} + +stop() { + check_sensors "Stopping" + + echo -n "Stopping $prog: " + + for module in $HWMON_MODULES $BUS_MODULES ; do + /sbin/modprobe -r $module >/dev/null 2>&1 + done + + RETVAL=$? + if [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/lm_sensors ; then + echo_success + echo + else + echo_failure + echo + fi +} + +dostatus() { + $PSENSORS + RETVAL=$? + if [ $RETVAL -ne 0 ]; then + RETVAL=3 + fi +} + +restart() { + stop + start +} + +condrestart() { + [ -e /var/lock/subsys/lm_sensors ] && restart || : +} + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + dostatus + ;; + restart|reload) + restart + ;; + condrestart) + condrestart + ;; + *) + echo "Usage: $0 {start|stop|status|restart|reload|condrestart}" + exit 3 +esac + +exit $RETVAL diff --git a/prog/init/lm_sensors.service b/prog/init/lm_sensors.service new file mode 100644 index 0000000..7d3bf80 --- /dev/null +++ b/prog/init/lm_sensors.service @@ -0,0 +1,13 @@ +[Unit] +Description=Initialize hardware monitoring sensors + +[Service] +EnvironmentFile=/etc/sysconfig/lm_sensors +Type=oneshot +RemainAfterExit=yes +ExecStart=-/sbin/modprobe -qab $BUS_MODULES $HWMON_MODULES +ExecStart=/usr/bin/sensors -s +ExecStop=-/sbin/modprobe -qabr $BUS_MODULES $HWMON_MODULES + +[Install] +WantedBy=multi-user.target diff --git a/prog/init/sensord.init b/prog/init/sensord.init new file mode 100755 index 0000000..fa95170 --- /dev/null +++ b/prog/init/sensord.init @@ -0,0 +1,157 @@ +#!@BASH@ +# +# @INITRDDIR@/sensord +# +# sensord This shell script takes care of starting and stopping +# sensord, the lm_sensors hardware health monitoring daemon. +# +# Here is the sensors service for SysV init, based on lm_sensors-2.5.5-sensors +# from Mandrake lm_sensors source RPM. It is modified according to recommendations +# for RedHat initscripts. The drivers starting part is taken from alsasound +# service. To configure this service one should put appropriate "alias i2c-bus-0 +# xxx" and "alias i2c-sensors-chip-0 xxx" in /etc/modules.conf. The rest should be +# self explaining. +# +# You put it into /etc/rc.d/init.d/, you make a symlink (probably using +# chkconfig, ntsysv, tksysv or serviceconf program) named S95xxx and K05xxx +# into /etc/rc#.d (where # is the number of runlevel), and sensors service +# (which starts lm_sensors modules, runs sensors -s and starts sensord) +# will be started automatically at startup/reboot and stopped at shutdown. +# One could also start/stop service manually. +# +# This service was tested for RedHat 7.2 only. +# Jakub Nar�bski, Poland +# + +# chkconfig: 2345 05 95 +# processname: sensord +# config: @SYSCONFDIR@/sensors.conf +# pidfile: /var/run/sensord.pid +# description: Sensors is a sensors daemon which can be used to alert you \ +# in the event of a hardware health monitoring alarm. + +# Source function library. +. @INITRDDIR@/functions + +# Set default return value to 0 (success) +RETVAL=0 +# Add @SBINDIR@ (sensord) and @BINDIR@ (sensors) to PATH if necessary +echo "$PATH" | grep -q @SBINDIR@ || PATH=$PATH:@SBINDIR@ +echo "$PATH" | grep -q @BINDIR@ || PATH=$PATH:@BINDIR@ +export PATH + +# Modules to load from modules.conf (modules configuration) +i2c_bus_drivers=�modprobe -c | \ + awk �/^[[:space:]]*alias[[:space:]]+i2c-bus-[[:digit:]]/ { print $3 }�� +i2c_chip_drivers=�modprobe -c | \ + awk �/^[[:space:]]*alias[[:space:]]+i2c-sensors-chip-[[:digit:]]/ { print $3 +}�� + +# Configuration of sensord +interval=1m # interval between scanning for sensor alarms +log_interval=30m # interval between logging all sensor readings + +# Check that we use kernel for which lm_sensors-drivers was installed +[ �uname -r� = @MVERSION@ ] || exit 0 + +# Check that lm_sensors is installed. +[ -x @SBINDIR@/sensord ] || exit 0 +[ -x @BINDIR@/sensors ] || exit 0 + +echo_status() +{ + if [ $1 -eq 0 ]; then + echo_success + else + echo_failure + fi + echo +} + +start() +{ + # Start modules + echo "Starting I2C bus (adapter) drivers: " + for driver in $i2c_bus_drivers; do + echo -n "Starting I2C driver: $driver " + /sbin/modprobe �echo $driver� + echo_status $? + done + echo "Starting I2C chip (sensors) drivers: " + for driver in $i2c_chip_drivers; do + echo -n "Starting I2C driver: $driver " + /sbin/modprobe $(echo $driver) + echo_status $? + done + # Set Alarm + echo -n "Configuring sensors: " + sensors -s && sleep 2 + echo_status $? + # Start daemons. + echo -n $"Starting sensord: " + daemon sensord -i $interval -l $log_interval + RETVAL=$? + + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/sensord + + echo + return $RETVAL +} + +stop() +{ + # Stop daemons. + echo -n $"Shutting down sensord: " + killproc sensord + RETVAL=$? + + echo + # Remove modules + drivers=�echo "$i2c_chip_drivers $i2c_bus_drivers" | \ + tr -s "[:space:]\n" " "� + echo -n "Removing I2C drivers: $drivers" + /sbin/modprobe -r -q $drivers + echo_status $? + + echo + [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sensord + + return $RETVAL +} + +reload() +{ + # Reread configuration file + sensors -s + + return $? +} + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status sensord + ;; + restart) + stop + start + ;; + reload) + reload + ;; + condrestart) + [ -e /var/lock/subsys/sensord ] && restart || : + ;; + *) + echo "Usage: sensord {start|stop|restart|reload|condrestart|status}" + exit 1 + ;; +esac + +exit $? diff --git a/prog/init/sensord.service b/prog/init/sensord.service new file mode 100644 index 0000000..2448bee --- /dev/null +++ b/prog/init/sensord.service @@ -0,0 +1,12 @@ +[Unit] +Description=Log hardware monitoring data +After=lm_sensors.service + +[Service] +EnvironmentFile=/etc/sysconfig/sensord +Type=forking +PIDFile=/var/run/sensord.pid +ExecStart=/usr/sbin/sensord -i $INTERVAL -l $LOG_INTERVAL -f daemon + +[Install] +WantedBy=multi-user.target diff --git a/prog/init/sysconfig-lm_sensors-convert b/prog/init/sysconfig-lm_sensors-convert new file mode 100755 index 0000000..0b907a5 --- /dev/null +++ b/prog/init/sysconfig-lm_sensors-convert @@ -0,0 +1,30 @@ +#!/bin/sh + +# Convert an lm_sensors service configuration file from the old convention +# (MODULE_0, MODULE_1...) to the new convention (HWMON_MODULES). +# +# Copyright (C) 2009 Jean Delvare +# +# Released without a license on purpose. This is public domain code, so +# that package maintainers can include it in their post-install script. + +CONFIG=/etc/sysconfig/lm_sensors +test -r "$CONFIG" || exit 0 + +unset ${!MODULE_*} $HWMON_MODULES +. "$CONFIG" +test -n "$HWMON_MODULES" && exit 0 + +for i in ${!MODULE_*} ; do + eval module=\$$i + if test -z "$HWMON_MODULES" ; then + HWMON_MODULES="$module" + else + HWMON_MODULES="$HWMON_MODULES $module" + fi +done +test -z "$HWMON_MODULES" && exit 0 + +echo >> "$CONFIG" +echo "# New configuration format generated by sysconfig-lm_sensors-convert" >> "$CONFIG" +echo "HWMON_MODULES=\"$HWMON_MODULES\"" >> "$CONFIG" diff --git a/prog/pwm/Module.mk b/prog/pwm/Module.mk new file mode 100644 index 0000000..30de1e3 --- /dev/null +++ b/prog/pwm/Module.mk @@ -0,0 +1,47 @@ +# Module.mk +# Copyright (c) 1998, 1999 Frodo Looijaard +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. + +MODULE_DIR := prog/pwm +PROGPWMDIR := $(MODULE_DIR) + +PROGPWMMAN8DIR := $(MANDIR)/man8 +PROGPWMMAN8FILES := $(MODULE_DIR)/fancontrol.8 $(MODULE_DIR)/pwmconfig.8 + +PROGPWMTARGETS := $(MODULE_DIR)/fancontrol \ + $(MODULE_DIR)/pwmconfig + +# The vt1211_pwm script is not installed by default, pass VT1211_PWM=1 +# to get it +ifeq ($(VT1211_PWM),1) +PROGPWMMAN8FILES += $(MODULE_DIR)/vt1211_pwm.8 +PROGPWMTARGETS += $(MODULE_DIR)/vt1211_pwm +endif + +REMOVEPWMBIN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(SBINDIR)/%,$(PROGPWMTARGETS)) +REMOVEPWMMAN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(PROGPWMMAN8DIR)/%,$(PROGPWMMAN8FILES)) + +install-prog-pwm: $(PROGPWMTARGETS) + $(MKDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(PROGPWMMAN8DIR) + $(INSTALL) -m 755 $(PROGPWMTARGETS) $(DESTDIR)$(SBINDIR) + $(INSTALL) -m 644 $(PROGPWMMAN8FILES) $(DESTDIR)$(PROGPWMMAN8DIR) + +user_install :: install-prog-pwm + +user_uninstall:: + $(RM) $(REMOVEPWMBIN) + $(RM) $(REMOVEPWMMAN) diff --git a/prog/pwm/fancontrol b/prog/pwm/fancontrol new file mode 100755 index 0000000..000a09b --- /dev/null +++ b/prog/pwm/fancontrol @@ -0,0 +1,647 @@ +#!/bin/bash +# +# Simple script implementing a temperature dependent fan speed control +# Supported Linux kernel versions: 2.6.5 and later +# +# Version 0.71 +# +# Usage: fancontrol [CONFIGFILE] +# +# Dependencies: +# bash, grep, sed, cut, sleep, readlink, lm_sensors :) +# +# Please send any questions, comments or success stories to +# marius.reiner@hdev.de +# Thanks! +# +# For configuration instructions and warnings please see fancontrol.txt, which +# can be found in the doc/ directory or at the website mentioned above. +# +# +# Copyright 2003 Marius Reiner +# Copyright (C) 2007-2014 Jean Delvare +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +PIDFILE="/var/run/fancontrol.pid" + +#DEBUG=1 +MAX=255 + +function LoadConfig +{ + local fcvcount fcv + + echo "Loading configuration from $1 ..." + if [ ! -r "$1" ] + then + echo "Error: Can't read configuration file" >&2 + exit 1 + fi + + # grep configuration from file + INTERVAL=$(grep -E '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g') + DEVPATH=$(grep -E '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g') + DEVNAME=$(grep -E '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g') + FCTEMPS=$(grep -E '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g') + MINTEMP=$(grep -E '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g') + MAXTEMP=$(grep -E '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g') + MINSTART=$(grep -E '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g') + MINSTOP=$(grep -E '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g') + # optional settings: + FCFANS=$(grep -E '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g') + MINPWM=$(grep -E '^MINPWM=.*$' $1 | sed -e 's/MINPWM=//g') + MAXPWM=$(grep -E '^MAXPWM=.*$' $1 | sed -e 's/MAXPWM=//g') + + # Check whether all mandatory settings are set + if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]] + then + echo "Some mandatory settings missing, please check your config file!" >&2 + exit 1 + fi + if [ "$INTERVAL" -le 0 ] + then + echo "Error in configuration file:" >&2 + echo "INTERVAL must be at least 1" >&2 + exit 1 + fi + + # write settings to arrays for easier use and print them + echo + echo "Common settings:" + echo " INTERVAL=$INTERVAL" + + let fcvcount=0 + for fcv in $FCTEMPS + do + if ! echo $fcv | grep -E -q '=' + then + echo "Error in configuration file:" >&2 + echo "FCTEMPS value is improperly formatted" >&2 + exit 1 + fi + + AFCPWM[$fcvcount]=$(echo $fcv |cut -d'=' -f1) + AFCTEMP[$fcvcount]=$(echo $fcv |cut -d'=' -f2) + AFCFAN[$fcvcount]=$(echo $FCFANS |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2) + AFCMINTEMP[$fcvcount]=$(echo $MINTEMP |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2) + AFCMAXTEMP[$fcvcount]=$(echo $MAXTEMP |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2) + AFCMINSTART[$fcvcount]=$(echo $MINSTART |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2) + AFCMINSTOP[$fcvcount]=$(echo $MINSTOP |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2) + AFCMINPWM[$fcvcount]=$(echo $MINPWM |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2) + [ -z "${AFCMINPWM[$fcvcount]}" ] && AFCMINPWM[$fcvcount]=0 + AFCMAXPWM[$fcvcount]=$(echo $MAXPWM |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2) + [ -z "${AFCMAXPWM[$fcvcount]}" ] && AFCMAXPWM[$fcvcount]=255 + + # verify the validity of the settings + if [ "${AFCMINTEMP[$fcvcount]}" -ge "${AFCMAXTEMP[$fcvcount]}" ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MINTEMP must be less than MAXTEMP" >&2 + exit 1 + fi + if [ "${AFCMAXPWM[$fcvcount]}" -gt 255 ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MAXPWM must be at most 255" >&2 + exit 1 + fi + if [ "${AFCMINSTOP[$fcvcount]}" -ge "${AFCMAXPWM[$fcvcount]}" ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MINSTOP must be less than MAXPWM" >&2 + exit 1 + fi + if [ "${AFCMINSTOP[$fcvcount]}" -lt "${AFCMINPWM[$fcvcount]}" ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MINSTOP must be greater than or equal to MINPWM" >&2 + exit 1 + fi + if [ "${AFCMINPWM[$fcvcount]}" -lt 0 ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MINPWM must be at least 0" >&2 + exit 1 + fi + + echo + echo "Settings for ${AFCPWM[$fcvcount]}:" + echo " Depends on ${AFCTEMP[$fcvcount]}" + echo " Controls ${AFCFAN[$fcvcount]}" + echo " MINTEMP=${AFCMINTEMP[$fcvcount]}" + echo " MAXTEMP=${AFCMAXTEMP[$fcvcount]}" + echo " MINSTART=${AFCMINSTART[$fcvcount]}" + echo " MINSTOP=${AFCMINSTOP[$fcvcount]}" + echo " MINPWM=${AFCMINPWM[$fcvcount]}" + echo " MAXPWM=${AFCMAXPWM[$fcvcount]}" + let fcvcount=fcvcount+1 + done + echo +} + +function DevicePath() +{ + if [ -h "$1/device" ] + then + readlink -f "$1/device" | sed -e 's/^\/sys\///' + fi +} + +function DeviceName() +{ + if [ -r "$1/name" ] + then + cat "$1/name" | sed -e 's/[[:space:]=]/_/g' + elif [ -r "$1/device/name" ] + then + cat "$1/device/name" | sed -e 's/[[:space:]=]/_/g' + fi +} + +function ValidateDevices() +{ + local OLD_DEVPATH="$1" OLD_DEVNAME="$2" outdated=0 + local entry device name path + + for entry in $OLD_DEVPATH + do + device=$(echo "$entry" | sed -e 's/=[^=]*$//') + path=$(echo "$entry" | sed -e 's/^[^=]*=//') + + if [ "$(DevicePath "$device")" != "$path" ] + then + echo "Device path of $device has changed" >&2 + outdated=1 + fi + done + + for entry in $OLD_DEVNAME + do + device=$(echo "$entry" | sed -e 's/=[^=]*$//') + name=$(echo "$entry" | sed -e 's/^[^=]*=//') + + if [ "$(DeviceName "$device")" != "$name" ] + then + echo "Device name of $device has changed" >&2 + outdated=1 + fi + done + + return $outdated +} + +function FixupDeviceFiles +{ + local DEVICE="$1" + local fcvcount pwmo tsen fan + + let fcvcount=0 + while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs + do + pwmo=${AFCPWM[$fcvcount]} + AFCPWM[$fcvcount]=${pwmo//$DEVICE\/device/$DEVICE} + if [ "${AFCPWM[$fcvcount]}" != "$pwmo" ] + then + echo "Adjusing $pwmo -> ${AFCPWM[$fcvcount]}" + fi + let fcvcount=$fcvcount+1 + done + + let fcvcount=0 + while (( $fcvcount < ${#AFCTEMP[@]} )) # go through all temp inputs + do + tsen=${AFCTEMP[$fcvcount]} + AFCTEMP[$fcvcount]=${tsen//$DEVICE\/device/$DEVICE} + if [ "${AFCTEMP[$fcvcount]}" != "$tsen" ] + then + echo "Adjusing $tsen -> ${AFCTEMP[$fcvcount]}" + fi + let fcvcount=$fcvcount+1 + done + + let fcvcount=0 + while (( $fcvcount < ${#AFCFAN[@]} )) # go through all fan inputs + do + fan=${AFCFAN[$fcvcount]} + AFCFAN[$fcvcount]=${fan//$DEVICE\/device/$DEVICE} + if [ "${AFCFAN[$fcvcount]}" != "$fan" ] + then + echo "Adjusing $fan -> ${AFCFAN[$fcvcount]}" + fi + let fcvcount=$fcvcount+1 + done +} + +# Some drivers moved their attributes from hard device to class device +function FixupFiles +{ + local DEVPATH="$1" + local entry device + + for entry in $DEVPATH + do + device=$(echo "$entry" | sed -e 's/=[^=]*$//') + + if [ -e "$device/name" ] + then + FixupDeviceFiles "$device" + fi + done +} + +# Check that all referenced sysfs files exist +function CheckFiles +{ + local outdated=0 fcvcount pwmo tsen fan + + let fcvcount=0 + while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs + do + pwmo=${AFCPWM[$fcvcount]} + if [ ! -w $pwmo ] + then + echo "Error: file $pwmo doesn't exist" >&2 + outdated=1 + fi + let fcvcount=$fcvcount+1 + done + + let fcvcount=0 + while (( $fcvcount < ${#AFCTEMP[@]} )) # go through all temp inputs + do + tsen=${AFCTEMP[$fcvcount]} + if [ ! -r $tsen ] + then + echo "Error: file $tsen doesn't exist" >&2 + outdated=1 + fi + let fcvcount=$fcvcount+1 + done + + let fcvcount=0 + while (( $fcvcount < ${#AFCFAN[@]} )) # go through all fan inputs + do + # A given PWM output can control several fans + for fan in $(echo ${AFCFAN[$fcvcount]} | sed -e 's/+/ /') + do + if [ ! -r $fan ] + then + echo "Error: file $fan doesn't exist" >&2 + outdated=1 + fi + done + let fcvcount=$fcvcount+1 + done + + if [ $outdated -eq 1 ] + then + echo >&2 + echo "At least one referenced file is missing. Either some required kernel" >&2 + echo "modules haven't been loaded, or your configuration file is outdated." >&2 + echo "In the latter case, you should run pwmconfig again." >&2 + fi + + return $outdated +} + +if [ -f "$1" ] +then + LoadConfig $1 +else + LoadConfig /etc/fancontrol +fi + +# Detect path to sensors +if echo "${AFCPWM[0]}" | grep -E -q '^/' +then + DIR=/ +elif echo "${AFCPWM[0]}" | grep -E -q '^hwmon[0-9]' +then + DIR=/sys/class/hwmon +elif echo "${AFCPWM[0]}" | grep -E -q '^[1-9]*[0-9]-[0-9abcdef]{4}' +then + DIR=/sys/bus/i2c/devices +else + echo "$0: Invalid path to sensors" >&2 + exit 1 +fi + +if [ ! -d $DIR ] +then + echo $0: 'No sensors found! (did you load the necessary modules?)' >&2 + exit 1 +fi +cd $DIR + +# Check for configuration change +if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +then + echo "Configuration is too old, please run pwmconfig again" >&2 + exit 1 +fi +if [ "$DIR" = "/" -a -n "$DEVPATH" ] +then + echo "Unneeded DEVPATH with absolute device paths" >&2 + exit 1 +fi +if ! ValidateDevices "$DEVPATH" "$DEVNAME" +then + echo "Configuration appears to be outdated, please run pwmconfig again" >&2 + exit 1 +fi +if [ "$DIR" = "/sys/class/hwmon" ] +then + FixupFiles "$DEVPATH" +fi +CheckFiles || exit 1 + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists, is fancontrol already running?" >&2 + exit 1 +fi +echo $$ > "$PIDFILE" + +# associative arrays to hold pwmN device name as key, and as value the +# pwmN_enable and pwmN values as they were before fancontrol was started +declare -A PWM_ENABLE_ORIG_STATE +declare -A PWM_ORIG_STATE + +# $1 = pwm file name +function pwmdisable() +{ + local ENABLE=${1}_enable + + # No enable file? Just set to max + if [ ! -f $ENABLE ] + then + echo $MAX > $1 + return 0 + fi + + # Try to restore pwmN and pwmN_enable value to the same state as before + # fancontrol start. Restoring the pwmN value is tried first, before the + # pwmN_enable mode switch. + # Some chips seem to need this to properly restore fan operation, + # when activating automatic (2) mode. + if [ ${PWM_ENABLE_ORIG_STATE[${1}]} ] + then + #restore the pwmN value + if [ "$DEBUG" != "" ] + then + echo "Restoring ${1} original value of ${PWM_ORIG_STATE[${1}]}" + fi + echo ${PWM_ORIG_STATE[${1}]} > ${1} 2> /dev/null + # restore the pwmN_enable value, if it is not 1. + # 1 is already set through fancontrol and setting it again might just + # reset the pwmN value. + if [ ${PWM_ENABLE_ORIG_STATE[${1}]} != 1 ] + then + if [ "$DEBUG" != "" ] + then + echo "Restoring $ENABLE original value of ${PWM_ENABLE_ORIG_STATE[${1}]}" + fi + echo ${PWM_ENABLE_ORIG_STATE[${1}]} > $ENABLE 2> /dev/null + # check if setting pwmN_enable value was successful. Checking the + # pwmN value makes no sense, as it might already have been altered + # by the chip. + if [ "$(cat $ENABLE)" = ${PWM_ENABLE_ORIG_STATE[${1}]} ] + then + return 0 + fi + # if pwmN_enable is manual (1), check if restoring the pwmN value worked + elif [ "$(cat ${1})" = ${PWM_ORIG_STATE[${1}]} ] + then + return 0 + fi + fi + + # Try pwmN_enable=0 + echo 0 > $ENABLE 2> /dev/null + if [ "$(cat $ENABLE)" -eq 0 ] + then + # Success + return 0 + fi + + # It didn't work, try pwmN_enable=1 pwmN=255 + echo 1 > $ENABLE 2> /dev/null + echo $MAX > $1 + if [ "$(cat $ENABLE)" -eq 1 -a "$(cat $1)" -ge 190 ] + then + # Success + return 0 + fi + + # Nothing worked + echo "$ENABLE stuck to" "$(cat $ENABLE)" >&2 + return 1 +} + +# $1 = pwm file name +function pwmenable() +{ + local ENABLE=${1}_enable + + if [ -f $ENABLE ] + then + # save the original pwmN_control state, e.g. 1 for manual or 2 for auto, + # and the value from pwmN + local PWM_CONTROL_ORIG=$(cat $ENABLE) + local PWM_ORIG=$(cat ${1}) + if [ "$DEBUG" != "" ] + then + echo "Saving $ENABLE original value as $PWM_CONTROL_ORIG" + echo "Saving ${1} original value as $PWM_ORIG" + fi + #check for degenerate case where these values might be empty + if [ $PWM_CONTROL_ORIG ] && [ $PWM_ORIG ] + then + PWM_ENABLE_ORIG_STATE[${1}]=$PWM_CONTROL_ORIG + PWM_ORIG_STATE[${1}]=$PWM_ORIG + fi + # enable manual control by fancontrol + echo 1 > $ENABLE 2> /dev/null + if [ $? -ne 0 ] + then + return 1 + fi + fi + echo $MAX > $1 +} + +function restorefans() +{ + local status=$1 fcvcount pwmo + + echo 'Aborting, restoring fans...' + let fcvcount=0 + while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs + do + pwmo=${AFCPWM[$fcvcount]} + pwmdisable $pwmo + let fcvcount=$fcvcount+1 + done + echo 'Verify fans have returned to full speed' + rm -f "$PIDFILE" + exit $status +} + +trap 'restorefans 0' SIGQUIT SIGTERM +trap 'restorefans 1' SIGHUP SIGINT + +# main function +function UpdateFanSpeeds +{ + local fcvcount + local pwmo tsens fan mint maxt minsa minso minpwm maxpwm + local tval pwmpval fanval min_fanval one_fan one_fanval + local -i pwmval + + let fcvcount=0 + while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs + do + #hopefully shorter vars will improve readability: + pwmo=${AFCPWM[$fcvcount]} + tsens=${AFCTEMP[$fcvcount]} + fan=${AFCFAN[$fcvcount]} + let mint="${AFCMINTEMP[$fcvcount]}*1000" + let maxt="${AFCMAXTEMP[$fcvcount]}*1000" + minsa=${AFCMINSTART[$fcvcount]} + minso=${AFCMINSTOP[$fcvcount]} + minpwm=${AFCMINPWM[$fcvcount]} + maxpwm=${AFCMAXPWM[$fcvcount]} + + read tval < ${tsens} + if [ $? -ne 0 ] + then + echo "Error reading temperature from $DIR/$tsens" + restorefans 1 + fi + + read pwmpval < ${pwmo} + if [ $? -ne 0 ] + then + echo "Error reading PWM value from $DIR/$pwmo" + restorefans 1 + fi + + # If fanspeed-sensor output shall be used, do it + if [[ -n ${fan} ]] + then + min_fanval=100000 + fanval= + # A given PWM output can control several fans + for one_fan in $(echo $fan | sed -e 's/+/ /') + do + read one_fanval < ${one_fan} + if [ $? -ne 0 ] + then + echo "Error reading Fan value from $DIR/$one_fan" >&2 + restorefans 1 + fi + + # Remember the minimum, it only matters if it is 0 + if [ $one_fanval -lt $min_fanval ] + then + min_fanval=$one_fanval + fi + + if [ -z "$fanval" ] + then + fanval=$one_fanval + else + fanval="$fanval/$one_fanval" + fi + done + else + min_fanval=1 # set it to a non zero value, so the rest of the script still works + fi + + # debug info + if [ "$DEBUG" != "" ] + then + echo "pwmo=$pwmo" + echo "tsens=$tsens" + echo "fan=$fan" + echo "mint=$mint" + echo "maxt=$maxt" + echo "minsa=$minsa" + echo "minso=$minso" + echo "minpwm=$minpwm" + echo "maxpwm=$maxpwm" + echo "tval=$tval" + echo "pwmpval=$pwmpval" + echo "fanval=$fanval" + echo "min_fanval=$min_fanval" + fi + + if (( $tval <= $mint )) + then pwmval=$minpwm # below min temp, use defined min pwm + elif (( $tval >= $maxt )) + then pwmval=$maxpwm # over max temp, use defined max pwm + else + # calculate the new value from temperature and settings + pwmval="(${tval}-${mint})*(${maxpwm}-${minso})/(${maxt}-${mint})+${minso}" + if [ $pwmpval -eq 0 -o $min_fanval -eq 0 ] + then # if fan was stopped start it using a safe value + echo $minsa > $pwmo + # Sleep while still handling signals + sleep 1 & + wait + fi + fi + echo $pwmval > $pwmo # write new value to pwm output + if [ $? -ne 0 ] + then + echo "Error writing PWM value to $DIR/$pwmo" >&2 + restorefans 1 + fi + if [ "$DEBUG" != "" ] + then + echo "new pwmval=$pwmval" + fi + let fcvcount=$fcvcount+1 + done +} + +echo 'Enabling PWM on fans...' +let fcvcount=0 +while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs +do + pwmo=${AFCPWM[$fcvcount]} + pwmenable $pwmo + if [ $? -ne 0 ] + then + echo "Error enabling PWM on $DIR/$pwmo" >&2 + restorefans 1 + fi + let fcvcount=$fcvcount+1 +done + +echo 'Starting automatic fan control...' + +# main loop calling the main function at specified intervals +while true +do + UpdateFanSpeeds + # Sleep while still handling signals + sleep $INTERVAL & + wait +done diff --git a/prog/pwm/fancontrol.8 b/prog/pwm/fancontrol.8 new file mode 100644 index 0000000..98fc5e5 --- /dev/null +++ b/prog/pwm/fancontrol.8 @@ -0,0 +1,124 @@ +.TH FANCONTROL 8 "September 2009" "lm-sensors 3" +.SH NAME +fancontrol \- automated software based fan speed regulation + +.SH SYNOPSIS +.B fancontrol +.I [configfile] + +.SH DESCRIPTION +\fBfancontrol\fP is a shell script for use with lm_sensors. It reads its +configuration from a file, then calculates fan speeds from temperatures and +sets the corresponding PWM outputs to the computed values. + +.SH WARNING +Please be careful when using the fan control features of your mainboard, in +addition to the risk of burning your CPU, at higher temperatures there will be +a higher wearout of your other hardware components, too. So if you plan to use +these components in 50 years, \fBmaybe\fP you shouldn't use fancontrol +at all. Also please keep in mind most fans aren't designed to be +powered by a PWMed voltage. + +In practice it doesn't seem to be a major issue, the fans will get slightly +warmer, just be sure to have a temperature alarm and/or shutdown call, in case +some fan fails, because you probably won't hear it anymore ;) + +.SH CONFIGURATION +For easy configuration, there's a script +named \fBpwmconfig\fP(8) which lets you interactively write your +configuration file for \fBfancontrol\fP. Alternatively you can write this +file yourself using the information from this manpage. + +Since most of you are going to use \fBpwmconfig\fP(8) script, the config +file syntax will be discussed last. First I'm going to describe the various +variables available for changing \fBfancontrol\fP's behaviour: + +.TP +.B INTERVAL +This variable defines at which interval in seconds the main loop of +\fBfancontrol\fP will be executed +.TP +.B DEVPATH +Maps hwmon class devices to physical devices. This lets \fBfancontrol\fP +check that the configuration file is still up-to-date. +.TP +.B DEVNAME +Records hwmon class device names. This lets \fBfancontrol\fP check that +the configuration file is still up-to-date. +.TP +.B FCTEMPS +Maps PWM outputs to temperature sensors so \fBfancontrol\fP knows which +temperature sensors should be used for calculation of new values for +the corresponding PWM outputs. +.TP +.B FCFANS +Records the association between a PWM output and a fan input. +Then \fBfancontrol\fP can check the fan speed and restart it if it +stops unexpectedly. +.TP +.B MINTEMP +The temperature below which the fan gets switched to minimum speed. +.TP +.B MAXTEMP +The temperature over which the fan gets switched to maximum speed. +.TP +.B MINSTART +Sets the minimum speed at which the fan begins spinning. You should +use a safe value to be sure it works, even when the fan gets old. +.TP +.B MINSTOP +The minimum speed at which the fan still spins. Use a safe value here, +too. +.TP +.B MINPWM +The PWM value to use when the temperature is below MINTEMP. +Typically, this will be either 0 if it is OK for the fan to plain +stop, or the same value as MINSTOP if you don't want the fan to +ever stop. +If this value isn't defined, it defaults to 0 (stopped fan). +.TP +.B MAXPWM +The PWM value to use when the temperature is over MAXTEMP. +If this value isn't defined, it defaults to 255 (full speed). +.PP +The configuration file format is a bit strange: +.IP +.nf +VARIABLE=chip/pwmdev=value chip/pwmdev2=value2 +VARIABLE2=... +.fi +.PP +Each variable has its own line. The variable name is followed by an equal sign +and the device=value pairs. These consist of the path to the pwm output for +which the value is valid, equal sign followed by the value and are separated +by a blank. Path can be absolute or relative (from /sys/bus/i2c/devices or +/sys/class/hwmon depending on the kernel version). Example: +.IP +MINTEMP=hwmon0/device/pwm1=40 hwmon0/device/pwm2=54 +.PP +You have to play with the temperature values a bit to get happy. For initial +setup I recommend using the \fBpwmconfig\fP script. Small changes can be made by +editing the config file directly following the rules above. + +Upon starting, fancontrol will make sure that all referenced devices +do exist and match what they were at configuration time, and that all +referenced sysfs files do exist. If not, it will quit immediately, upon +the assumption that the configuration file may be out-of-sync with the +loaded kernel drivers. + +.SH THE ALGORITHM + +\fBfancontrol\fP first reads its configuration, writes it to arrays and loops its +main function. This function gets the temperatures and fanspeeds from +kernel driver files and calculates new speeds depending on temperature +changes, but only if the temp is between MINTEMP and MAXTEMP. After that, the +new values are written to the PWM outputs. Currently the speed increases +linearly with rising temperature. This way you won't hear your fans most +of the time at best. + +.SH SEE ALSO +pwmconfig(8), sensors(1). + +.SH AUTHOR +.PP +Marius Reiner diff --git a/prog/pwm/pwmconfig b/prog/pwm/pwmconfig new file mode 100755 index 0000000..c24c891 --- /dev/null +++ b/prog/pwm/pwmconfig @@ -0,0 +1,1036 @@ +#!/bin/bash +# +# pwmconfig +# Tests the pwm outputs of sensors and configures fancontrol +# Supported Linux kernel versions: 2.6.5 and later +# +# Warning!!! This program will stop your fans, one at a time, +# for approximately 5 seconds each!!! +# This may cause your processor temperature to rise!!! +# Verify that all fans are running at normal speed after this +# program has exited!!! +# +# Copyright (C) 2007-2013 Jean Delvare +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +REVISION=$(echo '$Revision$' | cut -d' ' -f2) +REVDATE=$(echo '$Date$' | cut -d' ' -f2) +PIDFILE="/var/run/fancontrol.pid" + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists. This typically means that the" + echo "fancontrol deamon is running. You should stop it before running pwmconfig." + echo "If you are certain that fancontrol is not running, then you can delete" + echo "$PIDFILE manually." + exit 1 +fi + +if [ "$(id -u)" != "0" ] +then + echo "You need to be root to run this script." + exit 1 +fi + +echo "# pwmconfig revision $REVISION ($REVDATE)" +echo 'This program will search your sensors for pulse width modulation (pwm)' +echo 'controls, and test each one to see if it controls a fan on' +echo 'your motherboard. Note that many motherboards do not have pwm' +echo 'circuitry installed, even if your sensor chip supports pwm.' +echo +echo 'We will attempt to briefly stop each fan using the pwm controls.' +echo 'The program will attempt to restore each fan to full speed' +echo 'after testing. However, it is ** very important ** that you' +echo 'physically verify that the fans have been to full speed' +echo 'after the program has completed.' +echo + +DELAY=5 # 3 seconds delay is too short for large fans, thus I increased it to 5 +MAX=255 + +if [ -d "/sys/class/hwmon" ] +then + SYSFS=2 + DIR="/sys/class/hwmon" + PREFIX='hwmon*' +elif [ -d "/sys/bus/i2c/devices" ] +then + SYSFS=1 + DIR="/sys/bus/i2c/devices" + PREFIX='*-*' +else + echo $0: 'No sensors found! (modprobe sensor modules?)' + exit 1 +fi + +cd $DIR +DEVICES=$(echo $PREFIX) +if [ "$PREFIX" = "$DEVICES" ] +then + echo $0: 'No sensors found! (modprobe sensor modules?)' + exit 1 +fi + +# We may need to adjust the device path +if [ "$SYSFS" = "2" ] +then + OLD_DEVICES="$DEVICES" + DEVICES="" + + for device in $OLD_DEVICES + do + if [ ! -r "$device/name" ] + then + device="$device/device" + fi + + DEVICES="$DEVICES $device" + done +fi + + +for device in $DEVICES +do + # Find available fan control outputs + MATCH=$device/'pwm[1-9]' + device_pwm=$(echo $MATCH) + if [ "$SYSFS" = "1" -a "$MATCH" = "$device_pwm" ] + then + # Deprecated naming scheme (used in kernels 2.6.5 to 2.6.9) + MATCH=$device/'fan[1-9]_pwm' + device_pwm=$(echo $MATCH) + fi + if [ "$MATCH" != "$device_pwm" ] + then + PWM="$PWM $device_pwm" + fi + + # Find available fan monitoring inputs + MATCH=$device/'fan[1-9]_input' + device_fan=$(echo $MATCH) + if [ "$MATCH" != "$device_fan" ] + then + FAN="$FAN $device_fan" + fi +done + +if [ -z "$PWM" ] +then + echo $0: 'There are no pwm-capable sensor modules installed' + exit 1 +fi +if [ -z "$FAN" ] +then + echo $0: 'There are no fan-capable sensor modules installed' + exit 1 +fi + +# $1 = padding +function print_devices() +{ + local name device + + for device in $DEVICES + do + name=$(cat $device/name 2> /dev/null) + [ -z "$name" ] && name="unknown (no name attribute)" + echo "$1$device is $name" + done +} + +# $1 = pwm file name +function is_pwm_auto() +{ + local ENABLE=${1}_enable + + if [ -f $ENABLE ] + then + if [ "$(cat $ENABLE)" -gt 1 ] + then + return 0 + fi + fi + + return 1 +} + +# $1 = pwm file name +function pwmdisable() +{ + local ENABLE=${1}_enable + + # No enable file? Just set to max + if [ ! -f $ENABLE ] + then + echo $MAX > $1 + return 0 + fi + + # Try pwmN_enable=0 + echo 0 2>/dev/null > $ENABLE + if [ "$(cat $ENABLE)" -eq 0 ] + then + # Success + return 0 + fi + + # It didn't work, try pwmN_enable=1 pwmN=255 + echo 1 2>/dev/null > $ENABLE + if [ "$(cat $ENABLE)" -ne 1 ] + then + echo "$ENABLE stuck to $(cat $ENABLE)" >&2 + return 1 + fi + + echo $MAX > $1 + if [ "$(cat $1)" -ge 190 ] + then + # Success + return 0 + fi + + # Nothing worked + echo "$1 stuck to $(cat $1)" >&2 + return 1 +} + +# $1 = pwm file name +function pwmenable() +{ + local ENABLE=${1}_enable + + if [ -w $ENABLE ] + then + echo 1 2>/dev/null > $ENABLE + if [ $? -ne 0 ] + then + return 1 + fi + fi + echo $MAX > $1 +} + +# $1 = pwm file name; $2 = pwm value 0-255 +function pwmset() +{ + echo $2 > $1 +} + +echo 'Found the following devices:' +print_devices " " +echo + +echo 'Found the following PWM controls:' +for i in $PWM +do + P=$(cat $i) + echo " $i current value: $P" + if [ -w $i ] + then + # First check if PWM output is in automatic mode + if is_pwm_auto $i + then + echo "$i is currently setup for automatic speed control." + echo 'In general, automatic mode is preferred over manual mode, as' + echo 'it is more efficient and it reacts faster. Are you sure that' + echo -n 'you want to setup this output for manual control? (n) ' + read X + if [ "$X" = "" -o "$X" != "y" -a "$X" != "Y" ] + then + continue + fi + fi + + pwmdisable $i + if [ $? -ne 0 ] + then + echo "Manual control mode not supported, skipping $i." + elif [ "$GOODPWM" = "" ] + then + GOODPWM=$i + else + GOODPWM="$GOODPWM $i" + fi + else + echo "Can't write to $i, skipping." + fi +done + +if [ "$GOODPWM" = "" ] +then + echo 'There are no usable PWM outputs.' + exit 1 +fi + +echo +echo "Giving the fans some time to reach full speed..." +sleep $DELAY +echo 'Found the following fan sensors:' +for i in $FAN +do + S=$(cat $i) + if [ "$S" = "0" -o "$S" = "-1" ] + then + echo " $i current speed: 0 ... skipping!" + else + echo " $i current speed: $S RPM" + if [ "$GOODFAN" = "" ] + then + GOODFAN=$i + SPEEDS=$S + else + GOODFAN="$GOODFAN $i" + SPEEDS="$SPEEDS $S" + fi + fi +done +echo + +if [ "$GOODFAN" = "" ] +then + echo 'There are no working fan sensors, all readings are 0.' + echo 'Make sure you have a 3-wire fan connected.' + echo 'You may also need to increase the fan divisors.' + echo 'See doc/fan-divisors for more information.' + exit 1 +fi + +echo 'Warning!!! This program will stop your fans, one at a time,' +echo "for approximately $DELAY seconds each!!!" +echo 'This may cause your processor temperature to rise!!!' +echo 'If you do not want to do this hit control-C now!!!' +echo -n 'Hit return to continue: ' +read X +echo + +PLOTTER=gnuplot +STEP=15 +PDELAY=2 +# Use a smaller step for low PWM values as this is typically where the +# more important fan speed changes are happening. +STEP2=2 +STEP2_BELOW=31 + +function pwmdetail() +{ + local P=$1 F=$2 + local X PLOT= + local TMP1 TMP2 + local threshold=100000 pwm S + + type $PLOTTER > /dev/null 2>&1 + if [ $? -eq 0 ] + then + echo -n "Would you like to generate a graphical plot using $PLOTTER (y)? " + read X + if [ "$X" = "y" -o "$X" = "Y" -o "$X" = "" ] + then + PLOT=y + fi + else + if [ -n "$DISPLAY" ] + then + echo "Note: If you had $PLOTTER installed, I could generate a graphical plot." + fi + fi + + if [ "$PLOT" = "y" ] + then + TMP1=$(mktemp -t pwmtest1.XXXXXXXXXX) || { echo "$0: Cannot create temporary file" >&2; exit 1; } + TMP2=$(mktemp -t pwmtest2.XXXXXXXXXX) || { rm -f $TMP1 ; echo "$0: Cannot create temporary file" >&2; exit 1; } + echo "set xlabel \"PWM: $P\"" > $TMP1 + echo "set ylabel \"FAN: $F (RPM)\"" >> $TMP1 + echo 'set nokey' >> $TMP1 + echo 'set xrange [0:255]' >> $TMP1 + echo "plot \"$TMP2\" with lines" >> $TMP1 + echo 'pause -1 " Hit return to continue..."' >> $TMP1 + > $TMP2 + fi + + let pwm=$MAX + pwmenable $P + while [ $pwm -ge 0 ] + do + pwmset $P $pwm + sleep $PDELAY + if [ $? -ne 0 ] + then + pwmdisable $P + echo '^C received, aborting...' + rm -f $TMP1 $TMP2 + exit 1 + fi + S=$(cat $F) + # Fan speed should never increase significantly + if [ $S -gt $threshold ] + then + echo " PWM $pwm FAN $S (probably incorrect)" + else + echo " PWM $pwm FAN $S" + let threshold=S*6/5 + fi + + if [ "$PLOT" = "y" ] + then + echo "$pwm $S" >> $TMP2 + fi + if [ "$S" = "0" -o "$S" = "-1" ] + then + pwmdisable $P + echo " Fan Stopped at PWM = $pwm" + if [ $pwm -eq $MAX ] + then + echo " This fan appears to stop when the PWM is enabled;" + echo " perhaps the fan input shares a pin with the PWM output" + echo " on the sensor chip." + echo " You cannot control this fan with this PWM output." + rm -f $TMP1 $TMP2 + echo + return 0 + fi + break + fi + if [ $pwm -lt $STEP2_BELOW ] + then + let pwm=$pwm-$STEP2 + else + let pwm=$pwm-$STEP + fi + done + pwmdisable $P + if [ "$PLOT" = "y" ] + then + $PLOTTER $TMP1 + rm -f $TMP1 $TMP2 + fi + echo +} + +for i in $GOODPWM +do + echo Testing pwm control $i ... + pwmenable $i + if [ $? -ne 0 ] + then + echo "Manual control mode not supported, skipping." + continue + fi + pwmset $i 0 + sleep $DELAY + if [ $? -ne 0 ] + then + pwmdisable $i + echo '^C received, restoring PWM and aborting...' + exit 1 + fi + + # Sample all current fan speeds at once, so that we can quickly + # disable PWM and return all fans to full speed + CURRENT_SPEEDS="$(cat $GOODFAN)" + pwmdisable $i + + let pwmactivecount=0 + let count=1 + S_MIN= + for j in $GOODFAN + do + OS=$(echo $SPEEDS | cut -d' ' -f$count) + S=$(echo $CURRENT_SPEEDS | cut -d' ' -f$count) + echo " $j ... speed was $OS now $S" + let threshold=3*$OS/4 + if [ $S -lt $threshold ] + then + echo " It appears that fan $j" + echo " is controlled by pwm $i" +# +# a PWM can control more than one fan.... +# + if [ $pwmactivecount -eq 0 ] + then + let pwmactivecount=1 + pwmactive="$i ${pwmactive}" + fanactive="$j ${fanactive}" + + # Give all correlated fans time to return to full speed + sleep $DELAY + if [ $? -ne 0 ] + then + echo '^C received, aborting...' + exit 1 + fi + else + fanactive="$j+${fanactive}" + fi + + # Keep track of the slowest fan controlled by one PWM + if [ -z "$S_MIN" ] || [ $S -lt $S_MIN ] + then + S_MIN=$S + fi + + S=$(cat $j) + if [ $S -lt $threshold ] + then + echo " Fan $j has not returned to speed, please investigate!" + else + echo -n "Would you like to generate a detailed correlation (y)? " + read X + if [ "$X" = "y" -o "$X" = "Y" -o "$X" = "" ] + then + pwmdetail $i $j + fi + fi + else + echo " no correlation" + fi + let count=count+1 + done + echo + if [ "$pwmactivecount" = "0" ] + then + echo "No correlations were detected." + echo "There is either no fan connected to the output of $i," + echo "or the connected fan has no rpm-signal connected to one of" + echo "the tested fan sensors. (Note: not all motherboards have" + echo "the pwm outputs connected to the fan connectors," + echo "check out the hardware database on http://www.almico.com/forumindex.php)" + echo + echo -n "Did you see/hear a fan stopping during the above test (n)? " + read X + if [ "$X" = "y" -o "$X" = "Y" ] + then + pwmactive="$i ${pwmactive}" + fanactive_min="0 $fanactive_min" + fi + echo + else + fanactive_min="$S_MIN $fanactive_min" + fi +done + + +echo 'Testing is complete.' +echo 'Please verify that all fans have returned to their normal speed.' +echo +echo 'The fancontrol script can automatically respond to temperature changes' +echo 'of your system by changing fanspeeds.' +echo -n 'Do you want to set up its configuration file now (y)? ' + +read X +if [ "$X" = "n" -o "$X" = "N" ] +then + exit +fi + +for device in $DEVICES +do + # Find available temperature monitoring inputs + MATCH=$device/'temp[1-9]_input' + device_temp=$(echo $MATCH) + if [ "$MATCH" != "$device_temp" ] + then + TEMPS="$TEMPS $device_temp" + fi +done + +if [ -z "$TEMPS" ] +then + echo $0: 'There are no temperature-capable sensor modules installed' + exit 1 +fi + +function DevicePath() +{ + if [ -h "$1/device" ] + then + readlink -f "$1/device" | sed -e 's/^\/sys\///' + fi +} + +function DeviceName() +{ + if [ -r "$1/name" ] + then + cat "$1/name" | sed -e 's/[[:space:]=]/_/g' + elif [ -r "$1/device/name" ] + then + cat "$1/device/name" | sed -e 's/[[:space:]=]/_/g' + fi +} + +function ValidateDevices() +{ + local OLD_DEVPATH="$1" OLD_DEVNAME="$2" outdated=0 + local entry device name path + + for entry in $OLD_DEVPATH + do + device=$(echo "$entry" | sed -e 's/=[^=]*$//') + path=$(echo "$entry" | sed -e 's/^[^=]*=//') + + if [ "$(DevicePath "$device")" != "$path" ] + then + echo "Device path of $device has changed" + outdated=1 + fi + done + + for entry in $OLD_DEVNAME + do + device=$(echo "$entry" | sed -e 's/=[^=]*$//') + name=$(echo "$entry" | sed -e 's/^[^=]*=//') + + if [ "$(DeviceName "$device")" != "$name" ] + then + echo "Device name of $device has changed" + outdated=1 + fi + done + + return $outdated +} + +function AskPath() +{ + echo -n 'What should be the path to your fancontrol config file (/etc/fancontrol)? ' + + read FCCONFIG + if [ "$FCCONFIG" = "" ] + then + FCCONFIG="/etc/fancontrol" + fi +} + +AskPath + +function ClearConfig() +{ + FCTEMPS="" + FCFANS="" + MINTEMP="" + MAXTEMP="" + MINSTART="" + MINSTOP="" + MINPWM="" + MAXPWM="" +} + +function LoadConfig() +{ + local OLD_DEVPATH OLD_DEVNAME + + # Nothing to do + if [ ! -f "$1" ] + then + ClearConfig + return 0 + fi + + echo "Loading configuration from $1 ..." + INTERVAL=$(egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL= *//g') + OLD_DEVPATH=$(egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g') + OLD_DEVNAME=$(egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g') + FCTEMPS=$(egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS= *//g') + FCFANS=$(egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS= *//g') + MINTEMP=$(egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP= *//g') + MAXTEMP=$(egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP= *//g') + MINSTART=$(egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART= *//g') + MINSTOP=$(egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP= *//g') + MINPWM=$(egrep '^MINPWM=.*$' $1 | sed -e 's/MINPWM= *//g') + MAXPWM=$(egrep '^MAXPWM=.*$' $1 | sed -e 's/MAXPWM= *//g') + + # Check for configuration change + if ! ValidateDevices "$OLD_DEVPATH" "$OLD_DEVNAME" + then + echo "Configuration appears to be outdated, discarded" + ClearConfig + return 0 + fi +} + +LoadConfig $FCCONFIG + +# $1 = pwm value below which the fan is stopped +function TestMinStart() +{ + local fanok FANTEST + + echo + echo 'Now we increase the PWM value in 10-unit-steps.' + echo 'Let the fan stop completely, then press return until the' + echo "fan starts spinning. Then enter 'y'." + echo 'We will use this value +20 as the starting speed.' + let fanok=0 + let fanval="$1" + + pwmenable $pwms + until [ "$fanok" = "1" ] + do + if [ $fanval -gt 240 ] ; then let fanval=$MAX ; let fanok=1 ; fi + echo -n "Setting $pwms to $fanval..." + pwmset $pwms $fanval + read FANTEST + if [ "$FANTEST" != "" ] ; then let fanok=1 ; fi + let fanval=fanval+10 + done + pwmdisable $pwms + + let fanval=fanval+20 + if [ $fanval -gt 240 ] ; then let fanval=$MAX ; fi + echo "OK, using $fanval" +} + +# $1 = fan input to read the fan speed from +function TestMinStop() +{ + local faninput=$1 + local threshold=100000 + local fanspeed + + echo + echo 'Now we decrease the PWM value to figure out the lowest usable value.' + echo 'We will use a slightly greater value as the minimum speed.' + let fanval=$MAX + + pwmenable $pwms + while [ $fanval -ge 0 ] + do + pwmset $pwms $fanval + sleep $PDELAY + fanspeed=$(cat $faninput) + if [ $fanspeed -gt $threshold ] + then + echo " PWM $fanval -> $fanspeed RPM (probably incorrect)" + break + else + echo " PWM $fanval -> $fanspeed RPM" + if [ $fanspeed = "0" -o $fanspeed = "-1" ] + then + break + fi + let threshold=fanspeed*6/5 + fi + if [ $fanval -lt $STEP2_BELOW ] + then + let fanval=$fanval-$STEP2 + else + let fanval=$fanval-$STEP + fi + done + pwmdisable $pwms + + if [ $fanval -lt $STEP2_BELOW ] + then + let 'fanval=fanval+2*STEP2' + else + let 'fanval=fanval+STEP' + fi + echo "OK, using $fanval" +} + +# Remember the path and name of each device with at least one +# reference (pwm, temp or fan) in the configuration file. +# This function sets globals DEVPATH and DEVNAME as a side effect. +function RememberDevices() +{ + local used entry device name path tempfandev pwmdev + DEVPATH="" + DEVNAME="" + + for device in $DEVICES + do + device=$(echo "$device" | sed -e 's/\/.*$//') + + used=0 + for entry in $1 $2 + do + pwmdev=$(echo "$entry" | sed -e 's/\/.*$//') + tempfandev=$(echo "$entry" | sed -e 's/^[^=]*=//' -e 's/\/.*$//') + + if [ "$device" = "$pwmdev" -o "$device" = "$tempfandev" ] + then + used=1 + fi + done + if [ "$used" -eq 0 ] + then + continue + fi + + # Record the device path and name. This lets the fancontrol + # script check that they didn't change. If they did, then the + # configuration file can no longer be trusted. + path=$(DevicePath "$device") + if [ -z "$DEVPATH" ] + then + DEVPATH="$device=$path" + else + DEVPATH="$DEVPATH $device=$path" + fi + + name=$(DeviceName "$device") + if [ -z "$DEVNAME" ] + then + DEVNAME="$device=$name" + else + DEVNAME="$DEVNAME $device=$name" + fi + done +} + +function SaveConfig() +{ + local tmpfile + + RememberDevices "$FCTEMPS" "$FCFANS" + + echo + echo "Saving configuration to $FCCONFIG..." + tmpfile=$(mktemp -t pwmcfg.XXXXXXXXXX) || { echo "$0: Cannot create temporary file" >&2; exit 1; } + trap " [ -f \"$tmpfile\" ] && /bin/rm -f -- \"$tmpfile\"" 0 1 2 3 13 15 + echo "# Configuration file generated by pwmconfig, changes will be lost" >$tmpfile + echo "INTERVAL=$INTERVAL" >>$tmpfile + echo "DEVPATH=$DEVPATH" >>$tmpfile + echo "DEVNAME=$DEVNAME" >>$tmpfile + echo "FCTEMPS=$FCTEMPS" >>$tmpfile + echo "FCFANS=$FCFANS" >>$tmpfile + echo "MINTEMP=$MINTEMP" >>$tmpfile + echo "MAXTEMP=$MAXTEMP" >>$tmpfile + echo "MINSTART=$MINSTART" >>$tmpfile + echo "MINSTOP=$MINSTOP" >>$tmpfile + [ -n "$MINPWM" ] && echo "MINPWM=$MINPWM" >>$tmpfile + [ -n "$MAXPWM" ] && echo "MAXPWM=$MAXPWM" >>$tmpfile + mv $tmpfile $FCCONFIG + chmod +r $FCCONFIG + #check if file was written correctly + echo 'Configuration saved' +} + +INTERVAL=10 +PS3='select (1-n): ' +DEFMINTEMP=20 +DEFMAXTEMP=60 +DEFMINSTART=150 +DEFMINSTOP=100 + +function filter_cfgvar() +{ + echo "$1" | sed -e 's/ /\n/g' \ + | egrep "$2" \ + | sed -e 's/.*=//g' +} + +# "select" won't repeat the list of options, so we enclose it in a +# never-ending loop so that it starts over again with each iteration. +# I admit it's not exactly nice, but I do not have a better idea to +# keep usability at an acceptable level. +while [ 1 ] ; do +echo +echo 'Select fan output to configure, or other action:' +select pwms in $pwmactive "Change INTERVAL" "Just quit" "Save and quit" "Show configuration"; do + case $pwms in + "Change INTERVAL") + echo + echo "Current interval is $INTERVAL seconds." + echo -n "Enter the interval at which fancontrol should update PWM values (in s): " + read INTERVAL #check user input here + break ;; + "Just quit") + exit ;; + "Save and quit") + SaveConfig + exit ;; + "Show configuration") + echo + echo "Common Settings:" + echo "INTERVAL=$INTERVAL" + for pwmo in $pwmactive + do + echo + echo "Settings of ${pwmo}:" + echo " Depends on $(filter_cfgvar "$FCTEMPS" "$pwmo")" + echo " Controls $(filter_cfgvar "$FCFANS" "$pwmo")" + echo " MINTEMP=$(filter_cfgvar "$MINTEMP" $pwmo)" + echo " MAXTEMP=$(filter_cfgvar "$MAXTEMP" "$pwmo")" + echo " MINSTART=$(filter_cfgvar "$MINSTART" "$pwmo")" + echo " MINSTOP=$(filter_cfgvar "$MINSTOP" "$pwmo")" + XMINP=$(filter_cfgvar "$MINPWM" "$pwmo") + [ -n "$XMINP" ] && echo " MINPWM=$XMINP" + XMAXP=$(filter_cfgvar "$MAXPWM" "$pwmo") + [ -n "$XMAXP" ] && echo " MAXPWM=$XMAXP" + done + echo + break ;; + + "$(echo ${pwmactive} |sed -e 's/ /\n/g' | egrep "${pwms}")" ) + pwmsed=$(echo ${pwms} | sed -e 's/\//\\\\\//g') #escape / for sed + echo + + echo 'Devices:' + print_devices "" + echo + + echo 'Current temperature readings are as follows:' + for j in $TEMPS + do + S=$(cat $j) + let S="$S / 1000" + echo "$j $S" + done + FAN=$(echo $fanactive|cut -d' ' -f$REPLY) + FAN_MIN=$(echo $fanactive_min|cut -d' ' -f$REPLY) + FCFANS="$(echo $FCFANS | sed -e "s/${pwmsed}[^ ]* *//g") ${pwms}=$FAN" + echo + echo "Select a temperature sensor as source for ${pwms}:" + select tempss in $TEMPS "None (Do not affect this PWM output)"; do + if [ "$tempss" = "None (Do not affect this PWM output)" ] + then + + break; + else + if [ "$FCTEMPS" = "" ] + then + FCTEMPS="${pwms}=${tempss}" + else + FCTEMPS="$(echo $FCTEMPS | sed -e "s/${pwmsed}[^ ]* *//g") ${pwms}=${tempss}" + fi + fi + echo + echo 'Enter the low temperature (degree C)' + echo -n "below which the fan should spin at minimum speed ($DEFMINTEMP): " + read XMT + if [ "$XMT" = "" ] + then + XMT=$DEFMINTEMP + fi + if [ "$MINTEMP" = "" ] + then + MINTEMP="${pwms}=${XMT}" + else + MINTEMP="$(echo $MINTEMP | sed -e "s/${pwmsed}[^ ]* *//g") ${pwms}=${XMT}" + fi + echo + echo 'Enter the high temperature (degree C)' + echo -n "over which the fan should spin at maximum speed ($DEFMAXTEMP): " + read XMT + if [ "$XMT" = "" ] + then + XMT=$DEFMAXTEMP + fi + if [ "$MAXTEMP" = "" ] + then + MAXTEMP="${pwms}=${XMT}" + else + MAXTEMP="$(echo $MAXTEMP | sed -e "s/${pwmsed}[^ ]* *//g") ${pwms}=${XMT}" + fi + + if [ $FAN_MIN -eq 0 ] + then + echo + echo "Enter the minimum PWM value (0-$MAX)" + echo -n "at which the fan STOPS spinning (press t to test) ($DEFMINSTOP): " + read XMSTOP + + if [ "$XMSTOP" = "" ] + then + XMSTOP=$DEFMINSTOP + fi + if [ "$XMSTOP" = "t" -o "$XMSTOP" = "T" ] + then + TestMinStop $FAN + XMSTOP=$fanval + fi + else + XMSTOP=0 + fi + if [ "$MINSTOP" = "" ] + then + MINSTOP="${pwms}=${XMSTOP}" + else + MINSTOP="$(echo $MINSTOP | sed -e "s/${pwmsed}[^ ]* *//g") ${pwms}=${XMSTOP}" + fi + + if [ $FAN_MIN -eq 0 ] + then + echo + echo "Enter the minimum PWM value ($XMSTOP-$MAX)" + echo -n "at which the fan STARTS spinning (press t to test) ($DEFMINSTART): " + read XMSTART + + if [ "$XMSTART" = "" ] + then + XMSTART=$DEFMINSTART + fi + if [ "$XMSTART" = "t" -o "$XMSTART" = "T" ] + then + TestMinStart $XMSTOP + XMSTART=$fanval + fi + else + XMSTART=$DEFMINSTART + fi + if [ "$MINSTART" = "" ] + then + MINSTART="${pwms}=${XMSTART}" + else + MINSTART="$(echo $MINSTART | sed -e "s/${pwmsed}[^ ]* *//g") ${pwms}=${XMSTART}" + fi + + if [ $XMSTOP -gt 0 ] + then + echo + echo "Enter the PWM value (0-$XMSTOP) to use when the temperature" + echo -n "is below the low temperature limit (0): " + read XMINP + else + XMINP="" + fi + if [ -n "$XMINP" ] + then + if [ "$MINPWM" = "" ] + then + MINPWM="${pwms}=${XMINP}" + else + MINPWM="$(echo $MINPWM | sed -e "s/${pwmsed}[^ ]* *//g") ${pwms}=${XMINP}" + fi + fi + echo + echo "Enter the PWM value ($XMSTOP-$MAX) to use when the temperature" + echo -n "is over the high temperature limit ($MAX): " + read XMAXP + if [ -n "$XMAXP" ] + then + if [ "$MAXPWM" = "" ] + then + MAXPWM="${pwms}=${XMAXP}" + else + MAXPWM="$(echo $MAXPWM | sed -e "s/${pwmsed}[^ ]* *//g") ${pwms}=${XMAXP}" + fi + fi + echo + break; + done + break ;; + + *) + echo "No such option. Enter a number." + break ;; + esac +done +done diff --git a/prog/pwm/pwmconfig.8 b/prog/pwm/pwmconfig.8 new file mode 100644 index 0000000..c2b6d79 --- /dev/null +++ b/prog/pwm/pwmconfig.8 @@ -0,0 +1,55 @@ +.TH PWMCONFIG 8 "September 28, 2008" "lm-sensors 3" +.SH NAME +pwmconfig \- tests the PWM outputs of sensors and configures fancontrol + +.SH SYNOPSIS +.B pwmconfig + +.SH WARNING +\fBpwmconfig\fR will attempt to stop your fans, one at a time, for +approximately 5 seconds each. This may cause your processor +temperature to rise. Verify that all fans are running at normal speed +after this program has exited. +\fBpwmconfig\fR does its best to check that the fans are spinning when +they are supposed to, but due to the diversity of available +motherboards and fans, it shouldn't be blindly trusted. Always verify +by yourself. + +It is strongly recommended to run \fBpwmconfig\fR at a time when there +is no significant system load, to minimize the risk of overheating. + +.SH DESCRIPTION +.B pwmconfig +searches your sensors for pulse width modulation (PWM) +controls, and tests each one to see if it controls a fan on +your motherboard. Note that many motherboards do not have PWM +circuitry installed, even if your sensor chip supports PWM. + +When a connection is established between a PWM control and a fan, +\fBpwmconfig\fR can generate a detailed correlation, to show how a +given fan is responding to various PWM duty cycles. + +Lastly, \fBpwmconfig\fR will enter in \fBfancontrol\fR configuration +mode (unless you decide to skip that part.) In this mode, you are +invited to enter several parameters which will determine how the +\fBfancontrol\fR daemon regulates the speed of one or more fans in +your system based on temperature measurements. In particular, you will +have the opportunity to establish mappings between fans and +temperature inputs, define the temperature range over which the speed +of the fan should be adjusted dynamically, the minimum speed at which +the fan should spin, etc. See fancontrol(8) for additional +information. + +.SH BUGS +The term "PWM" is used because most fan control systems in computers +are based on pulse width modulation. Some motherboards however use DC +variation instead. So, the term "PWM" should be seen as a generic term +for "fan speed control", regardless of the actual method used. + +.SH SEE ALSO +fancontrol(8), sensors(1). + +.SH AUTHORS +.PP +Marius Reiner , +Jean Delvare diff --git a/prog/pwm/vt1211_pwm b/prog/pwm/vt1211_pwm new file mode 100755 index 0000000..9d76f34 --- /dev/null +++ b/prog/pwm/vt1211_pwm @@ -0,0 +1,179 @@ +#!/bin/bash +# +# vt1211_pwm - Manually control the PWM outputs of the VIA vt1211 Super-I/O +# +# Copyright (C) 2008 Juerg Haefliger (juergh at gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +function usage +{ + echo "Usage: vt1211_pwm -i | -r | -s ," + echo + echo "DESCRIPTION" + echo " This tool provides manual control of the PWM outputs of the VIA " + echo " vt1211 Super-I/O." + echo + echo "OPTIONS" + echo " -d Display the current PWM settings of the vt1211." + echo " -i Initialize the PWM output for manual control." + echo " -r Restore the PWM output to the original settings." + echo " -s , Set the PWM output duty-cycle. " + echo + echo "WITH" + echo " PWM output (1-2)." + echo " PWM duty-cycle (0-255)." + echo + exit 2 +} + +function set_attr +{ + local tmp + read tmp < $1 + echo "echo $tmp > $1" + echo $2 > $1 +} + +# check if we have the right permissions to run +if [ $(whoami) != "root" ] ; then + echo "You must be root to run this script." + exit 1 +fi + +# parse the command line options +action= +nr=1 +val=0 +while getopts di:r:s: opt ; do + [ -z "$action" ] || usage + case $opt in + d) action="display" + ;; + i) action="init" + nr=$OPTARG + ;; + r) action="restore" + nr=$OPTARG + ;; + s) action="set" + nr=${OPTARG%,*} + val=${OPTARG#*,} + ;; + ?) usage + ;; + esac +done + +[ -z "$action" ] && usage +[ $nr -lt 1 -o $nr -gt 2 ] && usage +[ $val -lt 0 -o $val -gt 255 ] && usage + +# check hwmon device +dev=$(ls -d /sys/devices/platform/vt1211.*) +if [ -z "$dev" ] ; then + echo "Platform device vt1211 not found. Did you load the vt1211 module?" + exit 1 +fi + +# init file +initfile="/root/.vt1211_pwm${nr}" + +# ACTION: display +if [ $action = "display" ] ; then + for nr in 1 2 ; do + read mode < ${dev}/pwm${nr}_enable + if [ $mode -eq 0 ] ; then + mode_txt="(disabled)" + elif [ $mode -eq 2 ] ; then + mode_txt="(auto) " + else + mode_txt="(unknown) " + fi + read val < ${dev}/pwm${nr} + dc=$((val * 100 / 255)) + echo "pwm${nr}: mode = ${mode} ${mode_txt}, val = ${val} (${dc}%)" + done +fi + +# ACTION: init +if [ $action = "init" ] ; then + # check for an init file + if [ -e $initfile ] ; then + echo " $initfile exists. Did you already initialize this PWM?" + exit 1 + fi + + ( + # set the pwm-to-temp mapping + # use the internal temp as a reference + set_attr ${dev}/pwm${nr}_auto_channels_temp 2 + + # enable the pwm auto controller + set_attr ${dev}/pwm${nr}_enable 2 + + # set the PWM duty-cycle + set_attr ${dev}/pwm${nr}_auto_point2_pwm 0 + set_attr ${dev}/pwm${nr}_auto_point3_pwm 255 + + # set the temp boundaries to extrem values + set_attr ${dev}/pwm1_auto_point1_temp 0 + set_attr ${dev}/pwm1_auto_point2_temp 0 + set_attr ${dev}/pwm1_auto_point3_temp 1000000 + set_attr ${dev}/pwm1_auto_point4_temp 1000000 + + ) > $initfile + + exit 0 +fi + +# ACTION: restore +if [ $action = "restore" ] ; then + # check for an init file + if [ ! -e $initfile ] ; then + echo " $initfile not found. Nothing to restore." + exit 1 + fi + + sh $initfile + rm $initfile + + exit 0 +fi + +# ACTION: set +if [ $action = "set" ] ; then + # check for an init file + if [ ! -e $initfile ] ; then + echo "$initfile not found. Did you initialize this PWM?" + exit 1 + fi + + # set the PWM duty-cycle + echo $val > ${dev}/pwm${nr}_auto_point3_pwm + + # fool the vt1211 into believing there is a temp change + # otherwise the new PWM duty-cycle doesn't take effect + echo 0 > ${dev}/pwm1_auto_point3_temp + echo 1000000 > ${dev}/pwm1_auto_point3_temp + + # read the new PWM duty-cycle back and print it + read val < ${dev}/pwm${nr} + dc=$((val * 100 / 255)) + echo "pwm${nr} is now at ${val} (${dc}%)." + + exit 0 +fi diff --git a/prog/pwm/vt1211_pwm.8 b/prog/pwm/vt1211_pwm.8 new file mode 100644 index 0000000..68fcc5d --- /dev/null +++ b/prog/pwm/vt1211_pwm.8 @@ -0,0 +1,52 @@ +.TH VT1211_PWM 8 "July 2008" "lm-sensors 3" +.SH NAME +vt1211_pwm \- manual control of VIA vt1211 PWM outputs + +.SH SYNOPSIS +.B vt1211_pwm +.B -d | -i | -r | -s , + +.SH DESCRIPTION +\fBvt1211_pwm\fP is a shell script that provides manual control of the two PWM +outputs of the VIA vt1211 Super-I/O device. + +.SH OPTIONS +.TP +.B -d +Display the current settings of the two PWM outputs. +.TP +.B -i +Initialize PWM \fB\fP for manual control. Valid numbers for \fB\fP +are 1 or 2. This option also writes the original vt1211 register values to +~/.vt1211_pwm\fB\fP which is used for restoring the original settings. +.TP +.B -r +Restore PWM \fB\fP to the original settings. Valid numbers for \fB\fP +are 1 or 2. This options reads the original settings from +~/.vt1211_pwm\fB\fP and writes them to the vt1211. +.TP +.B -s , +Set PMW \fB\fP output to \fB\fP. Valid numbers for \fB\fP are 1 +or 2 and valid numbers for \fB\fP are 0 to 255. The \fB\fP range of +0-255 maps to an output duty-cycle of 0%-100%, i.e., output duty-cycle = +\fB\fP * 100 / 255. + +.SH REQUIREMENTS +You need root privileges to execute the vt1211_pwm script and the vt1211 kernel +module needs to be loaded and you obviously need to have fans connected to the +PWM outputs of the vt1211 :-) + +.SH WARNING +This script puts the PWM controller of the vt1211 into automatic mode and +toggles the thermal thresholds between extreme values to fool the chip into +believing that there is a temperature change and thus forcing the PWM outputs +to change to the specified values. Since there is only a single PWM controller +that controls both PWM outputs, setting the duty-cycle of one PWM output could +affect the duty-cycle of the other PWM output. Use at you own risk! + +.SH SEE ALSO +sensors(1) + +.SH AUTHOR +.PP +Juerg Haefliger diff --git a/prog/rrd/Makefile b/prog/rrd/Makefile new file mode 100644 index 0000000..8755429 --- /dev/null +++ b/prog/rrd/Makefile @@ -0,0 +1,55 @@ +# +# Edit the following for your setup +# +USER=apache +# CRONTAB not used +#CRONTAB=/var/spool/cron/tabs/$(USER) +RRDPATH=/usr/bin +BINPATH=/usr/local/bin +RRDDIR=/var/lib/sensors-rrd +APACHE=/var/www/html +APACHDIR=$(APACHE)/senspix +MACH=`uname -n` +SENSDEV=hwmon0 +SENSDIR=/sys/class/hwmon/$(SENSDEV)/device +################################################ +# Everything below here should be fine +# +RRDB=$(RRDDIR)/sensors.rrd + +all: sens_day.cgi sens_week.cgi summ_week.cgi $(SENSDIR) + +%.cgi : %.in Makefile + sed -e "s#%%RRDPATH%%#$(RRDPATH)#g;s#%%APACHDIR%%#$(APACHDIR)#g;s#%%RRDDIR%%#$(RRDDIR)#g;s#%%MACH%%#$(MACH)#g" $< > $@ + +$(RRDDIR) : + install -d -o $(USER) $(RRDDIR) + +$(RRDB) : $(RRDDIR) + ./sens_create_rrd $(RRDB) + chown $(USER) $(RRDB) + +$(SENSDIR) : + $(error error - sensor $(SENSDEV) not installed - check SENSDEV definition in Makefile) + +$(CRONTAB) : + $(error error - crontab for user $(USER) not present - check CRONTAB definition in Makefile) + +$(APACHE) : + $(error error - Web server directory $(APACHE) not present - check APACHE definition in Makefile) + +$(APACHDIR)/pix : $(APACHE) + install -d -o $(USER) -m 777 $(APACHDIR)/pix + +install: all $(RRDB) $(SENSDIR) $(CRONTAB) $(APACHDIR)/pix + install -m 755 sens_update_rrd $(BINPATH) + install -m 755 sens_week.cgi $(APACHDIR) + install -m 755 sens_day.cgi $(APACHDIR) + install -m 755 summ_week.cgi $(APACHDIR) +# grep sens_update_rrd $(CRONTAB) > /dev/null 2>&1 || echo '*/5 * * * * /usr/local/bin/sens_update_rrd' $(RRDB) $(SENSDEV) >> $(CRONTAB) + @echo + @echo Note!!! You must manually install the following line in the crontab for user $(USER): + @echo ' */5 * * * * ' /usr/local/bin/sens_update_rrd $(RRDB) $(SENSDEV) + +clean: + rm -f sens_day.cgi sens_week.cgi summ_week.cgi diff --git a/prog/rrd/README b/prog/rrd/README new file mode 100644 index 0000000..89ab85c --- /dev/null +++ b/prog/rrd/README @@ -0,0 +1,101 @@ +OVERVIEW +-------- +This directory contains shell and cgi scripts which maintain a +database of sensor data and generate web pages containing +graphs of sensor data. + +The RRD (Round Robin Database) package is REQUIRED. +Get this package from + http://oss.oetiker.ch/rrdtool/ + +A web server with CGI support is required. + +We have provided these scripts because the RRD package, +while simple to build and install, is rather difficult +to configure to store and display data. + +RRD, together with lm_sensors and these scripts, provide the +following advantages: + - True round-robin (constant-size) database + - On-the-fly graph generation with CGI scripts + - Multiple data views using single database + - Automatic time stamping, interpolation of missing data, + large data dropouts (during machine downtime) correctly + shown on graphs + +If you are looking for something a little simpler, +that does not require RRD, try ../tellerstats. + +The RRD scripts read /sys entries and do not use libsensors. +Therefore the scale factors in /etc/sensors.conf are not used, +and you may have to change the scale factors in the cgi scripts. + + +WARNING! +-------- +The 'make install' script tries to make it easy for you but +makes a lot of assumptions about your cron and web setup. +If you have any concerns, do NOT run make install, and +install the items by hand instead. + + +INSTALLATION INSTRUCTIONS +------------------------- + + - Make and install lm_sensors. Get it working (run 'sensors') + before you try this! + - Get RRD, make and install it + - Edit the top of the Makefile. Do NOT skip this step. + The defaults will probably not work for you. + Here are the defaults: + Cron user + USER=httpd + Path to rrdtool and rrdcgi + RRDPATH=/usr/bin + Place to install sens_update_rrd script + BINPATH=/usr/local/bin + Place to store the database + RRDDIR=/var/lib/sensors-rrd + Place to put the cgi script and the graphs + APACHE=/usr/local/apache/htdocs + APACHDIR=$(APACHE)/senspix + The sensor device in your system + (isa recommended over i2c if both are available) + SENSDEV=hwmon0 (look in /sys/class/hwmon) + - make + - (as root) make install, which does the following. + If you don't want it to do this, install by hand!!! + Creates a database + Installs the data gathering script + Installs the CGI script in your web server + - Manually add the following line to the crontab for + the user specified above, which will call the data gathering + script every 5 minutes (adjust paths as necessary) + */5 * * * * /usr/local/bin/sens_update_rrd /var/lib/sensors-rrd/sensors.rrd hwmon0 + - Load http://localhost/senspix/sens_day.cgi in your web browser + to test + + +TROUBLESHOOTING +--------------- + RRD problems: See the RRD documentation + + Cron problems: check the cron logs, maybe your cron format + is different or you need to signal the cron daemon? + + Unused sensors: remove appropriate sections from sens_*.cgi.in + and remake and install. + + Sensor scaling factors incorrect (in3-in6): Edit lines in + sens_*.cgi.in that start + 'CDEF:' to change the scale factor. + + CGI problems: Check the apache logs. If CGI is not enabled for + the directory add a .htaccess file to the directory + including the line + Options ExecCGI + + Removing the "RRDTOOL / TOBI OETIKER" tag in RRD graphs: + Comment out the line + gator(gif, (int) im->xgif-5, 5); + in src/rrd_graph.c in the RRD package. diff --git a/prog/rrd/sens_create_rrd b/prog/rrd/sens_create_rrd new file mode 100755 index 0000000..09ef1f8 --- /dev/null +++ b/prog/rrd/sens_create_rrd @@ -0,0 +1,60 @@ +#!/bin/sh +# +# sens_create_rrd - +# Create a sensors rrd database of 14 sensor readings +# at 5 minute intervals for 1 week. +# +# Copyright 2001 Mark D. Studebaker +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +RRDPATH=/usr/bin +RRDB=$1 +#Heartbeat 15 minutes +HB=900 +#Rows 12 * 24 * 7 = 1 week of every 5 minutes +RW=2016 + +if [ $# -ne 1 ] +then + echo usage: $0 database.rrd + exit 1 +fi + +DIR=`dirname $1` +if [ ! -w $DIR ] +then + echo $0: directory $DIR not present or not writable + exit 1 +fi + +$RRDPATH/rrdtool create $RRDB --step 300 \ + DS:fan1:GAUGE:${HB}:0:12000 \ + DS:fan2:GAUGE:${HB}:0:12000 \ + DS:fan3:GAUGE:${HB}:0:12000 \ + DS:temp1:GAUGE:${HB}:-25:250 \ + DS:temp2:GAUGE:${HB}:-25:250 \ + DS:temp3:GAUGE:${HB}:-25:250 \ + DS:in0:GAUGE:${HB}:-25:25 \ + DS:in1:GAUGE:${HB}:-25:25 \ + DS:in2:GAUGE:${HB}:-25:25 \ + DS:in3:GAUGE:${HB}:-25:25 \ + DS:in4:GAUGE:${HB}:-25:25 \ + DS:in5:GAUGE:${HB}:-25:25 \ + DS:in6:GAUGE:${HB}:-25:25 \ + DS:loadavg:GAUGE:${HB}:0:U \ + RRA:AVERAGE:0.5:1:$RW + diff --git a/prog/rrd/sens_day.in b/prog/rrd/sens_day.in new file mode 100644 index 0000000..75dc13b --- /dev/null +++ b/prog/rrd/sens_day.in @@ -0,0 +1,231 @@ +#!%%RRDPATH%%/rrdcgi + + + +One Day Hardware Statistics for %%MACH%% + + +

ONE DAY VIEW

+See also:
+One Week View
+One Week Summary View + +

TEMPERATURES

+ + +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Temperature (degrees C)" + -t "Motherboard temperature" + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 1:5 + DEF:temp=%%RRDDIR%%/sensors.rrd:temp1:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Temperature (degrees C)" + -t "CPU 1 temperature" + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 1:5 + DEF:temp=%%RRDDIR%%/sensors.rrd:temp2:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Temperature (degrees C)" + -t "CPU 2 temperature" + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 1:5 + DEF:temp=%%RRDDIR%%/sensors.rrd:temp3:AVERAGE + LINE2:temp#FF00FF> +

+ +

FANS

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Fan speed (RPM)" + -t "Fan 1 speed" + -u 5000 + --units-exponent 0 + --alt-autoscale + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + DEF:temp=%%RRDDIR%%/sensors.rrd:fan1:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Fan speed (RPM)" + -t "Fan 2 speed" + -u 5000 + --units-exponent 0 + --alt-autoscale + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + DEF:temp=%%RRDDIR%%/sensors.rrd:fan2:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Fan speed (RPM)" + -t "Fan 3 speed" + -u 5000 + --units-exponent 0 + --alt-autoscale + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + DEF:temp=%%RRDDIR%%/sensors.rrd:fan3:AVERAGE + LINE2:temp#FF00FF> +

+ +

POWER SUPPLIES

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Volts" + -t "Core 1 Voltage" + -l 1 -u 3 --rigid + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 0.2:1 + DEF:temp=%%RRDDIR%%/sensors.rrd:in0:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Volts" + -t "Core 2 Voltage" + -l 1 -u 3 --rigid + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 0.2:1 + DEF:temp=%%RRDDIR%%/sensors.rrd:in1:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Volts" + -t "+3.3 Volt Supply" + -l 2 -u 4 --rigid + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 0.2:1 + DEF:temp=%%RRDDIR%%/sensors.rrd:in2:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Volts" + -t "+5 Volt Supply" + -l 4 -u 6 --rigid + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 0.2:1 + DEF:x=%%RRDDIR%%/sensors.rrd:in3:AVERAGE + CDEF:temp=1.68,x,* + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Volts" + -t "+12 Volt Supply" + -l 10 -u 14 + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 0.5:1 + DEF:x=%%RRDDIR%%/sensors.rrd:in4:AVERAGE + CDEF:temp=3.8,x,* + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Volts" + -t "-12 Volt Supply" + -l -14 -u -10 + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 0.5:1 + DEF:x=%%RRDDIR%%/sensors.rrd:in5:AVERAGE + CDEF:temp=-3.48,x,* + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1days + -v "Volts" + -t "-5 Volt Supply" + -l -6 -u -4 --rigid + -x HOUR:1:HOUR:3:HOUR:3:0:'%b %d %H:00' + -y 0.2:1 + DEF:x=%%RRDDIR%%/sensors.rrd:in6:AVERAGE + CDEF:temp=-1.5,x,* + LINE2:temp#FF00FF> +

+ +This page generated with data and scripts from +the lm_sensors project; +the data are stored in a Round Robin Database and +the graphs are generated by + +RRD. + + + + + + + diff --git a/prog/rrd/sens_update_rrd b/prog/rrd/sens_update_rrd new file mode 100755 index 0000000..6be365b --- /dev/null +++ b/prog/rrd/sens_update_rrd @@ -0,0 +1,102 @@ +#!/bin/sh +# +# sens_update_rrd - +# Update a sensors rrd database. +# Sample usage: +# sens_update_rrd /var/lib/database.rrd hwmon0 +# Sample cron entry: +# */5 * * * * /usr/local/bin/sens_update_rrd /var/lib/sensors-rrd/sensors.rrd hwmon0 +# +################################################################# +# +# Copyright 2001,2005 Mark D. Studebaker +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +################################################################# +# +if [ $# -lt 1 -o $# -gt 2 ] +then + echo "usage: $0 database.rrd [hwmonN]" + exit 1 +elif [ $# -eq 2 ] +then + HWMON=$2 +else + HWMON=hwmon0 +fi +# +RRDPATH=/usr/bin +RRDB=$1 + +SENSDIR=/sys/class/hwmon +SENS=$SENSDIR/$HWMON/device + +if [ ! -d $SENS ] +then + echo "No sensors found in: $SENS" + echo "(modprobe sensor modules?)" + exit 1 +fi + +STRING=N +# +# Get the value from these sensor files (/sys) +# +SENSORS="fan1 fan2 fan3" +for i in $SENSORS +do + V="`cat $SENS/${i}_input 2> /dev/null`" + if [ $? -ne 0 ] + then + STRING="${STRING}:U" + else + STRING="${STRING}:${V}" + fi +done +# +# Get the value from these sensor files (/sys) and divide by 1000 +# +SENSORS="temp1 temp2 temp3 in0 in1 in2 in3 in4 in5 in6" +for i in $SENSORS +do + V="`cat $SENS/${i}_input 2> /dev/null`" + if [ $? -ne 0 ] + then + STRING="${STRING}:U" + else + V=`echo "3k0 ${V/-/_} 1000/p"|dc` + STRING="${STRING}:${V}" + fi +done + +# +# Get the first value from these /proc files +# +SENSORS="loadavg" +for i in $SENSORS +do + V="`cat /proc/$i 2> /dev/null`" + if [ $? -ne 0 ] + then + STRING="${STRING}:U" + else + V="`echo $V | cut -d ' ' -f 1`" + STRING="${STRING}:${V}" + fi +done + +$RRDPATH/rrdtool update $RRDB $STRING diff --git a/prog/rrd/sens_week.in b/prog/rrd/sens_week.in new file mode 100644 index 0000000..cce5055 --- /dev/null +++ b/prog/rrd/sens_week.in @@ -0,0 +1,231 @@ +#!%%RRDPATH%%/rrdcgi + + + +One Week Hardware Statistics for %%MACH%% + + +

ONE WEEK VIEW

+See also:
+One Day View
+One Week Summary View + +

TEMPERATURES

+ + +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Temperature (degrees C)" + -t "Motherboard temperature" + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 1:5 + DEF:temp=%%RRDDIR%%/sensors.rrd:temp1:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Temperature (degrees C)" + -t "CPU 1 temperature" + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 1:5 + DEF:temp=%%RRDDIR%%/sensors.rrd:temp2:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Temperature (degrees C)" + -t "CPU 2 temperature" + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 1:5 + DEF:temp=%%RRDDIR%%/sensors.rrd:temp3:AVERAGE + LINE2:temp#FF00FF> +

+ +

FANS

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Fan speed (RPM)" + -t "Fan 1 speed" + -u 5000 + --units-exponent 0 + --alt-autoscale + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + DEF:temp=%%RRDDIR%%/sensors.rrd:fan1:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Fan speed (RPM)" + -t "Fan 2 speed" + -u 5000 + --units-exponent 0 + --alt-autoscale + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + DEF:temp=%%RRDDIR%%/sensors.rrd:fan2:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Fan speed (RPM)" + -t "Fan 3 speed" + -u 5000 + --units-exponent 0 + --alt-autoscale + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + DEF:temp=%%RRDDIR%%/sensors.rrd:fan3:AVERAGE + LINE2:temp#FF00FF> +

+ +

POWER SUPPLIES

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Volts" + -t "Core 1 Voltage" + -l 1 -u 3 --rigid + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 0.2:1 + DEF:temp=%%RRDDIR%%/sensors.rrd:in0:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Volts" + -t "Core 2 Voltage" + -l 1 -u 3 --rigid + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 0.2:1 + DEF:temp=%%RRDDIR%%/sensors.rrd:in1:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Volts" + -t "+3.3 Volt Supply" + -l 2 -u 4 --rigid + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 0.2:1 + DEF:temp=%%RRDDIR%%/sensors.rrd:in2:AVERAGE + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Volts" + -t "+5 Volt Supply" + -l 4 -u 6 --rigid + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 0.2:1 + DEF:x=%%RRDDIR%%/sensors.rrd:in3:AVERAGE + CDEF:temp=1.68,x,* + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Volts" + -t "+12 Volt Supply" + -l 10 -u 14 + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 1:1 + DEF:x=%%RRDDIR%%/sensors.rrd:in4:AVERAGE + CDEF:temp=3.8,x,* + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Volts" + -t "-12 Volt Supply" + -l -14 -u -10 + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 1:1 + DEF:x=%%RRDDIR%%/sensors.rrd:in5:AVERAGE + CDEF:temp=-3.48,x,* + LINE2:temp#FF00FF> +

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Volts" + -t "-5 Volt Supply" + -l -6 -u -4 --rigid + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 0.2:1 + DEF:x=%%RRDDIR%%/sensors.rrd:in6:AVERAGE + CDEF:temp=-1.5,x,* + LINE2:temp#FF00FF> +

+ +This page generated with data and scripts from +the lm_sensors project; +the data are stored in a Round Robin Database and +the graphs are generated by + +RRD. + + + + + + + diff --git a/prog/rrd/summ_week.in b/prog/rrd/summ_week.in new file mode 100644 index 0000000..713197d --- /dev/null +++ b/prog/rrd/summ_week.in @@ -0,0 +1,103 @@ +#!%%RRDPATH%%/rrdcgi + + + +One Week Summary Hardware Statistics for %%MACH%% + + +

ONE WEEK SUMMARY VIEW

+See also:
+One Day View
+One Week View
+ +

TEMPERATURES

+ + +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Temperature (degrees C); Load Avg * 10" + -t "Temperatures and Load Average" + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 5:10 + DEF:temp=%%RRDDIR%%/sensors.rrd:temp1:AVERAGE + DEF:ttemp=%%RRDDIR%%/sensors.rrd:temp2:AVERAGE + DEF:la=%%RRDDIR%%/sensors.rrd:loadavg:AVERAGE + CDEF:lla=10,la,* + LINE2:ttemp#FF0000:"CPU Temp" + LINE2:temp#FF00FF:"Motherboard Temp" + LINE2:lla#00FFFF:"Load Average * 10"> +

+ + +

FANS

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Fan speed (RPM)" + -t "Fan speeds" + -u 5000 + --units-exponent 0 + --alt-autoscale + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + DEF:f1=%%RRDDIR%%/sensors.rrd:fan1:AVERAGE + DEF:f2=%%RRDDIR%%/sensors.rrd:fan2:AVERAGE + DEF:f3=%%RRDDIR%%/sensors.rrd:fan3:AVERAGE + LINE2:f1#FF00FF:"Fan 1" + LINE2:f2#FF0000:"Fan 2" + LINE2:f3#00FFFF:"Fan 3"> +

+ +

POWER SUPPLIES

+ +

' + -a PNG + -h 200 -w 800 + --lazy + -s -1week + -v "Volts" + -t "All Power Supplies" + -l -15 -u 15 --rigid + -x HOUR:6:DAY:1:DAY:1:86400:'%a %b %d' + -y 1:5 + DEF:i0=%%RRDDIR%%/sensors.rrd:in0:AVERAGE + DEF:i1=%%RRDDIR%%/sensors.rrd:in1:AVERAGE + DEF:i2=%%RRDDIR%%/sensors.rrd:in2:AVERAGE + DEF:i3=%%RRDDIR%%/sensors.rrd:in3:AVERAGE + DEF:i4=%%RRDDIR%%/sensors.rrd:in4:AVERAGE + DEF:i5=%%RRDDIR%%/sensors.rrd:in5:AVERAGE + DEF:i6=%%RRDDIR%%/sensors.rrd:in6:AVERAGE + CDEF:ii3=1.68,i3,* + CDEF:ii4=3.8,i4,* + CDEF:ii5=-3.48,i5,* + CDEF:ii6=-1.5,i6,* + LINE2:ii4#00FF00:"+12V" + LINE2:ii3#FF0000:"+5V" + LINE2:i2#FF8000:"+3.3V" + LINE2:i0#FF00FF:"Core 1" + LINE2:i1#00FFFF:"Core 2" + LINE2:ii6#FF0080:"-5V" + LINE2:ii5#0000FF:"-12V"> +

+ +This page generated with data and scripts from +the lm_sensors project; +the data are stored in a Round Robin Database and +the graphs are generated by + +RRD. + + + + + + + diff --git a/prog/sensord/Module.mk b/prog/sensord/Module.mk new file mode 100644 index 0000000..9dcf9d2 --- /dev/null +++ b/prog/sensord/Module.mk @@ -0,0 +1,63 @@ +# Module.mk - Makefile for a Linux module for reading sensor data. +# Copyright (c) 1998, 1999 Frodo Looijaard +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. + +# The round robin database (RRD) development headers and libraries are +# REQUIRED. Get this package from: +# http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/ + +# Note that MODULE_DIR (the directory in which this file resides) is a +# 'simply expanded variable'. That means that its value is substituted +# verbatim in the rules, until it is redefined. +MODULE_DIR := prog/sensord +PROGSENSORDDIR := $(MODULE_DIR) + +PROGSENSORDMAN8DIR := $(MANDIR)/man8 +PROGSENSORDMAN8FILES := $(MODULE_DIR)/sensord.8 + +# Regrettably, even 'simply expanded variables' will not put their currently +# defined value verbatim into the command-list of rules... +PROGSENSORDTARGETS := $(MODULE_DIR)/sensord +PROGSENSORDSOURCES := $(MODULE_DIR)/args.c $(MODULE_DIR)/chips.c $(MODULE_DIR)/lib.c $(MODULE_DIR)/rrd.c $(MODULE_DIR)/sense.c $(MODULE_DIR)/sensord.c + +# Include all dependency files. We use '.rd' to indicate this will create +# executables. +INCLUDEFILES += $(PROGSENSORDSOURCES:.c=.rd) + +REMOVESENSORDBIN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(SBINDIR)/%,$(PROGSENSORDTARGETS)) +REMOVESENSORDMAN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(PROGSENSORDMAN8DIR)/%,$(PROGSENSORDMAN8FILES)) + +$(PROGSENSORDTARGETS): $(PROGSENSORDSOURCES:.c=.ro) lib/$(LIBSHBASENAME) + $(CC) $(EXLDFLAGS) -o $@ $(PROGSENSORDSOURCES:.c=.ro) -Llib -lsensors -lrrd + +all-prog-sensord: $(PROGSENSORDTARGETS) +user :: all-prog-sensord + +install-prog-sensord: all-prog-sensord + $(MKDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(PROGSENSORDMAN8DIR) + $(INSTALL) -m 755 $(PROGSENSORDTARGETS) $(DESTDIR)$(SBINDIR) + $(INSTALL) -m 644 $(PROGSENSORDMAN8FILES) $(DESTDIR)$(PROGSENSORDMAN8DIR) +user_install :: install-prog-sensord + +user_uninstall:: + $(RM) $(REMOVESENSORDBIN) + $(RM) $(REMOVESENSORDMAN) + +clean-prog-sensord: + $(RM) $(PROGSENSORDDIR)/*.rd $(PROGSENSORDDIR)/*.ro + $(RM) $(PROGSENSORDTARGETS) +clean :: clean-prog-sensord diff --git a/prog/sensord/README b/prog/sensord/README new file mode 100644 index 0000000..9965800 --- /dev/null +++ b/prog/sensord/README @@ -0,0 +1,9 @@ +Daemon that periodically logs sensor readings to syslog or a round-robin +database, and warns of sensor alarms. + +Compile this program by making lm_sensors with the following argument: + make PROG_EXTRA:=sensord + +The RRD (Round Robin Database) development headers and libraries are +REQUIRED. Get this package from: + http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/ diff --git a/prog/sensord/args.c b/prog/sensord/args.c new file mode 100644 index 0000000..929ab0a --- /dev/null +++ b/prog/sensord/args.c @@ -0,0 +1,274 @@ +/* + * sensord + * + * A daemon that periodically logs sensor information to syslog. + * + * Copyright (c) 1999-2002 Merlin Hughes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#include "args.h" +#include "sensord.h" +#include "lib/error.h" +#include "version.h" + +struct sensord_arguments sensord_args = { + .pidFile = "/var/run/sensord.pid", + .scanTime = 60, + .logTime = 30 * 60, + .rrdTime = 5 * 60, + .syslogFacility = LOG_DAEMON, +}; + +static int parseTime(char *arg) +{ + char *end; + int value = strtoul(arg, &end, 10); + if ((end > arg) && (*end == 's')) { + ++ end; + } else if ((end > arg) && (*end == 'm')) { + value *= 60; + ++ end; + } else if ((end > arg) && (*end == 'h')) { + value *= 60 * 60; + ++ end; + } + if ((end == arg) || *end) { + fprintf(stderr, "Error parsing time value `%s'.\n", arg); + return -1; + } + return value; +} + +static struct { + const char *name; + int id; +} facilities[] = { + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + { "daemon", LOG_DAEMON }, + { "user", LOG_USER }, + { NULL, 0 } +}; + +static int parseFacility(char *arg) +{ + int i = 0; + while (facilities[i].name && strcasecmp(arg, facilities[i].name)) + ++ i; + if (!facilities[i].name) { + fprintf(stderr, "Error parsing facility value `%s'.\n", arg); + return -1; + } + return facilities[i].id; +} + +static const char *daemonSyntax = + " -i, --interval