root/lm-sensors/trunk/prog/detect/sensors-detect @ 4196

Revision 4196, 167.0 KB (checked in by khali, 7 years ago)

libsensors: Add support for the pc87247 driver (fans only).
sensord: Add pc87247 support (fans only).
sensors: Add pc87247 support (fans only).
sensors-detect: Advertise the upcoming pc87427 driver.
Thanks to Amir Habibi at Candelis for setting up a test system.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/perl -w
2
3#
4#    sensors-detect - Detect PCI bus and chips
5#    Copyright (C) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>
6#    Copyright (C) 2000 - 2004  The lm_sensors team
7#    Copyright (C) 2005 - 2006  Jean Delvare <khali@linux-fr.org>
8#
9#    This program is free software; you can redistribute it and/or modify
10#    it under the terms of the GNU General Public License as published by
11#    the Free Software Foundation; either version 2 of the License, or
12#    (at your option) any later version.
13#
14#    This program is distributed in the hope that it will be useful,
15#    but WITHOUT ANY WARRANTY; without even the implied warranty of
16#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17#    GNU General Public License for more details.
18#
19#    You should have received a copy of the GNU General Public License
20#    along with this program; if not, write to the Free Software
21#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22#
23
24# TODO: Better handling of chips with several addresses
25
26# A Perl wizard really ought to look upon this; the PCI and I2C stuff should
27# each be put in a separate file, using modules and packages. That is beyond
28# me.
29
30require 5.004;
31
32use strict;
33use Fcntl;
34use POSIX;
35use File::Basename;
36
37# Just in case a root user doesn't have /sbin in his/her path for some reason
38# (was seen once)
39$ENV{PATH} = '/sbin:'.$ENV{PATH}
40        unless $ENV{PATH} =~ m,(^|:)/sbin/?(:|$),;
41# Same for /usr/local/sbin since we need i2cdetect which is installed there
42# by default (reported by Lennard Klein)
43$ENV{PATH} = '/usr/local/sbin:'.$ENV{PATH}
44        unless $ENV{PATH} =~ m,(^|:)/usr/local/sbin/?(:|$),;
45
46#########################
47# CONSTANT DECLARATIONS #
48#########################
49
50use vars qw(@pci_adapters @chip_ids @superio_ids $revision);
51
52$revision = '$Revision$ ($Date$)';
53$revision =~ s/\$\w+: (.*?) \$/$1/g;
54$revision =~ s/ \([^()]*\)//;
55
56# This is the list of SMBus or I2C adapters we recognize by their PCI
57# signature. This is an easy and fast way to determine which SMBus or I2C
58# adapters should be present.
59# Each entry must have a vendid (Vendor ID), devid (Device ID) and
60# procid (string as appears in /proc/pci; see linux/driver/pci,
61# either pci.c or oldproc.c). If no driver is written yet, set the
62# driver (Driver Name) field to "to-be-written".
63# The match (Match Description) field should contain a regular expression
64# matching the adapter name as it would appear in /proc/bus/i2c or /sys.
65@pci_adapters = ( 
66     { 
67       vendid => 0x8086,
68       devid  => 0x7113,
69       procid => "Intel 82371AB PIIX4 ACPI",
70       driver => "i2c-piix4",
71       match => qr/^SMBus PIIX4 adapter at /,
72     } , 
73     { 
74       vendid => 0x8086,
75       devid  => 0x719b,
76       procid => "Intel 82443MX Mobile",
77       driver => "i2c-piix4",
78       match => qr/^SMBus PIIX4 adapter at /,
79     } , 
80     { 
81       vendid => 0x8086,
82       devid  => 0x2413,
83       procid => "Intel 82801AA ICH",
84       driver => "i2c-i801",
85       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
86     } , 
87     { 
88       vendid => 0x8086,
89       devid  => 0x2423,
90       procid => "Intel 82801AB ICH0",
91       driver => "i2c-i801",
92       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
93     } , 
94     { 
95       vendid => 0x8086,
96       devid  => 0x2443,
97       procid => "Intel 82801BA ICH2",
98       driver => "i2c-i801",
99       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
100     } , 
101     { 
102       vendid => 0x8086,
103       devid  => 0x2483,
104       procid => "Intel 82801CA/CAM ICH3",
105       driver => "i2c-i801",
106       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
107     } , 
108     { 
109       vendid => 0x8086,
110       devid  => 0x24C3,
111       procid => "Intel 82801DB ICH4",
112       driver => "i2c-i801",
113       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
114     } , 
115     { 
116       vendid => 0x8086,
117       devid  => 0x24D3,
118       procid => "Intel 82801EB ICH5",
119       driver => "i2c-i801",
120       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
121     } , 
122     { 
123       vendid => 0x8086,
124       devid  => 0x25A4,
125       procid => "Intel 6300ESB",
126       driver => "i2c-i801",
127       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
128     } , 
129     { 
130       vendid => 0x8086,
131       devid  => 0x269B,
132       procid => "Intel Enterprise Southbridge - ESB2",
133       driver => "i2c-i801",
134       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
135     },
136     {
137       vendid => 0x8086,
138       devid  => 0x266A,
139       procid => "Intel 82801FB ICH6",
140       driver => "i2c-i801",
141       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
142     } , 
143     { 
144       vendid => 0x8086,
145       devid  => 0x27DA,
146       procid => "Intel ICH7",
147       driver => "i2c-i801",
148       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
149     } , 
150     { 
151       vendid => 0x8086,
152       devid  => 0x283E,
153       procid => "Intel ICH8",
154       driver => "i2c-i801",
155       match => qr/^SMBus I801 adapter at [0-9a-f]{4}/,
156     }, 
157     { 
158       vendid => 0x1106,
159       devid  => 0x3040,
160       procid => "VIA Technologies VT82C586B Apollo ACPI",
161       driver => "i2c-via",
162       match => qr/^VIA i2c/,
163     } ,
164     { 
165       vendid => 0x1106,
166       devid  => 0x3050,
167       procid => "VIA Technologies VT82C596 Apollo ACPI",
168       driver => "i2c-viapro",
169       match => qr/^SMBus V(IA|ia) Pro adapter at/,
170     } ,
171     { 
172       vendid => 0x1106,
173       devid  => 0x3051,
174       procid => "VIA Technologies VT82C596B ACPI",
175       driver => "i2c-viapro",
176       match => qr/^SMBus V(IA|ia) Pro adapter at/,
177     } ,
178     { 
179       vendid => 0x1106,
180       devid  => 0x3057,
181       procid => "VIA Technologies VT82C686 Apollo ACPI",
182       driver => "i2c-viapro",
183       match => qr/^SMBus V(IA|ia) Pro adapter at/,
184     } ,
185     { 
186       vendid => 0x1106,
187       devid  => 0x3074,
188       procid => "VIA Technologies VT8233 VLink South Bridge",
189       driver => "i2c-viapro",
190       match => qr/^SMBus V(IA|ia) Pro adapter at/,
191     } ,
192     { 
193       vendid => 0x1106,
194       devid  => 0x3147,
195       procid => "VIA Technologies VT8233A South Bridge",
196       driver => "i2c-viapro",
197       match => qr/^SMBus V(IA|ia) Pro adapter at/,
198     } ,
199     { 
200       vendid => 0x1106,
201       devid  => 0x3177,
202       procid => "VIA Technologies VT8233A/8235 South Bridge",
203       driver => "i2c-viapro",
204       match => qr/^SMBus V(IA|ia) Pro adapter at/,
205     } ,
206     {
207       vendid => 0x1106,
208       devid  => 0x3227,
209       procid => "VIA Technologies VT8237 South Bridge",
210       driver => "i2c-viapro",
211       match => qr/^SMBus V(IA|ia) Pro adapter at/,
212     } ,
213     {
214       vendid => 0x1106,
215       devid  => 0x3337,
216       procid => "VIA Technologies VT8237A South Bridge",
217       driver => "i2c-viapro",
218       match => qr/^SMBus V(IA|ia) Pro adapter at/,
219     } ,
220     { 
221       vendid => 0x1106,
222       devid  => 0x8235,
223       procid => "VIA Technologies VT8231 South Bridge",
224       driver => "i2c-viapro",
225       match => qr/^SMBus V(IA|ia) Pro adapter at/,
226     } ,
227     { 
228       vendid => 0x1106,
229       devid  => 0x3287,
230       procid => "VIA Technologies VT8251 South Bridge",
231       driver => "i2c-viapro",
232       match => qr/^SMBus V(IA|ia) Pro adapter at/,
233     } ,
234     {
235       vendid => 0x1039,
236       devid  => 0x5597,
237       procid => "Silicon Integrated Systems SIS5581/5582/5597/5598 (To be written - Do not use 5595 drivers)",
238       driver => "to-be-written",
239     } ,
240     {
241       vendid => 0x1039,
242       devid  => 0x5598,
243       procid => "Silicon Integrated Systems SIS5598 (To be written - Do not use 5595 drivers)",
244       driver => "to-be-written",
245     } ,
246     {
247       vendid => 0x1039,
248       devid  => 0x0540,
249       procid => "Silicon Integrated Systems SIS540 (To be written - Do not use 5595 drivers)",
250       driver => "to-be-written",
251     } ,
252     {
253       vendid => 0x1039,
254       devid  => 0x0630,
255       procid => "Silicon Integrated Systems SIS630",
256       driver => "i2c-sis630",
257       match => qr/^SMBus SIS630 adapter at [0-9a-f]{4}/,
258     } ,
259     {
260       vendid => 0x1039,
261       devid  => 0x0730,
262       procid => "Silicon Integrated Systems SIS730",
263       driver => "i2c-sis630",
264       match => qr/^SMBus SIS630 adapter at [0-9a-f]{4}/,
265     } ,
266#
267# Both Ali chips below have same PCI ID. Can't be helped. Only one should load.
268#
269     {
270       vendid => 0x10b9,
271       devid => 0x7101,
272       procid => "Acer Labs 1533/1543",
273       driver => "i2c-ali15x3",
274       match => qr/^SMBus ALI15X3 adapter at/,
275     },
276     {
277       vendid => 0x10b9,
278       devid => 0x7101,
279       procid => "Acer Labs 1535",
280       driver => "i2c-ali1535",
281       match => qr/^SMBus ALI1535 adapter at/,
282     },
283     {
284       vendid => 0x10b9,
285       devid => 0x1563,
286       procid => "Acer Labs 1563",
287       driver => "i2c-ali1563",
288       match => qr/^SMBus ALi 1563 Adapter @/,
289     },
290     { 
291       vendid => 0x106b,
292       devid  => 0x000e,
293       procid => "Apple Computer Inc. Hydra Mac I/O",
294       driver => "i2c-hydra",
295       match => qr/^Hydra i2c/,
296     },
297     { 
298       vendid => 0x1022,
299       devid  => 0x740b,
300       procid => "AMD-756 Athlon ACPI",
301       driver => "i2c-amd756",
302       match => qr/^SMBus AMD756 adapter at [0-9a-f]{4}/,
303     },
304     { 
305       vendid => 0x1022,
306       devid  => 0x7413,
307       procid => "AMD-766 Athlon ACPI",
308       driver => "i2c-amd756",
309       match => qr/^SMBus AMD766 adapter at [0-9a-f]{4}/,
310     },
311     { 
312       vendid => 0x1022,
313       devid  => 0x7443,
314       procid => "AMD-768 System Management",
315       driver => "i2c-amd756",
316       match => qr/^SMBus AMD768 adapter at [0-9a-f]{4}/,
317     },
318     { 
319       vendid => 0x1022,
320       devid  => 0x746b,
321       procid => "AMD-8111 ACPI",
322       driver => "i2c-amd756",
323       match => qr/^SMBus AMD8111 adapter at [0-9a-f]{4}/,
324     },
325     { 
326       vendid => 0x1022,
327       devid  => 0x746a,
328       procid => "AMD-8111 SMBus 2.0",
329       driver => "i2c-amd8111",
330       match => qr/^SMBus2 AMD8111 adapter at [0-9a-f]{4}/,
331     },
332     {
333       vendid => 0x102b,
334       devid  => 0x0519,
335       procid => "MGA 2064W [Millennium]",
336       driver => "i2c-matroxfb",
337       match  => qr/^DDC:fb[0-9]{1,2}/,
338     },
339     {
340       vendid => 0x102b,
341       devid  => 0x051a,
342       procid => "MGA 1064SG [Mystique]",
343       driver => "i2c-matroxfb",
344       match  => qr/^DDC:fb[0-9]{1,2}/,
345     },
346     {
347       vendid => 0x102b,
348       devid  => 0x051b,
349       procid => "MGA 2164W [Millennium II]",
350       driver => "i2c-matroxfb",
351       match  => qr/^DDC:fb[0-9]{1,2}/,
352     },
353     {
354       vendid => 0x102b,
355       devid  => 0x051e,
356       procid => "MGA 1064SG [Mystique] AGP",
357       driver => "i2c-matroxfb",
358       match  => qr/^DDC:fb[0-9]{1,2}/,
359     },
360     {
361       vendid => 0x102b,
362       devid  => 0x051f,
363       procid => "MGA 2164W [Millennium II] AGP",
364       driver => "i2c-matroxfb",
365       match  => qr/^DDC:fb[0-9]{1,2}/,
366     },
367     {
368       vendid => 0x102b,
369       devid  => 0x1000,
370       procid => "MGA G100 [Productiva]",
371       driver => "i2c-matroxfb",
372       match  => qr/^DDC:fb[0-9]{1,2}/,
373     },
374     {
375       vendid => 0x102b,
376       devid  => 0x1001,
377       procid => "MGA G100 [Productiva] AGP",
378       driver => "i2c-matroxfb",
379       match  => qr/^DDC:fb[0-9]{1,2}/,
380     },
381     {
382       vendid => 0x102b,
383       devid  => 0x0520,
384       procid => "MGA G200",
385       driver => "i2c-matroxfb",
386       match  => qr/^DDC:fb[0-9]{1,2}/,
387     },
388     {
389       vendid => 0x102b,
390       devid  => 0x0521,
391       procid => "MGA G200 AGP",
392       driver => "i2c-matroxfb",
393       match  => qr/^DDC:fb[0-9]{1,2}/,
394     },
395     {
396       vendid => 0x102b,
397       devid  => 0x0525,
398       procid => "MGA G400 AGP",
399       driver => "i2c-matroxfb",
400       match  => qr/^(DDC,MAVEN):fb[0-9]{1,2}/,
401     },
402     {
403       vendid => 0x121a,
404       devid  => 0x0005,
405       procid => "3Dfx Voodoo3",
406       driver => "i2c-voodoo3",
407       match  => qr/^(I2C|DDC) Voodoo3\/Banshee adapter/,
408     },
409     {
410       vendid => 0x121a,
411       devid  => 0x0003,
412       procid => "3Dfx Voodoo Banshee",
413       driver => "i2c-voodoo3",
414       match  => qr/^(I2C|DDC) Voodoo3\/Banshee adapter/,
415     },
416     { 
417       vendid => 0x8086,
418       devid  => 0x7121,
419       procid => "Intel 82810 GMCH",
420       driver => "i2c-i810",
421       match => qr/^I810/,
422     } , 
423     { 
424       vendid => 0x8086,
425       devid  => 0x7123,
426       procid => "Intel 82810-DC100 GMCH",
427       driver => "i2c-i810",
428       match => qr/^I810/ ,
429     } , 
430     { 
431       vendid => 0x8086,
432       devid  => 0x7125,
433       procid => "Intel 82810E GMCH",
434       driver => "i2c-i810",
435       match => qr/^I810/,
436     } , 
437     { 
438       vendid => 0x8086,
439       devid  => 0x1132,
440       procid => "Intel 82815 GMCH",
441       driver => "i2c-i810",
442       match => qr/^I810/,
443     } , 
444     {
445       vendid => 0x8086,
446       devid  => 0x2562,
447       procid => "Intel 82845G GMCH",
448       driver => "i2c-i810",
449       match => qr/^I810/,
450     },
451     {
452       vendid => 0x10de,
453       devid  => 0x01b4,
454       procid => "nVidia nForce SMBus",
455       driver => "i2c-amd756",
456       match => qr/^SMBus nVidia nForce adapter at [0-9a-f]{4}/,
457     } , 
458     { 
459       vendid => 0x10de,
460       devid  => 0x0064,
461       procid => "nVidia Corporation nForce2 SMBus (MCP)",
462       driver => "i2c-nforce2",
463       match => qr/^SMBus nForce2 adapter at /,
464     }, 
465     {
466       vendid => 0x10de,
467       devid  => 0x0084,
468       procid => "nVidia Corporation nForce2 Ultra 400 SMBus (MCP)",
469       driver => "i2c-nforce2",
470       match => qr/^SMBus nForce2 adapter at /,
471     }, 
472     {
473       vendid => 0x10de,
474       devid  => 0x00D4,
475       procid => "nVidia Corporation nForce3 Pro150 SMBus (MCP)",
476       driver => "i2c-nforce2",
477       match => qr/^SMBus nForce2 adapter at /,
478     }, 
479     {
480       vendid => 0x10de,
481       devid  => 0x00E4,
482       procid => "nVidia Corporation nForce3 250Gb SMBus (MCP)",
483       driver => "i2c-nforce2",
484       match => qr/^SMBus nForce2 adapter at /,
485     }, 
486     {
487       vendid => 0x10de,
488       devid  => 0x0052,
489       procid => "nVidia Corporation nForce4 SMBus (MCP)",
490       driver => "i2c-nforce2",
491       match => qr/^SMBus nForce2 adapter at /,
492     }, 
493     {
494       vendid => 0x10de,
495       devid => 0x0034,
496       procid => "nVidia Corporation nForce4 SMBus (MCP-04)",
497       driver => "i2c-nforce2",
498       match => qr/^SMBus nForce2 adapter at /,
499     },
500     {
501       vendid => 0x10de,
502       devid => 0x0264,
503       procid => "nVidia Corporation nForce4 SMBus (MCP51)",
504       driver => "i2c-nforce2",
505       match => qr/^SMBus nForce2 adapter at /,
506     },
507     {
508       vendid => 0x10de,
509       devid => 0x0368,
510       procid => "nVidia Corporation nForce4 SMBus (MCP55)",
511       driver => "i2c-nforce2",
512       match => qr/^SMBus nForce2 adapter at /,
513     },
514     {
515       vendid => 0x1166,
516       devid  => 0x0200,
517       procid => "ServerWorks OSB4 South Bridge",
518       driver => "i2c-piix4",
519       match => qr/^SMBus PIIX4 adapter at /,
520     } , 
521     { 
522       vendid => 0x1055,
523       devid  => 0x9463,
524       procid => "SMSC Victory66 South Bridge",
525       driver => "i2c-piix4",
526       match => qr/^SMBus PIIX4 adapter at /,
527     } , 
528     { 
529       vendid => 0x1166,
530       devid  => 0x0201,
531       procid => "ServerWorks CSB5 South Bridge",
532       driver => "i2c-piix4",
533       match => qr/^SMBus PIIX4 adapter at /,
534     } , 
535     { 
536       vendid => 0x1166,
537       devid  => 0x0203,
538       procid => "ServerWorks CSB6 South Bridge",
539       driver => "i2c-piix4",
540       match => qr/^SMBus PIIX4 adapter at /,
541     } , 
542     {
543       vendid => 0x1166,
544       devid  => 0x0205,
545       procid => "ServerWorks HT-1000 South Bridge",
546       driver => "i2c-piix4",
547       match => qr/^SMBus PIIX4 adapter at /,
548     },
549     { 
550       vendid => 0x1283,
551       devid  => 0x8172,
552       procid => "ITE 8172G MIPS/SH4 Support Chip",
553       driver => "i2c-adap-ite",
554       match => qr/^ITE IIC adapter/,
555     } , 
556     { 
557       vendid => 0x5333,
558       devid  => 0x8A20,
559       procid => "S3 Savage 3D",
560       driver => "to-be-written",
561     } , 
562     { 
563       vendid => 0x5333,
564       devid  => 0x8A21,
565       procid => "S3 Savage 3D MV",
566       driver => "to-be-written",
567     } , 
568     { 
569       vendid => 0x5333,
570       devid  => 0x8A22,
571       procid => "S3 Savage 4",
572       driver => "i2c-savage4",
573       match => qr/^I2C Savage4 adapter/,
574     } , 
575     { 
576       vendid => 0x5333,
577       devid  => 0x9102,
578       procid => "S3 Savage 2000",
579       driver => "i2c-savage4",
580       match => qr/^I2C Savage4 adapter/,
581     } , 
582     { 
583       vendid => 0x5333,
584       devid  => 0x8A25,
585       procid => "S3 ProSavage PM",
586       driver => "to-be-written",
587     } , 
588     { 
589       vendid => 0x5333,
590       devid  => 0x8A26,
591       procid => "S3 ProSavage KM",
592       driver => "to-be-written",
593     } , 
594     { 
595       vendid => 0x5333,
596       devid  => 0x8C10,
597       procid => "S3 Savage MX MV",
598       driver => "to-be-written",
599     } , 
600     { 
601       vendid => 0x5333,
602       devid  => 0x8C11,
603       procid => "S3 Savage MX",
604       driver => "to-be-written",
605     } , 
606     { 
607       vendid => 0x5333,
608       devid  => 0x8C12,
609       procid => "S3 Savage IX MV",
610       driver => "to-be-written",
611     } , 
612     { 
613       vendid => 0x5333,
614       devid  => 0x8C13,
615       procid => "S3 Savage IX",
616       driver => "to-be-written",
617     } , 
618     { 
619       vendid => 0x1002,
620       devid  => 0x4353,
621       procid => "ATI Technologies Inc ATI SMBus",
622       driver => "i2c-piix4",
623       match => qr/^SMBus PIIX4 adapter at /,
624     } , 
625     { 
626       vendid => 0x1002,
627       devid  => 0x4363,
628       procid => "ATI Technologies Inc ATI SMBus",
629       driver => "i2c-piix4",
630       match => qr/^SMBus PIIX4 adapter at /,
631     } , 
632     { 
633       vendid => 0x1002,
634       devid  => 0x4372,
635       procid => "ATI Technologies Inc ATI SMBus",
636       driver => "i2c-piix4",
637       match => qr/^SMBus PIIX4 adapter at /,
638     } , 
639     {
640       vendid => 0x100B,
641       devid => 0x0500,
642       procid => "SCx200 Bridge",
643       driver => "scx200_acb",
644       match => qr/^(NatSemi SCx200 ACCESS\.bus|SCx200 ACB\d+) /,
645     },
646     {
647       vendid => 0x100B,
648       devid => 0x0510,
649       procid => "SC1100 Bridge",
650       driver => "scx200_acb",
651       match => qr/^(NatSemi SCx200 ACCESS\.bus|SCx200 ACB\d+) /,
652     },
653     {
654       vendid => 0x100B,
655       devid => 0x002B,
656       procid => "CS5535 ISA bridge",
657       driver => "scx200_acb",
658       match => qr/^CS5535 ACB\d+ /,
659     },
660     {
661       vendid => 0x1022,
662       devid => 0x2090,
663       procid => "CS5536 [Geode companion] ISA",
664       driver => "scx200_acb",
665       match => qr/^CS553[56] ACB\d+ /,
666     },
667);
668
669# The following entries used to appear directly in @pci_adapters.
670# Because of the tendency of SiS chipsets to have their real PCI
671# IDs obscured, we have to qualify these with a custom detection
672# routine before we add them to the @pci_adapters list.
673#
674use vars qw(@pci_adapters_sis5595 @pci_adapters_sis645 @pci_adapters_sis96x);
675@pci_adapters_sis5595 = (
676     {
677       vendid => 0x1039,
678       devid  => 0x0008,
679       procid => "Silicon Integrated Systems SIS5595",
680       driver => "i2c-sis5595",
681       match => qr/^SMBus SIS5595 adapter at [0-9a-f]{4}/,
682     } ,
683);
684
685@pci_adapters_sis645 = (
686     {
687       vendid => 0x1039,
688       devid  => 0x0008,
689       procid => "Silicon Integrated Systems SIS5595",
690       driver => "i2c-sis645",
691       match => qr/^SiS645 SMBus adapter at [0-9a-f]{4}/,
692     } ,
693     {
694       vendid => 0x1039,
695       devid  => 0x0016,
696       procid => "Silicon Integrated Systems SMBus Controller",
697       driver => "i2c-sis645",
698       match => qr/^SiS645 SMBus adapter at 0x[0-9a-f]{4}/,
699     } ,
700     {
701       vendid => 0x1039,
702       devid  => 0x0018,
703       procid => "Silicon Integrated Systems 85C503/5513 (LPC Bridge)",
704       driver => "i2c-sis645",
705       match => qr/^SiS645 SMBus adapter at 0x[0-9a-f]{4}/,
706     } ,
707);
708
709@pci_adapters_sis96x = (
710     {
711       vendid => 0x1039,
712       devid  => 0x0016,
713       procid => "Silicon Integrated Systems SMBus Controller",
714       driver => "i2c-sis96x",
715       match => qr/^SiS96x SMBus adapter at 0x[0-9a-f]{4}/,
716     } ,
717);
718
719# This is a list of all recognized chips.
720# Each entry must have the following fields:
721#  name: The full chip name
722#  driver: The driver name (without .o extension). Put in exactly
723#      "to-be-written" if it is not yet available. Put in exactly
724#      "not-a-sensor" if it is not a hardware monitoring chip and
725#      there is no known driver for it.
726#      Put in exactly "use-isa-instead" if no i2c driver will be written.
727#  i2c_addrs (optional): For I2C chips, the range of valid I2C addresses to
728#      probe. Recommend avoiding 0x69 because of clock chips.
729#  i2c_detect (optional): For I2C chips, the function to call to detect
730#      this chip. The function should take two parameters: an open file
731#      descriptor to access the bus, and the I2C address to probe.
732#  isa_addrs (optional): For ISA chips, the range of valid port addresses to
733#      probe.
734#  isa_detect (optional): For ISA chips, the function to call to detect
735#      this chip. The function should take one parameter: the ISA address
736#      to probe.
737#  alias_detect (optional): For chips which can be both on the ISA and the
738#      I2C bus, a function which detectes whether two entries are the same.
739#      The function should take three parameters: The ISA address, the
740#      I2C bus number, and the I2C address.
741@chip_ids = (
742     {
743       name => "Myson MTP008",
744       driver => "mtp008",
745       i2c_addrs => [0x2c..0x2e], 
746       i2c_detect => sub { mtp008_detect(@_); },
747     } ,
748     {
749       name => "National Semiconductor LM78",
750       driver => "lm78",
751       i2c_addrs => [0x20..0x2f], 
752       i2c_detect => sub { lm78_detect(0, @_); },
753       isa_addrs => [0x290],
754       isa_detect => sub { lm78_isa_detect(0, @_); },
755       alias_detect => sub { lm78_alias_detect(0, @_); },
756     } ,
757     {
758       name => "National Semiconductor LM78-J",
759       driver => "lm78",
760       i2c_addrs => [0x20..0x2f], 
761       i2c_detect => sub { lm78_detect(1, @_); },
762       isa_addrs => [0x290],
763       isa_detect => sub { lm78_isa_detect(1, @_); },
764       alias_detect => sub { lm78_alias_detect(1, @_); },
765     } ,
766     {
767       name => "National Semiconductor LM79",
768       driver => "lm78",
769       i2c_addrs => [0x20..0x2f], 
770       i2c_detect => sub { lm78_detect(2, @_); },
771       isa_addrs => [0x290],
772       isa_detect => sub { lm78_isa_detect(2, @_); },
773       alias_detect => sub { lm78_alias_detect(2, @_); },
774     } ,
775     {
776       name => "National Semiconductor LM75",
777       driver => "lm75",
778       i2c_addrs => [0x48..0x4f],
779       i2c_detect => sub { lm75_detect(@_); },
780     } ,
781     {
782       name => "National Semiconductor LM77",
783       driver => "lm77",
784       i2c_addrs => [0x48..0x4b],
785       i2c_detect => sub { lm77_detect(@_); },
786     },
787     {
788       name => "National Semiconductor LM80",
789       driver => "lm80",
790       i2c_addrs => [0x28..0x2f],
791       i2c_detect => sub { lm80_detect(@_); },
792     },
793     {
794       name => "National Semiconductor LM85 or LM96000",
795       driver => "lm85",
796       i2c_addrs => [0x2c..0x2e],
797       i2c_detect => sub { lm85_detect(0x01, @_); },
798     },
799     {
800       name => "Analog Devices ADM1027, ADT7460 or ADT7463",
801       driver => "lm85",
802       i2c_addrs => [0x2c..0x2e],
803       i2c_detect => sub { lm85_detect(0x41, @_); },
804     },
805     {
806       name => "SMSC EMC6D100, EMC6D101 or EMC6D102",
807       driver => "lm85",
808       i2c_addrs => [0x2c..0x2e],
809       i2c_detect => sub { lm85_detect(0x5c, @_); },
810     },
811     {
812       name => "Analog Devices ADT7462",
813       driver => "to-be-written",
814       # The datasheet says addresses 0x5C and 0x58, but I guess these are
815       # left-aligned values
816       i2c_addrs => [0x2c, 0x2e],
817       i2c_detect => sub { adt7467_detect(2, @_); },
818     },
819     {
820       name => "Analog Devices ADT7466",
821       driver => "to-be-written",
822       i2c_addrs => [0x4c],
823       i2c_detect => sub { adt7467_detect(3, @_); },
824     },
825     {
826       name => "Analog Devices ADT7467 or ADT7468",
827       driver => "to-be-written",
828       i2c_addrs => [0x2e],
829       i2c_detect => sub { adt7467_detect(0, @_); },
830     },
831     {
832       name => "Analog Devices ADT7470",
833       driver => "to-be-written",
834       i2c_addrs => [0x2c, 0x2e, 0x2f],
835       i2c_detect => sub { adt7467_detect(4, @_); },
836     },
837     {
838       name => "Analog Devices ADT7473",
839       driver => "to-be-written",
840       i2c_addrs => [0x2e],
841       i2c_detect => sub { adt7473_detect(0, @_); },
842     },
843     {
844       name => "Analog Devices ADT7475",
845       driver => "to-be-written",
846       i2c_addrs => [0x2e],
847       i2c_detect => sub { adt7473_detect(1, @_); },
848     },
849     {
850       name => "Analog Devices ADT7476",
851       driver => "to-be-written",
852       i2c_addrs => [0x2c..0x2e],
853       i2c_detect => sub { adt7467_detect(1, @_); },
854     },
855     {
856       name => "National Semiconductor LM87",
857       driver => "lm87",
858       i2c_addrs => [0x2c..0x2e],
859       i2c_detect => sub { lm87_detect(@_); },
860     },
861     {
862       name => "National Semiconductor LM93",
863       driver => "lm93",
864       i2c_addrs => [0x2c..0x2e],
865       i2c_detect => sub { lm93_detect(@_); },
866     },
867     {
868       name => "Winbond W83781D",
869       driver => "w83781d",
870       i2c_detect => sub { w83781d_detect(0, @_); },
871       i2c_addrs => [0x20..0x2f], 
872       isa_addrs => [0x290],
873       isa_detect => sub { w83781d_isa_detect(0, @_); },
874       alias_detect => sub { w83781d_alias_detect(0, @_); },
875     } ,
876     {
877       name => "Winbond W83782D",
878       driver => "w83781d",
879       i2c_addrs => [0x20..0x2f], 
880       i2c_detect => sub { w83781d_detect(1, @_); },
881       isa_addrs => [0x290],
882       isa_detect => sub { w83781d_isa_detect(1, @_); },
883       alias_detect => sub { w83781d_alias_detect(1, @_); },
884     } ,
885     {
886       name => "Winbond W83783S",
887       driver => "w83781d",
888       i2c_addrs => [0x2d],
889       i2c_detect => sub { w83781d_detect(2, @_); },
890     } ,
891     {
892       name => "Winbond W83792D",
893       driver => "w83792d",
894       i2c_addrs => [0x2c..0x2f],
895       i2c_detect => sub { w83781d_detect(8, @_); },
896     },
897     {
898       name => "Winbond W83793R/G",
899       driver => "w83793",
900       i2c_addrs => [0x2c..0x2f],
901       i2c_detect => sub { w83793_detect(0, @_); },
902     },
903     {
904       name => "Winbond W83791SD",
905       driver => "not-a-sensor",
906       i2c_addrs => [0x2c..0x2f],
907       i2c_detect => sub { w83791sd_detect(@_); },
908     },
909     {
910       name => "Winbond W83627HF",
911       driver => "w83781d",
912       i2c_addrs => [0x20..0x2f], 
913       i2c_detect => sub { w83781d_detect(3, @_); },
914       isa_addrs => [0x290],
915       isa_detect => sub { w83781d_isa_detect(3, @_); },
916       alias_detect => sub { w83781d_alias_detect(3, @_); },
917     } ,
918     {
919       name => "Winbond W83627EHF",
920       driver => "use-isa-instead",
921       i2c_addrs => [0x28..0x2f], 
922       i2c_detect => sub { w83781d_detect(9, @_); },
923     },
924     {
925       name => "Winbond W83627DHG",
926       driver => "use-isa-instead",
927       i2c_addrs => [0x28..0x2f], 
928       i2c_detect => sub { w83781d_detect(10, @_); },
929     },
930     {
931       name => "Asus AS99127F (rev.1)",
932       driver => "w83781d",
933       i2c_addrs => [0x28..0x2f],
934       i2c_detect => sub { w83781d_detect(4, @_); },
935     } ,
936     {
937       name => "Asus AS99127F (rev.2)",
938       driver => "w83781d",
939       i2c_addrs => [0x28..0x2f],
940       i2c_detect => sub { w83781d_detect(5, @_); },
941     } ,
942     {
943       name => "Asus ASB100 Bach",
944       driver => "asb100",
945       i2c_addrs => [0x28..0x2f],
946       i2c_detect => sub { w83781d_detect(6, @_); },
947     } ,
948     {
949       name => "Asus ASM58 Mozart-2",
950       driver => "to-be-written",
951       i2c_addrs => [0x77],
952       i2c_detect => sub { mozart_detect(0, @_); },
953     } ,
954     {
955       name => "Asus AS2K129R Mozart-2",
956       driver => "to-be-written",
957       i2c_addrs => [0x77],
958       i2c_detect => sub { mozart_detect(1, @_); },
959     } ,
960     {
961       name => "Asus Mozart-2",
962       driver => "to-be-written",
963       i2c_addrs => [0x77],
964       i2c_detect => sub { mozart_detect(2, @_); },
965     } ,
966     {
967       name => "Winbond W83L784R/AR",
968       driver => "to-be-written",
969       i2c_addrs => [0x2d],
970       i2c_detect => sub { w83l784r_detect(0, @_); },
971     } ,
972     {
973       name => "Winbond W83L785R",
974       driver => "to-be-written",
975       i2c_addrs => [0x2d],
976       i2c_detect => sub { w83l784r_detect(1, @_); },
977     } ,
978     {
979       name => "Winbond W83L785TS-S",
980       driver => "w83l785ts",
981       i2c_addrs => [0x2e], 
982       i2c_detect => sub { w83l785ts_detect(0, @_); },
983     } ,
984     {
985       name => "Genesys Logic GL518SM Revision 0x00",
986       driver => "gl518sm",
987       i2c_addrs => [0x2c, 0x2d],
988       i2c_detect => sub { gl518sm_detect(0, @_); },
989     },
990     {
991       name => "Genesys Logic GL518SM Revision 0x80",
992       driver => "gl518sm",
993       i2c_addrs => [0x2c, 0x2d],
994       i2c_detect => sub { gl518sm_detect(1, @_); },
995     },
996     {
997       name => "Genesys Logic GL520SM",
998       driver => "gl520sm",
999       i2c_addrs => [0x2c, 0x2d],
1000       i2c_detect => sub { gl520sm_detect(@_); },
1001     },
1002     {
1003       name => "Genesys Logic GL525SM",
1004       driver => "Unwritten (GL525SM)",
1005       i2c_addrs => [0x2d],
1006       i2c_detect => sub { gl525sm_detect(@_); },
1007     },
1008     {
1009       name => "Analog Devices ADM9240",
1010       driver => "adm9240",
1011       i2c_addrs => [0x2c..0x2f],
1012       i2c_detect => sub { adm9240_detect(0, @_); },
1013     },
1014     {
1015       name => "Dallas Semiconductor DS1621",
1016       driver => "ds1621",
1017       i2c_addrs => [0x48..0x4f],
1018       i2c_detect => sub { ds1621_detect(@_); },
1019     } ,
1020     {
1021       name => "Dallas Semiconductor DS1780",
1022       driver => "adm9240",
1023       i2c_addrs => [0x2c..0x2f],
1024       i2c_detect => sub { adm9240_detect(1, @_); },
1025     },
1026     {
1027       name => "National Semiconductor LM81",
1028       driver => "adm9240",
1029       i2c_addrs => [0x2c..0x2f],
1030       i2c_detect => sub { adm9240_detect(2, @_); },
1031     },
1032     {
1033       name => "Analog Devices ADM1026",
1034       driver => "adm1026",
1035       i2c_addrs => [0x2c,0x2d,0x2e],
1036       i2c_detect => sub { adm1026_detect(0, @_); },
1037     },
1038     {
1039       name => "Analog Devices ADM1025",
1040       driver => "adm1025",
1041       i2c_addrs => [0x2c..0x2e],
1042       i2c_detect => sub { adm1025_detect(0, @_); },
1043     },
1044     {
1045       name => "Philips NE1619",
1046       driver => "adm1025",
1047       i2c_addrs => [0x2c..0x2d],
1048       i2c_detect => sub { adm1025_detect(1, @_); },
1049     },
1050     {
1051       name => "Analog Devices ADM1024",
1052       driver => "adm1024",
1053       i2c_addrs => [0x2c..0x2e],
1054       i2c_detect => sub { adm1024_detect(0, @_); },
1055     },
1056     {
1057       name => "Analog Devices ADM1021",
1058       driver => "adm1021",
1059       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1060       i2c_detect => sub { adm1021_detect(0, @_); },
1061     },
1062     {
1063       name => "Analog Devices ADM1021A/ADM1023",
1064       driver => "adm1021",
1065       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1066       i2c_detect => sub { adm1021_detect(1, @_); },
1067     },
1068     {
1069       name => "Maxim MAX1617",
1070       driver => "adm1021",
1071       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1072       i2c_detect => sub { adm1021_detect(2, @_); },
1073     },
1074     {
1075       name => "Maxim MAX1617A",
1076       driver => "adm1021",
1077       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1078       i2c_detect => sub { adm1021_detect(3, @_); },
1079     },
1080     {
1081       name => "Maxim MAX6650/MAX6651",
1082       driver => "max6650",
1083       i2c_addrs => [0x1b,0x1f,0x48,0x4b],
1084       i2c_detect => sub { max6650_detect(0, @_); },
1085     },
1086     {
1087       name => "TI THMC10",
1088       driver => "adm1021",
1089       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1090       i2c_detect => sub { adm1021_detect(4, @_); },
1091     },
1092     {
1093       name => "National Semiconductor LM84",
1094       driver => "adm1021",
1095       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1096       i2c_detect => sub { adm1021_detect(5, @_); },
1097     },
1098     {
1099       name => "Genesys Logic GL523SM",
1100       driver => "adm1021",
1101       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1102       i2c_detect => sub { adm1021_detect(6, @_); },
1103     },
1104     {
1105       name => "Onsemi MC1066",
1106       driver => "adm1021",
1107       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1108       i2c_detect => sub { adm1021_detect(7, @_); },
1109     },
1110     {
1111       name => "Maxim MAX1619",
1112       driver => "max1619",
1113       i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
1114       i2c_detect => sub { max1619_detect(0, @_); },
1115     },
1116     {
1117       name => "National Semiconductor LM82/LM83",
1118       driver => "lm83",
1119       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1120       i2c_detect => sub { lm83_detect(0, @_); },
1121     },
1122     {
1123       name => "National Semiconductor LM90",
1124       driver => "lm90",
1125       i2c_addrs => [0x4c],
1126       i2c_detect => sub { lm90_detect(0, @_); },
1127     },
1128     {
1129       name => "National Semiconductor LM89/LM99",
1130       driver => "lm90",
1131       i2c_addrs => [0x4c..0x4d],
1132       i2c_detect => sub { lm90_detect(1, @_); },
1133     },
1134     {
1135       name => "National Semiconductor LM86",
1136       driver => "lm90",
1137       i2c_addrs => [0x4c],
1138       i2c_detect => sub { lm90_detect(2, @_); },
1139     },
1140     {
1141       name => "Analog Devices ADM1032",
1142       driver => "lm90",
1143       i2c_addrs => [0x4c..0x4d],
1144       i2c_detect => sub { lm90_detect(3, @_); },
1145     },
1146     {
1147       name => "Maxim MAX6657/MAX6658/MAX6659",
1148       driver => "lm90",
1149       i2c_addrs => [0x4c],
1150       i2c_detect => sub { lm90_detect(4, @_); },
1151     },
1152     {
1153       name => "Maxim MAX6659",
1154       driver => "lm90",
1155       i2c_addrs => [0x4d..0x4e], # 0x4c is handled above
1156       i2c_detect => sub { lm90_detect(4, @_); },
1157     },
1158     {
1159       name => "National Semiconductor LM63",
1160       driver => "lm63",
1161       i2c_addrs => [0x4c],
1162       i2c_detect => sub { lm63_detect(1, @_); },
1163     },
1164     {
1165       name => "Fintek F75363SG",
1166       driver => "lm63", # Not yet
1167       i2c_addrs => [0x4c],
1168       i2c_detect => sub { lm63_detect(2, @_); },
1169     },
1170     {
1171       name => "National Semiconductor LM92",
1172       driver => "lm92",
1173       i2c_addrs => [0x48..0x4b],
1174       i2c_detect => sub { lm92_detect(0, @_); },
1175     },
1176     {
1177       name => "National Semiconductor LM76",
1178       driver => "lm92",
1179       i2c_addrs => [0x48..0x4b],
1180       i2c_detect => sub { lm92_detect(1, @_); },
1181     },
1182     {
1183       name => "Maxim MAX6633/MAX6634/MAX6635",
1184       driver => "lm92",
1185       i2c_addrs => [0x40..0x4f],
1186       i2c_detect => sub { lm92_detect(2, @_); },
1187     },
1188     {
1189       name => "Analog Devices ADT7461",
1190       driver => "lm90",
1191       i2c_addrs => [0x4c..0x4d],
1192       i2c_detect => sub { lm90_detect(5, @_); },
1193     },
1194     {
1195       name => "Analog Devices ADM1029",
1196       driver => "to-be-written",
1197       i2c_addrs => [0x28..0x2f],
1198       i2c_detect => sub { adm1029_detect(0, @_); },
1199     },
1200     {
1201       name => "Analog Devices ADM1030",
1202       driver => "adm1031",
1203       i2c_addrs => [0x2c..0x2e],
1204       i2c_detect => sub { adm1031_detect(0, @_); },
1205     },
1206     {
1207       name => "Analog Devices ADM1031",
1208       driver => "adm1031",
1209       i2c_addrs => [0x2c..0x2e],
1210       i2c_detect => sub { adm1031_detect(1, @_); },
1211     },
1212     {
1213       name => "Analog Devices ADM1033",
1214       driver => "to-be-written",
1215       i2c_addrs => [0x50..0x53],
1216       i2c_detect => sub { adm1034_detect(0, @_); },
1217     },
1218     {
1219       name => "Analog Devices ADM1034",
1220       driver => "to-be-written",
1221       i2c_addrs => [0x50..0x53],
1222       i2c_detect => sub { adm1034_detect(1, @_); },
1223     },
1224     {
1225       name => "Analog Devices ADM1022",
1226       driver => "thmc50",
1227       i2c_addrs => [0x2c..0x2e],
1228       i2c_detect => sub { adm1022_detect(0, @_); },
1229     },
1230     {
1231       name => "Texas Instruments THMC50",
1232       driver => "thmc50",
1233       i2c_addrs => [0x2c..0x2e],
1234       i2c_detect => sub { adm1022_detect(1, @_); },
1235     },
1236     {
1237       name => "Analog Devices ADM1028",
1238       driver => "thmc50",
1239       i2c_addrs => [0x2e],
1240       i2c_detect => sub { adm1022_detect(2, @_); },
1241     },
1242     {
1243       name => "Silicon Integrated Systems SIS5595",
1244       driver => "sis5595",
1245       isa_addrs => [ 0 ],
1246       isa_detect => sub { sis5595_pci_detect(); },
1247     },
1248     {
1249       name => "VIA VT82C686 Integrated Sensors",
1250       driver => "via686a",
1251       isa_addrs => [ 0 ],
1252       isa_detect => sub { via686a_pci_detect(); },
1253     },
1254     {
1255       name => "VIA VT8231 Integrated Sensors",
1256       driver => "vt8231",
1257       isa_addrs => [ 0 ],
1258       isa_detect => sub { via8231_pci_detect(); },
1259     },
1260     {
1261       name => "VIA VT1211 (I2C)",
1262       driver => "use-isa-instead",
1263       i2c_addrs => [0x2d],
1264       i2c_detect => sub { vt1211_i2c_detect(0, @_); },
1265     },
1266     {
1267       name => "ITE IT8712F",
1268       driver => "it87",
1269       i2c_addrs => [0x28..0x2f],
1270       i2c_detect => sub { ite_detect(0, @_); },
1271     },
1272     {
1273       name => "ITE IT8201R/IT8203R/IT8206R/IT8266R",
1274       driver => "not-a-sensor",
1275       i2c_addrs => [0x4e],
1276       i2c_detect => sub { ite_overclock_detect(@_); },
1277     },
1278     {
1279       name => "SPD EEPROM",
1280       driver => "eeprom",
1281       i2c_addrs => [0x50..0x57],
1282       i2c_detect => sub { eeprom_detect(0, @_); },
1283     },
1284     {
1285       name => "Sony Vaio EEPROM",
1286       driver => "eeprom",
1287       i2c_addrs => [0x57],
1288       i2c_detect => sub { eeprom_detect(1, @_); },
1289     },
1290# Disabled by default (potentially dangerous)
1291#     {
1292#       name => "SPD EEPROM with Software Write-Protect",
1293#       driver => "eeprom",
1294#       i2c_addrs => [0x50..0x57],
1295#       i2c_detect => sub { eeprom_detect(2, @_); },
1296#     },
1297     {
1298       name => "EDID EEPROM",
1299       driver => "eeprom",
1300       i2c_addrs => [0x50],
1301       i2c_detect => sub { ddcmonitor_detect(@_); },
1302     },
1303     {
1304       name => "FSC Poseidon",
1305       driver => "fscpos",
1306       i2c_addrs => [0x73],
1307       i2c_detect => sub { fscpos_detect(@_); },
1308     },
1309     {
1310       name => "FSC Scylla",
1311       driver => "fscscy",
1312       i2c_addrs => [0x73],
1313       i2c_detect => sub { fscscy_detect(@_); },
1314     },
1315     {
1316       name => "FSC Hermes",
1317       driver => "fscher",
1318       i2c_addrs => [0x73],
1319       i2c_detect => sub { fscher_detect(@_); },
1320     },
1321     {
1322       name => "ALi M5879",
1323       driver => "to-be-written",
1324       i2c_addrs => [0x2c..0x2d],
1325       i2c_detect => sub { m5879_detect(@_); },
1326     },
1327     {
1328       name => "SMSC LPC47M15x, LPC47M192 or LPC47M997",
1329       driver => "smsc47m192",
1330       i2c_addrs => [0x2c..0x2d],
1331       i2c_detect => sub { smsc47m192_detect(@_); },
1332     },
1333     {
1334       name => "SMSC DME1737",
1335       driver => "to-be-written",
1336       i2c_addrs => [0x2c..0x2e],
1337       i2c_detect => sub { dme1737_detect(@_); },
1338     },
1339     {
1340       name => "Fintek F75111R/RG/N (GPIO)",
1341       driver => "to-be-written",
1342       i2c_addrs => [0x4e], # 0x37 not probed
1343       i2c_detect => sub { fintek_detect(1, @_); },
1344     },
1345     {
1346       name => "Fintek F75121R/F75122R/RG (VID+GPIO)",
1347       driver => "to-be-written",
1348       i2c_addrs => [0x4e], # 0x37 not probed
1349       i2c_detect => sub { fintek_detect(2, @_); },
1350     },
1351     {
1352       name => "Fintek F75373S/SG",
1353       driver => "to-be-written",
1354       i2c_addrs => [0x2d..0x2e],
1355       i2c_detect => sub { fintek_detect(3, @_); },
1356     },
1357     {
1358       name => "Fintek F75375S/SP",
1359       driver => "to-be-written",
1360       i2c_addrs => [0x2d..0x2e],
1361       i2c_detect => sub { fintek_detect(4, @_); },
1362     },
1363     {
1364       name => "Fintek F75387SG/RG",
1365       driver => "to-be-written",
1366       i2c_addrs => [0x2d..0x2e],
1367       i2c_detect => sub { fintek_detect(5, @_); },
1368     },
1369     {
1370       name => "Fintek F75383S/M",
1371       driver => "to-be-written",
1372       i2c_addrs => [0x4c],
1373       i2c_detect => sub { fintek_detect(6, @_); },
1374     },
1375     {
1376       name => "Fintek F75384S/M",
1377       driver => "to-be-written",
1378       i2c_addrs => [0x4d],
1379       i2c_detect => sub { fintek_detect(6, @_); },
1380     },
1381     {
1382       name => "Fintek custom power control IC",
1383       driver => "to-be-written",
1384       i2c_addrs => [0x2f],
1385       i2c_detect => sub { fintek_detect(7, @_); },
1386     },
1387     {
1388       name => "AMD K8 thermal sensors",
1389       driver => "k8temp",
1390       isa_addrs => [ 0 ],
1391       isa_detect => sub { k8temp_pci_detect(); },
1392     },
1393     {
1394       name => "Philips Semiconductors SAA1064",
1395       driver => "saa1064",
1396       i2c_addrs => [0x38..0x3b],
1397       i2c_detect => sub { saa1064_detect(@_); },
1398     },
1399     {
1400       name => "Philips Semiconductors PCA9540",
1401       driver => "pca9540",
1402       i2c_addrs => [0x70],
1403       i2c_detect => sub { pca9540_detect(@_); },
1404     },
1405     {
1406       name => "Philips Semiconductors PCA9556",
1407       driver => "to-be-written",
1408       i2c_addrs => [0x18..0x1f],
1409       i2c_detect => sub { pca9556_detect(@_); },
1410     },
1411     {
1412       name => "Maxim MAX6900",
1413       driver => "to-be-written",
1414       i2c_addrs => [0x50],
1415       i2c_detect => sub { max6900_detect(@_); },
1416     },
1417     {
1418       name => "SMBus 2.0 ARP-Capable Device",
1419       driver => "not-a-sensor",
1420       i2c_addrs => [0x61],
1421       i2c_detect => sub { arp_detect(@_); },
1422     },
1423     {
1424       name => "IPMI BMC KCS",
1425       driver => "bmcsensors",
1426       isa_addrs => [ 0x0ca0 ],
1427       isa_detect => sub { ipmi_kcs_detect(@_); },
1428     },
1429     {
1430       name => "IPMI BMC SMIC",
1431       driver => "bmcsensors",
1432       isa_addrs => [ 0x0ca8 ],
1433       isa_detect => sub { ipmi_smic_detect(@_); },
1434     },
1435     {
1436       name => "Smart Battery Charger",
1437       driver => "to-be-written",
1438       i2c_addrs => [0x09],
1439       i2c_detect => sub { smartbatt_chgr_detect(@_); },
1440     },
1441     {
1442       name => "Smart Battery Manager/Selector",
1443       driver => "to-be-written",
1444       i2c_addrs => [0x0a],
1445       i2c_detect => sub { smartbatt_mgr_detect(@_); },
1446     },
1447     {
1448       name => "Smart Battery",
1449       driver => "smartbatt",
1450       i2c_addrs => [0x0b],
1451       i2c_detect => sub { smartbatt_detect(@_); },
1452     },
1453);
1454
1455# Special case chip information goes here and would be included in
1456# the chip_special_cases routine below
1457use vars qw($chip_kern24_w83791d $chip_kern26_w83791d);
1458$chip_kern24_w83791d = {
1459        name => "Winbond W83791D",
1460        driver => "w83781d",
1461        i2c_addrs => [0x2c..0x2f],
1462        i2c_detect => sub { w83781d_detect(7, @_); },
1463};
1464
1465$chip_kern26_w83791d = {
1466        name => "Winbond W83791D",
1467        driver => "w83791d",
1468        i2c_addrs => [0x2c..0x2f],
1469        i2c_detect => sub { w83781d_detect(7, @_); },
1470};
1471
1472# This is a list of all recognized superio chips.
1473# Each entry must have the following fields:
1474#  name: The full chip name
1475#  driver: The driver name (without .o extension). Put in
1476#      "to-be-written" if it is not yet available.
1477#      Put in "not-a-sensor" if the chip doesn't have hardware monitoring
1478#      capabilities (listing such chips here removes the need of manual
1479#      lookup when people report them).
1480#  devid: The device ID(s) we have to match (base device)
1481#  devid_mask (optional): Bitmask to apply before checking the device ID
1482#  logdev: The logical device containing the sensors
1483#  alias_detect (optional): For chips which can be both on the ISA and the
1484#      I2C bus, a function which detectes whether two entries are the same.
1485#      The function should take three parameters: The ISA address, the
1486#      I2C bus number, and the I2C address.
1487# Entries are grouped by family. Each family entry has the following fields:
1488#  family: The family name
1489#  guess (optional): Typical logical device address. This lets us do
1490#      generic probing if we fail to recognize the chip.
1491#  enter: The password sequence to write to the address register
1492#  chips: Array of chips
1493@superio_ids = (
1494  {
1495    family => "ITE",
1496    guess => 0x290,
1497    enter =>
1498    {
1499      0x2e => [0x87, 0x01, 0x55, 0x55],
1500      0x4e => [0x87, 0x01, 0x55, 0xaa],
1501    },
1502    chips =>
1503    [
1504      {
1505        name => "ITE IT8702F Super IO Sensors",
1506        driver => "to-be-written",
1507        devid => 0x8702,
1508        logdev => 0x04,
1509      },
1510      {
1511        name => "ITE IT8705F Super IO Sensors",
1512        driver => "it87",
1513        devid => 0x8705,
1514        logdev => 0x04,
1515      },
1516      {
1517        name => "ITE IT8712F Super IO Sensors",
1518        driver => "it87",
1519        devid => 0x8712,
1520        logdev => 0x04,
1521        alias_detect => sub { ite_alias_detect(0, @_); },
1522      },
1523      {
1524        name => "ITE IT8716F Super IO Sensors",
1525        driver => "it87",
1526        devid => 0x8716,
1527        logdev => 0x04,
1528      },
1529      {
1530        name => "ITE IT8718F Super IO Sensors",
1531        driver => "it87",
1532        devid => 0x8718,
1533        logdev => 0x04,
1534      },
1535    ],
1536  },
1537  {
1538    family => "National Semiconductor",
1539    enter =>
1540    {
1541      0x2e => [],
1542      0x4e => [],
1543    },
1544    chips =>
1545    [
1546      {
1547        name => "Nat. Semi. PC87351 Super IO Fan Sensors",
1548        driver => "to-be-written",
1549        devid => 0xe2,
1550        logdev => 0x08,
1551      },
1552      {
1553        name => "Nat. Semi. PC87360 Super IO Fan Sensors",
1554        driver => "pc87360",
1555        devid => 0xe1,
1556        logdev => 0x09,
1557      },
1558      {
1559        name => "Nat. Semi. PC87363 Super IO Fan Sensors",
1560        driver => "pc87360",
1561        devid => 0xe8,
1562        logdev => 0x09,
1563      },
1564      {
1565        name => "Nat. Semi. PC87364 Super IO Fan Sensors",
1566        driver => "pc87360",
1567        devid => 0xe4,
1568        logdev => 0x09,
1569      },
1570      {
1571        name => "Nat. Semi. PC87365 Super IO Fan Sensors",
1572        driver => "pc87360",
1573        devid => 0xe5,
1574        logdev => 0x09,
1575      },
1576      {
1577        name => "Nat. Semi. PC87365 Super IO Voltage Sensors",
1578        driver => "pc87360",
1579        devid => 0xe5,
1580        logdev => 0x0d,
1581      },
1582      {
1583        name => "Nat. Semi. PC87365 Super IO Thermal Sensors",
1584        driver => "pc87360",
1585        devid => 0xe5,
1586        logdev => 0x0e,
1587      },
1588      {
1589        name => "Nat. Semi. PC87366 Super IO Fan Sensors",
1590        driver => "pc87360",
1591        devid => 0xe9,
1592        logdev => 0x09,
1593      },
1594      {
1595        name => "Nat. Semi. PC87366 Super IO Voltage Sensors",
1596        driver => "pc87360",
1597        devid => 0xe9,
1598        logdev => 0x0d,
1599      },
1600      {
1601        name => "Nat. Semi. PC87366 Super IO Thermal Sensors",
1602        driver => "pc87360",
1603        devid => 0xe9,
1604        logdev => 0x0e,
1605      },
1606      {
1607        name => "Nat. Semi. PC87372 Super IO Fan Sensors",
1608        driver => "to-be-written",
1609        devid => 0xf0,
1610        logdev => 0x09,
1611      },
1612      {
1613        name => "Nat. Semi. PC87373 Super IO Fan Sensors",
1614        driver => "to-be-written",
1615        devid => 0xf3,
1616        logdev => 0x09,
1617      },
1618      {
1619        name => "Nat. Semi. PC87591 Super IO",
1620        driver => "to-be-written",
1621        devid => 0xec,
1622        logdev => 0x0f,
1623      },
1624      {
1625        name => "Nat. Semi. PC87371 Super IO",
1626        driver => "not-a-sensor",
1627        devid => 0xd0,
1628      },
1629      {
1630        name => "Nat. Semi. PC97371 Super IO",
1631        driver => "not-a-sensor",
1632        devid => 0xdf,
1633      },
1634      {
1635        name => "Nat. Semi. PC8739x Super IO",
1636        driver => "not-a-sensor",
1637        devid => 0xea,
1638      },
1639      {
1640        name => "Nat. Semi. PC8741x Super IO",
1641        driver => "not-a-sensor",
1642        devid => 0xee,
1643      },
1644      {
1645        name => "Nat. Semi. PC87427 Super IO Fan Sensors",
1646        driver => "pc87427",
1647        devid => 0xf2,
1648        logdev => 0x09,
1649      },
1650      {
1651        name => "Nat. Semi. PC87427 Super IO Health Sensors",
1652        driver => "to-be-written",
1653        devid => 0xf2,
1654        logdev => 0x14,
1655      },
1656    ],
1657  },
1658  {
1659    family => "SMSC",
1660    enter =>
1661    {
1662      0x2e => [0x55],
1663      0x4e => [0x55],
1664    },
1665    chips =>
1666    [
1667      {
1668        name => "SMSC LPC47B27x Super IO Fan Sensors",
1669        driver => "smsc47m1",
1670        devid => 0x51,
1671        logdev => 0x0a,
1672      },
1673      {
1674        name => "SMSC LPC47M10x/112/13x Super IO Fan Sensors",
1675        driver => "smsc47m1",
1676        devid => 0x59,
1677        logdev => 0x0a,
1678      },
1679      {
1680        name => "SMSC LPC47M14x Super IO Fan Sensors",
1681        driver => "smsc47m1",
1682        devid => 0x5f,
1683        logdev => 0x0a,
1684      },
1685      {
1686        name => "SMSC LPC47M15x/192/997 Super IO Fan Sensors",
1687        driver => "smsc47m1",
1688        devid => 0x60,
1689        logdev => 0x0a,
1690      },
1691      {
1692        name => "SMSC LPC47S42x Super IO Fan Sensors",
1693        driver => "to-be-written",
1694        devid => 0x57,
1695        logdev => 0x0a,
1696      },
1697      {
1698        name => "SMSC LPC47S45x Super IO Fan Sensors",
1699        driver => "to-be-written",
1700        devid => 0x62,
1701        logdev => 0x0a,
1702      },
1703      {
1704        name => "SMSC LPC47M172 Super IO Fan Sensors",
1705        driver => "to-be-written",
1706        devid => 0x14,
1707        logdev => 0x0a,
1708      },
1709      {
1710        name => "SMSC LPC47M182 Super IO Fan Sensors",
1711        driver => "to-be-written",
1712        devid => 0x74,
1713        logdev => 0x0a,
1714      },
1715      {
1716        name => "SMSC LPC47B397-NC Super IO",
1717        driver => "smsc47b397",
1718        devid => 0x6f,
1719        logdev => 0x08,
1720      },
1721      {
1722        name => "SMSC SCH5307-NS Super IO",
1723        driver => "smsc47b397",
1724        devid => 0x81,
1725        logdev => 0x08,
1726      },
1727      {
1728        name => "SMSC LPC47M584-NC Super IO",
1729        # No datasheet
1730        devid => 0x76,
1731      },
1732      {
1733        name => "SMSC DME1737 Super IO",
1734        # Hardware monitoring features are accessed on the SMBus
1735        driver => "not-a-sensor",
1736        devid => 0x78,
1737      },
1738    ],
1739  },
1740  {
1741    family => "VIA/Winbond/Fintek",
1742    guess => 0x290,
1743    enter =>
1744    {
1745      0x2e => [0x87, 0x87],
1746      0x4e => [0x87, 0x87],
1747    },
1748    chips =>
1749    [
1750      {
1751        name => "VIA VT1211 Super IO Sensors",
1752        driver => "vt1211",
1753        devid => 0x3c,
1754        logdev => 0x0b,
1755        alias_detect => sub { vt1211_alias_detect(0, @_); },
1756      },
1757      {
1758        name => "Winbond W83627HF Super IO Sensors",
1759        driver => "w83627hf",
1760        devid => 0x52,
1761        logdev => 0x0b,
1762      },
1763      {
1764        name => "Winbond W83627THF Super IO Sensors",
1765        driver => "w83627hf",
1766        devid => 0x82,
1767        logdev => 0x0b,
1768      },
1769      {
1770        name => "Winbond W83637HF Super IO Sensors",
1771        driver => "w83627hf",
1772        devid => 0x70,
1773        logdev => 0x0b,
1774      },
1775      {
1776        name => "Winbond W83687THF Super IO Sensors",
1777        driver => "w83627hf",
1778        devid => 0x85,
1779        logdev => 0x0b,
1780      },
1781      {
1782        name => "Winbond W83697HF Super IO Sensors",
1783        driver => "w83627hf",
1784        devid => 0x60,
1785        logdev => 0x0b,
1786      },
1787      {
1788        name => "Winbond W83697SF/UF Super IO PWM",
1789        driver => "to-be-written",
1790        devid => 0x68,
1791        logdev => 0x0b,
1792      },
1793      {
1794        name => "Winbond W83627EHF/EHG Super IO Sensors",
1795        driver => "w83627ehf",
1796        # W83627EHF datasheet says 0x886x but 0x8853 was seen, thus the
1797        # broader mask. W83627EHG was seen with ID 0x8863.
1798        devid => 0x8840,
1799        devid_mask => 0xFFC0,
1800        logdev => 0x0b,
1801        alias_detect => sub { w83781d_alias_detect(9, @_); },
1802      },
1803      {
1804        name => "Winbond W83627DHG Super IO Sensors",
1805        driver => "w83627ehf",
1806        devid => 0xA020,
1807        devid_mask => 0xFFF0,
1808        logdev => 0x0b,
1809        alias_detect => sub { w83781d_alias_detect(10, @_); },
1810      },
1811      {
1812        name => "Winbond W83L517D Super IO",
1813        driver => "not-a-sensor",
1814        devid => 0x61,
1815      },
1816      {
1817        name => "Fintek F71805F/FG Super IO Sensors",
1818        driver => "f71805f",
1819        devid => 0x0406,
1820        logdev => 0x04,
1821      },
1822      {
1823        name => "Fintek F71872F/FG Super IO Sensors",
1824        driver => "f71805f",
1825        devid => 0x0341,
1826        logdev => 0x04,
1827      },
1828      {
1829        name => "Fintek F81218D Super IO",
1830        driver => "not-a-sensor",
1831        devid => 0x0206,
1832      },
1833      {
1834        name => "EPoX EP1308 Super IO",
1835        driver => "to-be-written",
1836        devid => 0x0541,
1837        logdev => 0x04,
1838      },
1839    ],
1840  },
1841);
1842
1843#######################
1844# AUXILIARY FUNCTIONS #
1845#######################
1846
1847sub swap_bytes
1848{
1849  return (($_[0] & 0xff00) >> 8) + (($_[0] & 0x00ff) << 8)
1850}
1851
1852# $_[0] is the sought value
1853# @_[1..] is the list to seek in
1854# Returns: 0 on failure, 1 if found.
1855# Note: Every use of this sub probably indicates the use of the wrong
1856#       datastructure
1857sub contains
1858{
1859  my $sought = shift;
1860  foreach (@_) {
1861    return 1 if $sought eq $_;
1862  }
1863  return 0;
1864}
1865
1866sub parse_not_to_scan
1867{
1868  my ($min,$max,$to_parse) = @_;
1869  my @ranges = split /\s*,\s*/, $to_parse;
1870  my @res;
1871  my $range;
1872  foreach $range (@ranges) {
1873    my ($start,$end) = split /\s*-s*/, $range;
1874    $start = oct $start if $start =~ /^0/;
1875    if (defined $end) {
1876      $end = oct $end if $end =~ /^0/;
1877      $start = $min if $start < $min;
1878      $end = $max if $end > $max;
1879      push @res, ($start+0..$end+0);
1880    } else {
1881      push @res, $start+0 if $start >= $min and $start <= $max;
1882    }
1883  }
1884  return sort { $a <=> $b } @res;
1885}
1886
1887# @_[0]: Reference to list 1
1888# @_[1]: Reference to list 2
1889# Result: 0 if they have no elements in common, 1 if they have
1890# Elements must be numeric.
1891sub any_list_match
1892{
1893  my ($list1,$list2) = @_;
1894  my ($el1,$el2);
1895  foreach $el1 (@$list1) {
1896    foreach $el2 (@$list2) {
1897      return 1 if $el1 == $el2;
1898    }
1899  }
1900  return 0;
1901}
1902
1903###################
1904# I/O port access #
1905###################
1906
1907sub initialize_ioports
1908{
1909  sysopen (IOPORTS, "/dev/port", O_RDWR)
1910    or die "/dev/port: $!\n";
1911  binmode IOPORTS;
1912}
1913
1914sub close_ioports
1915{
1916  close (IOPORTS)
1917    or print "Warning: $!\n";
1918}
1919
1920# $_[0]: port to read
1921# Returns: -1 on failure, read value on success.
1922sub inb
1923{
1924  my ($res,$nrchars);
1925  sysseek IOPORTS, $_[0], 0 or return -1;
1926  $nrchars = sysread IOPORTS, $res, 1;
1927  return -1 if not defined $nrchars or $nrchars != 1;
1928  $res = unpack "C",$res ;
1929  return $res;
1930}
1931
1932# $_[0]: port to write
1933# $_[1]: value to write
1934# Returns: -1 on failure, 0 on success.
1935sub outb
1936{
1937  if ($_[1] > 0xff)
1938  {
1939    my ($package, $filename, $line, $sub) = caller(1);
1940    print "\n*** Called outb with value=$_[1] from line $line\n",
1941          "*** (in $sub). PLEASE REPORT!\n",
1942          "*** Terminating.\n";
1943    exit(-1);
1944  }
1945  my $towrite = pack "C", $_[1];
1946  sysseek IOPORTS, $_[0], 0 or return -1;
1947  my $nrchars = syswrite IOPORTS, $towrite, 1;
1948  return -1 if not defined $nrchars or $nrchars != 1;
1949  return 0;
1950}
1951
1952# $_[0]: Address register
1953# $_[1]: Data register
1954# $_[2]: Register to read
1955# Returns: read value
1956sub isa_read_byte
1957{
1958  outb $_[0],$_[2];
1959  return inb $_[1];
1960}
1961
1962# $_[0]: Address register
1963# $_[1]: Data register
1964# $_[2]: Register to write
1965# $_[3}: Value to write
1966# Returns: nothing
1967sub isa_write_byte
1968{
1969  outb $_[0],$_[2];
1970  outb $_[1],$_[3];
1971}
1972
1973#################
1974# AUTODETECTION #
1975#################
1976
1977use vars qw($modules_conf $dev_i2c $sysfs_root);
1978
1979sub initialize_conf
1980{
1981  my $use_devfs = 0;
1982  open(local *INPUTFILE, "/proc/mounts") or die "Can't access /proc/mounts!";
1983  local $_;
1984  while (<INPUTFILE>) {
1985    if (m@^\w+ /dev devfs @) {
1986      $use_devfs = 1;
1987      $dev_i2c = '/dev/i2c/';
1988    }
1989    if (m@^\S+ (/\w+) sysfs @) {
1990      $sysfs_root = $1;
1991    }
1992  }
1993  close INPUTFILE;
1994
1995  my $use_udev = 0;
1996  if (open(*INPUTFILE, '/etc/udev/udev.conf')) {
1997    while (<INPUTFILE>) {
1998      if (m/^\s*udev_db\s*=\s*\"([^"]*)\"/ || m/^\s*udev_db\s*=\s*(\S+)/) {
1999        if (-e $1) {
2000          $use_udev = 1;
2001          $dev_i2c = '/dev/i2c-';
2002        }
2003        last;
2004      }
2005    }
2006    close INPUTFILE;
2007  }
2008 
2009  if (!$use_udev) {
2010    # Try some known default udev db locations, just in case
2011    if (-e '/dev/.udev.tdb' || -e '/dev/.udev'
2012     || -e '/dev/.udevdb') {
2013      $use_udev = 1;
2014      $dev_i2c = '/dev/i2c-';
2015    }
2016  }
2017
2018  if (-f '/etc/modules.conf') {
2019    $modules_conf = '/etc/modules.conf';
2020  } elsif (-f '/etc/conf.modules') {
2021    $modules_conf = '/etc/conf.modules';
2022  } else { # default
2023    $modules_conf = '/etc/modules.conf';
2024  }
2025
2026  if (!($use_devfs || $use_udev)) {
2027    if (-c '/dev/i2c-0') {
2028      $dev_i2c = '/dev/i2c-';
2029    } else { # default
2030      print "No i2c device files found. Use prog/mkdev/mkdev.sh to create them.\n";
2031      exit -1;
2032    }
2033  }
2034}
2035
2036# [0] -> VERSION
2037# [1] -> PATCHLEVEL
2038# [2] -> SUBLEVEL
2039# [3] -> EXTRAVERSION
2040#
2041use vars qw(@kernel_version);
2042
2043sub initialize_kernel_version
2044{
2045  `uname -r` =~ /(\d+)\.(\d+)\.(\d+)(.*)/;
2046  @kernel_version = ($1, $2, $3, $4);
2047}
2048
2049sub kernel_version_at_least
2050{
2051  my ($vers, $plvl, $slvl) = @_;
2052  return 1 if ($kernel_version[0]  > $vers ||
2053                ($kernel_version[0] == $vers && 
2054                  ($kernel_version[1]  > $plvl || 
2055                    ($kernel_version[1] == $plvl && 
2056                      ($kernel_version[2] >= $slvl)))));
2057  return 0;
2058}
2059
2060###########
2061# MODULES #
2062###########
2063
2064use vars qw(%modules_list %modules_supported);
2065
2066sub initialize_modules_list
2067{
2068  open(local *INPUTFILE, "/proc/modules") or return;
2069  local $_;
2070  while (<INPUTFILE>) {
2071    tr/_/-/;
2072    $modules_list{$1} = 1 if m/^(\S*)/;
2073  }
2074}
2075
2076sub initialize_modules_supported
2077{
2078  foreach my $chip (@chip_ids) {
2079    $modules_supported{$chip->{driver}}++;
2080  }
2081}
2082
2083#################
2084# SYSFS HELPERS #
2085#################
2086
2087# From a sysfs device path, return the driver name, or undef
2088sub sysfs_device_driver($)
2089{
2090  my $device = shift;
2091 
2092  my $link = readlink("$device/driver");
2093  return unless defined $link;
2094  return basename($link);
2095}
2096
2097# From a sysfs device path and an attribute name, return the attribute
2098# value, or undef
2099sub sysfs_device_attribute($$)
2100{
2101  my ($device, $attr) = @_;
2102  my $value;
2103
2104  open(local *FILE, "$device/$attr") or return;
2105  return unless defined($value = <FILE>);
2106  close(FILE);
2107
2108  chomp($value);
2109  return $value;
2110}
2111
2112##############
2113# PCI ACCESS #
2114##############
2115
2116use vars qw(%pci_list);
2117
2118# This function returns a list of hashes. Each hash has some PCI information:
2119# 'domain', 'bus', 'slot' and 'func' uniquely identify a PCI device in a
2120# computer; 'vendid' and 'devid' uniquely identify a type of device.
2121# 'class' lets us spot unknown SMBus adapters.
2122# This function is used when sysfs is available (Linux 2.6).
2123sub read_sys_dev_pci($)
2124{
2125  my $devices = shift;
2126  my ($dev, @pci_list);
2127
2128  opendir(local *DEVICES, "$devices")
2129    or die "$devices: $!";
2130
2131  while (defined($dev = readdir(DEVICES))) {
2132    my %record;
2133    next unless $dev =~
2134      m/^(?:([\da-f]+):)?([\da-f]+):([\da-f]+)\.([\da-f]+)$/;
2135
2136    $record{domain} = hex $1;
2137    $record{bus} = hex $2;
2138    $record{slot} = hex $3;
2139    $record{func} = hex $4;
2140
2141    $record{vendid} = oct sysfs_device_attribute("$devices/$dev", "vendor");
2142    $record{devid} = oct sysfs_device_attribute("$devices/$dev", "device");
2143    $record{class} = (oct sysfs_device_attribute("$devices/$dev", "class"))
2144                     >> 8;
2145
2146    push @pci_list, \%record;
2147  }
2148
2149  return \@pci_list;
2150}
2151
2152# This function returns a list of hashes. Each hash has some PCI information:
2153# 'bus', 'slot' and 'func' uniquely identify a PCI device in a computer;
2154# 'vendid' and 'devid' uniquely identify a type of device.
2155# This function is used when sysfs is not available (Linux 2.4).
2156sub read_proc_dev_pci
2157{
2158  my ($dfn, $vend, @pci_list);
2159  open(local *INPUTFILE, "/proc/bus/pci/devices")
2160    or die "/proc/bus/pci/devices: $!";
2161  local $_;
2162  while (<INPUTFILE>) {
2163    my %record;
2164    ($dfn, $vend) = map { hex } (split) [0..1];
2165    $record{bus} = $dfn >> 8;
2166    $record{slot} = ($dfn & 0xf8) >> 3;
2167    $record{func} = $dfn & 0x07;
2168    $record{vendid} = $vend >> 16;
2169    $record{devid} = $vend & 0xffff;
2170   
2171    push @pci_list, \%record;
2172  }
2173  return \@pci_list;
2174}
2175
2176sub initialize_proc_pci
2177{
2178  my $pci_list;
2179
2180  if (defined $sysfs_root) {
2181    $pci_list = read_sys_dev_pci("$sysfs_root/bus/pci/devices");
2182  } else {
2183    $pci_list = read_proc_dev_pci();
2184  }
2185
2186  # Note that we lose duplicate devices at this point, but we don't
2187  # really care. What matters to us is which unique devices are present,
2188  # not how many of each.
2189  %pci_list = map {
2190    sprintf("%04x:%04x", $_->{vendid}, $_->{devid}) => $_
2191  } @{$pci_list};
2192}
2193
2194#####################
2195# ADAPTER DETECTION #
2196#####################
2197
2198sub adapter_pci_detection_sis_96x
2199{
2200  my $driver="";
2201
2202  # first, determine which driver if any...
2203  if (kernel_version_at_least(2,6,0)) {
2204    if (exists $pci_list{"1039:0016"}) {
2205      $driver = "i2c-sis96x";
2206    } elsif (exists $pci_list{"1039:0008"}) {
2207      $driver = "i2c-sis5595";
2208    }
2209  } elsif (kernel_version_at_least(2,4,0)) {
2210    if (exists $pci_list{"1039:0008"}) {
2211      if ((exists $pci_list{"1039:0645"}) ||
2212          (exists $pci_list{"1039:0646"}) ||
2213          (exists $pci_list{"1039:0648"}) ||
2214          (exists $pci_list{"1039:0650"}) ||
2215          (exists $pci_list{"1039:0651"}) ||
2216          (exists $pci_list{"1039:0655"}) ||
2217          (exists $pci_list{"1039:0661"}) ||
2218          (exists $pci_list{"1039:0735"}) ||
2219          (exists $pci_list{"1039:0745"}) ||
2220          (exists $pci_list{"1039:0746"})) {
2221        $driver = "i2c-sis645";
2222      } else {
2223        $driver = "i2c-sis5595";
2224      }
2225    } elsif ((exists $pci_list{"1039:0016"}) ||
2226             (exists $pci_list{"1039:0018"})) {
2227      $driver = "i2c-sis645";
2228    }
2229  }
2230
2231  # then, add the appropriate entries to @pci_adapters
2232  if ($driver eq "i2c-sis5595") {
2233    push @pci_adapters, @pci_adapters_sis5595;
2234  } elsif ($driver eq "i2c-sis645") {
2235    push @pci_adapters, @pci_adapters_sis645;
2236  } elsif ($driver eq "i2c-sis96x") {
2237    push @pci_adapters, @pci_adapters_sis96x;
2238  }
2239}
2240
2241# Build and return a PCI device's bus ID
2242sub pci_busid($)
2243{
2244  my $device = shift;
2245  my $busid;
2246
2247  $busid = sprintf("\%02x:\%02x.\%x",
2248                   $device->{bus}, $device->{slot}, $device->{func});
2249  $busid = sprintf("\%04x:", $device->{domain}) . $busid
2250    if defined $device->{domain};
2251
2252  return $busid;
2253}
2254
2255sub adapter_pci_detection
2256{
2257  my ($key, $device, $try, @res, %smbus);
2258  print "Probing for PCI bus adapters...\n";
2259
2260  # Custom detection routine for some SiS chipsets
2261  adapter_pci_detection_sis_96x();
2262
2263  # Build a list of detected SMBus devices
2264  foreach $key (keys %pci_list) {
2265    $device = $pci_list{$key};
2266    $smbus{$key}++
2267      if exists $device->{class} && $device->{class} == 0x0c05; # SMBus
2268  }
2269
2270  # Loop over the known I2C/SMBus adapters
2271  foreach $try (@pci_adapters) {
2272    $key = sprintf("%04x:%04x", $try->{vendid}, $try->{devid});
2273    if (exists $pci_list{$key}) {
2274        $device = $pci_list{$key};
2275        printf "Use driver `\%s' for device \%s: \%s\n",
2276               $try->{driver}, pci_busid($device), $try->{procid};
2277        if ($try->{driver} eq "to-be-tested") {
2278          print "\nWe are currently looking for testers for this adapter!\n".
2279                "Please check http://www.lm-sensors.org/wiki/Devices\n".
2280                "and/or contact us if you want to help.\n\n";
2281          print "Continue... ";
2282          <STDIN>;
2283          print "\n";
2284        }
2285        push @res,$try->{driver};
2286
2287        # Delete from detected SMBus device list
2288        delete $smbus{$key};
2289    }
2290  }
2291
2292  # Now see if there are unknown SMBus devices left
2293  foreach $key (keys %smbus) {
2294    $device = $pci_list{$key};
2295    printf "Found unknown SMBus adapter \%04x:\%04x at \%s.\n",
2296           $device->{vendid}, $device->{devid}, pci_busid($device);
2297  }
2298 
2299  if (! @res) {
2300    print "Sorry, no known PCI bus adapters found.\n";
2301  }
2302  return @res;
2303}
2304
2305# $_[0]: Adapter description as found in /proc/bus/i2c
2306sub find_adapter_driver
2307{
2308  my $adapter;
2309  for $adapter (@pci_adapters) {
2310    return $adapter->{driver}
2311      if (exists $adapter->{match} && $_[0] =~ $adapter->{match});
2312  }
2313  return "UNKNOWN";
2314}
2315
2316#############################
2317# I2C AND SMBUS /DEV ACCESS #
2318#############################
2319
2320# This should really go into a separate module/package.
2321
2322# These are copied from <linux/i2c-dev.h>
2323
2324use constant IOCTL_I2C_SLAVE    => 0x0703;
2325use constant IOCTL_I2C_FUNCS    => 0x0705;
2326use constant IOCTL_I2C_SMBUS    => 0x0720;
2327
2328use constant SMBUS_READ         => 1;
2329use constant SMBUS_WRITE        => 0;
2330
2331use constant SMBUS_QUICK        => 0;
2332use constant SMBUS_BYTE         => 1;
2333use constant SMBUS_BYTE_DATA    => 2;
2334use constant SMBUS_WORD_DATA    => 3;
2335
2336use constant I2C_FUNC_SMBUS_QUICK       => 0x00010000;
2337use constant I2C_FUNC_SMBUS_READ_BYTE   => 0x00020000;
2338
2339# Get the i2c adapter's functionalities
2340# $_[0]: Reference to an opened filehandle
2341# Returns: -1 on failure, functionality bitfield on success.
2342sub i2c_get_funcs($)
2343{
2344  my $file = shift;
2345  my $funcs;
2346
2347  ioctl $file, IOCTL_I2C_FUNCS, $funcs='' or return -1;
2348  $funcs = unpack "L", $funcs;
2349
2350  return $funcs;
2351}
2352
2353# Select the device to communicate with through its address.
2354# $_[0]: Reference to an opened filehandle
2355# $_[1]: Address to select
2356# Returns: 0 on failure, 1 on success.
2357sub i2c_set_slave_addr
2358{
2359  my ($file,$addr) = @_;
2360  ioctl $file, IOCTL_I2C_SLAVE, $addr or return 0;
2361  return 1;
2362}
2363
2364# i2c_smbus_access is based upon the corresponding C function (see
2365# <linux/i2c-dev.h>). You should not need to call this directly.
2366# Exact calling conventions are intricate; read i2c-dev.c if you really need
2367# to know.
2368# $_[0]: Reference to an opened filehandle
2369# $_[1]: SMBUS_READ for reading, SMBUS_WRITE for writing
2370# $_[2]: Command (usually register number)
2371# $_[3]: Transaction kind (SMBUS_BYTE, SMBUS_BYTE_DATA, etc.)
2372# $_[4]: Reference to an array used for input/output of data
2373# Returns: 0 on failure, 1 on success.
2374# Note that we need to get back to Integer boundaries through the 'x2'
2375# in the pack. This is very compiler-dependent; I wish there was some other
2376# way to do this.
2377sub i2c_smbus_access
2378{
2379  my ($file,$read_write,$command,$size,$data) = @_;
2380  my $data_array = pack "C32", @$data;
2381  my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
2382  ioctl $file, IOCTL_I2C_SMBUS, $ioctl_data or return 0;
2383  @{$_[4]} = unpack "C32",$data_array;
2384  return 1;
2385}
2386
2387# $_[0]: Reference to an opened filehandle
2388# $_[1]: Either 0 or 1
2389# Returns: -1 on failure, the 0 on success.
2390sub i2c_smbus_write_quick
2391{
2392  my ($file,$value) = @_;
2393  my @data;
2394  i2c_smbus_access $file, $value, 0, SMBUS_QUICK, \@data
2395         or return -1;
2396  return 0;
2397}
2398
2399# $_[0]: Reference to an opened filehandle
2400# Returns: -1 on failure, the read byte on success.
2401sub i2c_smbus_read_byte
2402{
2403  my ($file) = @_;
2404  my @data;
2405  i2c_smbus_access $file, SMBUS_READ, 0, SMBUS_BYTE, \@data
2406         or return -1;
2407  return $data[0];
2408}
2409
2410# $_[0]: Reference to an opened filehandle
2411# $_[1]: Command byte (usually register number)
2412# Returns: -1 on failure, the read byte on success.
2413sub i2c_smbus_read_byte_data
2414{
2415  my ($file,$command) = @_;
2416  my @data;
2417  i2c_smbus_access $file, SMBUS_READ, $command, SMBUS_BYTE_DATA, \@data
2418         or return -1;
2419  return $data[0];
2420}
2421 
2422# $_[0]: Reference to an opened filehandle
2423# $_[1]: Command byte (usually register number)
2424# Returns: -1 on failure, the read word on success.
2425# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2426# this.
2427sub i2c_smbus_read_word_data
2428{
2429  my ($file,$command) = @_;
2430  my @data;
2431  i2c_smbus_access $file, SMBUS_READ, $command, SMBUS_WORD_DATA, \@data
2432         or return -1;
2433  return $data[0] + 256 * $data[1];
2434}
2435
2436# $_[0]: Reference to an opened filehandle
2437# $_[1]: Address
2438# $_[2]: Functionalities of this i2c adapter
2439# Returns: 1 on successful probing, 0 else.
2440# This function is meant to prevent AT24RF08 corruption and write-only
2441# chips locks. This is done by choosing the best probing method depending
2442# on the address range.
2443sub i2c_probe($$$)
2444{
2445  my ($file, $addr, $funcs) = @_;
2446  my $data = [];
2447  if (($addr >= 0x50 && $addr <= 0x5F)
2448   || ($addr >= 0x30 && $addr <= 0x37)) {
2449    # This covers all EEPROMs we know of, including page protection addresses.
2450    # Note that some page protection addresses will not reveal themselves with
2451    # this, because they ack on write only, but this is probably better since
2452    # some EEPROMs write-protect themselves permanently on almost any write to
2453    # their page protection address.
2454    return 0 unless ($funcs & I2C_FUNC_SMBUS_READ_BYTE);
2455    return i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE, $data);
2456  } else {
2457    return 0 unless ($funcs & I2C_FUNC_SMBUS_QUICK);
2458    return i2c_smbus_access($file, SMBUS_WRITE, 0, SMBUS_QUICK, $data);
2459  }
2460}
2461
2462####################
2463# ADAPTER SCANNING #
2464####################
2465
2466use vars qw(@chips_detected);
2467
2468# We will build a complicated structure @chips_detected here, being:
2469# A list of
2470#  references to hashes
2471#    with field 'driver', being a string with the driver name for this chip;
2472#    with field 'detected'
2473#      being a reference to a list of
2474#        references to hashes of type 'detect_data';
2475#    with field 'misdetected'
2476#      being a reference to a list of
2477#        references to hashes of type 'detect_data'
2478
2479# Type detect_data:
2480# A hash
2481#   with field 'i2c_adap' containing an adapter string as appearing
2482#        in /proc/bus/i2c (if this is an I2C detection)
2483#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
2484#       adapter (if this is an I2C detection)
2485#  with field 'i2c_driver', containing the driver name for this adapter
2486#       (if this is an I2C detection)
2487#  with field 'i2c_addr', containing the I2C address of the detection;
2488#       (if this is an I2C detection)
2489#  with field 'i2c_sub_addrs', containing a reference to a list of
2490#       other I2C addresses (if this is an I2C detection)
2491#  with field 'isa_addr' containing the ISA address this chip is on
2492#       (if this is an ISA detection)
2493#  with field 'conf', containing the confidence level of this detection
2494#  with field 'chipname', containing the chip name
2495
2496# This adds a detection to the above structure. We do no alias detection
2497# here; so you should do ISA detections *after* all I2C detections.
2498# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
2499# In all normal cases, it should be all right.
2500# $_[0]: chip driver
2501# $_[1]: reference to data hash
2502# Returns: Nothing
2503sub add_i2c_to_chips_detected
2504{
2505  my ($chipdriver,$datahash) = @_;
2506  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2507      $main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs,
2508      $do_not_add);
2509
2510  # First determine where the hash has to be added.
2511  for ($i = 0; $i < @chips_detected; $i++) {
2512    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2513  }
2514  if ($i == @chips_detected) {
2515    push @chips_detected, { driver => $chipdriver,
2516                            detected => [],
2517                            misdetected => [] };
2518  }
2519  $new_detected_ref = $chips_detected[$i]->{detected};
2520  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2521
2522  # Find out whether our new entry should go into the detected or the
2523  # misdetected list. We compare all i2c addresses; if at least one matches,
2524  # but our conf value is lower, we assume this is a misdetect.
2525  @hash_addrs = ($datahash->{i2c_addr});
2526  push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
2527       if exists $datahash->{i2c_sub_addrs};
2528  $put_in_detected = 1;
2529  $do_not_add = 0;
2530  FIND_LOOP:
2531  foreach $main_entry (@chips_detected) {
2532    foreach $detected_entry (@{$main_entry->{detected}}) {
2533      @entry_addrs = ($detected_entry->{i2c_addr});
2534      push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
2535               if exists $detected_entry->{i2c_sub_addrs};
2536      if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
2537          any_list_match \@entry_addrs, \@hash_addrs) {
2538        if ($detected_entry->{conf} >= $datahash->{conf}) {
2539          $put_in_detected = 0;
2540        }
2541        if ($chipdriver eq $main_entry->{driver}) {
2542          $do_not_add = 1;
2543        }
2544        last FIND_LOOP;
2545      }
2546    }
2547  }
2548
2549  if ($put_in_detected) {
2550    # Here, we move all entries from detected to misdetected which
2551    # match at least in one main or sub address. This may not be the
2552    # best idea to do, as it may remove detections without replacing
2553    # them with second-best ones. Too bad.
2554    # (Khali 2003-09-13) If the driver is the same, the "misdetected"
2555    # entry is simply deleted; failing to do so cause the configuration
2556    # lines generated later to look very confusing (the driver will
2557    # be told to ignore valid addresses).
2558    @hash_addrs = ($datahash->{i2c_addr});
2559    push @hash_addrs, @{$datahash->{i2c_sub_addrs}} 
2560         if exists $datahash->{i2c_sub_addrs};
2561    foreach $main_entry (@chips_detected) {
2562      $detected_ref = $main_entry->{detected};
2563      $misdetected_ref = $main_entry->{misdetected};
2564      for ($i = @$detected_ref-1; $i >=0; $i--) {
2565        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
2566        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
2567             if exists $detected_ref->[$i]->{i2c_sub_addrs};
2568        if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} and
2569            any_list_match \@entry_addrs, \@hash_addrs) {
2570          push @$misdetected_ref,$detected_ref->[$i]
2571            unless $chipdriver eq $main_entry->{driver};
2572          splice @$detected_ref, $i, 1;
2573        }
2574      }
2575    }
2576
2577    # Now add the new entry to detected
2578    push @$new_detected_ref, $datahash;
2579  } else {
2580    # No hard work here
2581    push @$new_misdetected_ref, $datahash
2582      unless $do_not_add;
2583  }
2584}
2585
2586# This adds a detection to the above structure. We also do alias detection
2587# here; so you should do ISA detections *after* all I2C detections.
2588# $_[0]: alias detection function
2589# $_[1]: chip driver
2590# $_[2]: reference to data hash
2591# Returns: 0 if it is not an alias, datahash reference if it is.
2592sub add_isa_to_chips_detected
2593{
2594  my ($alias_detect,$chipdriver,$datahash) = @_;
2595  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2596      $main_entry,$isalias);
2597
2598  # First determine where the hash has to be added.
2599  $isalias=0;
2600  for ($i = 0; $i < @chips_detected; $i++) {
2601    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2602  }
2603  if ($i == @chips_detected) {
2604    push @chips_detected, { driver => $chipdriver,
2605                            detected => [],
2606                            misdetected => [] };
2607  }
2608  $new_detected_ref = $chips_detected[$i]->{detected};
2609  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2610
2611  # Now, we are looking for aliases. An alias can only be the same chiptype.
2612  # If an alias is found in the misdetected list, we add the new information
2613  # and terminate this function. If it is found in the detected list, we
2614  # still have to check whether another chip has claimed this ISA address.
2615  # So we remove the old entry from the detected list and put it in datahash.
2616
2617  # Misdetected alias detection:
2618  for ($i = 0; $i < @$new_misdetected_ref; $i++) {
2619    if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
2620        not exists $new_misdetected_ref->[$i]->{isa_addr} and
2621        defined $alias_detect and
2622        $new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2623      open(local *FILE, "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}") or
2624        print("Can't open $dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2625        next;
2626      binmode FILE;
2627      i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{i2c_addr} or
2628           print("Can't set I2C address for ",
2629                 "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2630           next;
2631      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2632                          $new_misdetected_ref->[$i]->{i2c_addr})) {
2633        $new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2634        return $new_misdetected_ref->[$i]; 
2635      }
2636    }
2637  }
2638
2639  # Detected alias detection:
2640  for ($i = 0; $i < @$new_detected_ref; $i++) {
2641    if (exists $new_detected_ref->[$i]->{i2c_addr} and
2642        not exists $new_detected_ref->[$i]->{isa_addr} and
2643        defined $alias_detect and
2644        $new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2645      open(local *FILE, "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}") or
2646        print("Can't open $dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2647        next;
2648      binmode FILE;
2649      i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{i2c_addr} or
2650           print("Can't set I2C address for ",
2651                 "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2652           next;
2653      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2654                          $new_detected_ref->[$i]->{i2c_addr})) {
2655        $new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2656        ($datahash) = splice (@$new_detected_ref, $i, 1);
2657        $isalias=1;
2658        last;
2659      }
2660    }
2661  }
2662
2663
2664  # Find out whether our new entry should go into the detected or the
2665  # misdetected list. We only compare main isa_addr here, of course.
2666  # (Khali 2004-05-12) If the driver is the same, the "misdetected"
2667  # entry is simply deleted; same we do for I2C chips.
2668  foreach $main_entry (@chips_detected) {
2669    $detected_ref = $main_entry->{detected};
2670    $misdetected_ref = $main_entry->{misdetected};
2671    for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
2672      if (exists $detected_ref->[$i]->{isa_addr} and
2673          $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
2674        if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
2675          push @$new_misdetected_ref, $datahash
2676            unless $main_entry->{driver} eq $chipdriver;
2677        } else {
2678          push @$misdetected_ref,$detected_ref->[$i]
2679            unless $main_entry->{driver} eq $chipdriver;
2680          splice @$detected_ref, $i,1;
2681          push @$new_detected_ref, $datahash;
2682        }
2683        if ($isalias) {
2684          return $datahash;
2685        } else {
2686          return 0;
2687        }
2688      }
2689    }
2690  }
2691
2692  # Not found? OK, put it in the detected list
2693  push @$new_detected_ref, $datahash;
2694  if ($isalias) {
2695    return $datahash;
2696  } else {
2697    return 0;
2698  }
2699}
2700
2701# $_[0]: The number of the adapter to scan
2702# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
2703# $_[2]: The driver of the adapter
2704# @_[3]: Addresses not to scan (array reference)
2705sub scan_adapter
2706{
2707  my ($adapter_nr, $adapter_name, $adapter_driver, $not_to_scan) = @_;
2708  my ($funcs, $chip, $addr, $conf, @chips, $new_hash, $other_addr);
2709
2710  # As we modify it, we need a copy
2711  my @not_to_scan = @$not_to_scan;
2712
2713  open(local *FILE, "$dev_i2c$adapter_nr") or 
2714    (print "Can't open $dev_i2c$adapter_nr\n"), return;
2715  binmode FILE;
2716
2717  # Can we probe this adapter?
2718  $funcs = i2c_get_funcs(\*FILE);
2719  if ($funcs < 0) {
2720    print "Adapter failed to provide its functionalities, skipping.\n";
2721    return;
2722  }
2723  if (!($funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) {
2724    print "Adapter cannot be probed, skipping.\n";
2725    return;
2726  }
2727  if (~$funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE)) {
2728    print "Adapter doesn't support all probing functions.\n",
2729          "Some addresses won't be probed.\n";
2730  }
2731
2732  # Now scan each address in turn
2733  foreach $addr (0x03..0x77) {
2734    # As the not_to_scan list is sorted, we can check it fast
2735    if (@not_to_scan and $not_to_scan[0] == $addr) {
2736      shift @not_to_scan;
2737      next;
2738    }
2739
2740    if (!i2c_set_slave_addr(\*FILE, $addr)) {
2741      # If the address is busy, in Linux 2.6 we can find out which driver
2742      # is using it, and we assume it is the right one. In Linux 2.4 we
2743      # just give up and warn the user.
2744      my ($device, $driver);
2745      if (defined($sysfs_root)) {
2746        $device = sprintf("$sysfs_root/bus/i2c/devices/\%d-\%04x",
2747                             $adapter_nr, $addr);
2748        $driver = sysfs_device_driver($device);
2749      }
2750      if (defined($driver)) {
2751        $new_hash = {
2752          conf => 6, # Arbitrary confidence
2753          i2c_addr => $addr,
2754          chipname => sysfs_device_attribute($device, "name") || "unknown",
2755          i2c_adap => $adapter_name,
2756          i2c_driver => $adapter_driver,
2757          i2c_devnr => $adapter_nr,
2758        };
2759
2760        printf "Client found at address 0x\%02x\n", $addr;
2761        printf "Handled by driver `\%s' (already loaded), chip type `\%s'\n",
2762               $driver, $new_hash->{chipname};
2763
2764        # Only add it to the list if this is something we would have
2765        # detected, else we end up with random i2c chip drivers listed
2766        # (for example media/video drivers.)
2767        if (exists $modules_supported{$driver}) {
2768          add_i2c_to_chips_detected($driver, $new_hash);
2769        } else {
2770          print "    (note: this is probably NOT a sensor chip!)\n";
2771        }   
2772      } else {
2773        printf("Client at address 0x%02x can not be probed - ".
2774               "unload all client drivers first!\n", $addr);
2775      }
2776      next;
2777    }
2778
2779    next unless i2c_probe(\*FILE, $addr, $funcs);
2780    printf "Client found at address 0x%02x\n",$addr;
2781
2782    foreach $chip (@chip_ids) {
2783      if (exists $chip->{i2c_addrs} and contains $addr, @{$chip->{i2c_addrs}}) {
2784        printf("\%-60s", sprintf("Probing for `\%s'... ", $chip->{name}));
2785        if (($conf,@chips) = &{$chip->{i2c_detect}} (\*FILE ,$addr)) {
2786          print "Success!\n",
2787                "    (confidence $conf, driver `$chip->{driver}')";
2788          if (@chips) {
2789            print ", other addresses:";
2790            @chips = sort @chips;
2791            foreach $other_addr (sort @chips) {
2792              printf(" 0x%02x",$other_addr);
2793            }
2794          }
2795          printf "\n";
2796          $new_hash = { conf => $conf,
2797                        i2c_addr => $addr,
2798                        chipname => $chip->{name},
2799                        i2c_adap => $adapter_name,
2800                        i2c_driver => $adapter_driver,
2801                        i2c_devnr => $adapter_nr,
2802                      };
2803          if (@chips) {
2804            my @chips_copy = @chips;
2805            $new_hash->{i2c_sub_addrs} = \@chips_copy;
2806          }
2807          add_i2c_to_chips_detected $chip->{driver}, $new_hash;
2808        } else {
2809          print "No\n";
2810        }
2811      }
2812    }
2813  }
2814}
2815
2816sub scan_isa_bus
2817{
2818  my ($chip,$addr,$conf);
2819  foreach $chip (@chip_ids) {
2820    next if not exists $chip->{isa_addrs} or not exists $chip->{isa_detect};
2821    foreach $addr (@{$chip->{isa_addrs}}) {
2822      printf("\%-60s", sprintf("Probing for `\%s'\%s... ", $chip->{name},
2823                               $addr ? sprintf(" at 0x\%x", $addr) : ''));
2824      $conf = &{$chip->{isa_detect}} ($addr);
2825      print("No\n"), next if not defined $conf;
2826      print "Success!\n";
2827      printf "    (confidence %d, driver `%s')\n", $conf, $chip->{driver};
2828      my $new_hash = { conf => $conf,
2829                       isa_addr => $addr,
2830                       chipname => $chip->{name}
2831                     };
2832      $new_hash = add_isa_to_chips_detected $chip->{alias_detect},$chip->{driver},
2833                                            $new_hash;
2834      if ($new_hash) {
2835        printf "    Alias of the chip on I2C bus `%s', address 0x%04x\n",
2836                        $new_hash->{i2c_adap},$new_hash->{i2c_addr};
2837      }
2838    }
2839  }
2840}
2841
2842use vars qw(%superio);
2843
2844%superio = (
2845  devidreg => 0x20,
2846  logdevreg => 0x07,
2847  actreg => 0x30,
2848  actmask => 0x01,
2849  basereg => 0x60,
2850);
2851
2852sub exit_superio
2853{
2854  my ($addrreg, $datareg) = @_;
2855
2856  # Some chips (SMSC, Winbond) want this
2857  outb($addrreg, 0xaa);
2858
2859  # Return to "Wait For Key" state (PNP-ISA spec)
2860  outb($addrreg, 0x02);
2861  outb($datareg, 0x02);
2862}
2863
2864# Guess if an unknown Super-I/O chip has sensors
2865sub guess_superio_ld($$$)
2866{
2867  my ($addrreg, $datareg, $typical_addr) = @_;
2868  my ($oldldn, $ldn, $addr);
2869
2870  # Save logical device number
2871  outb($addrreg, $superio{logdevreg});
2872  $oldldn = inb($datareg);
2873
2874  for ($ldn = 0; $ldn < 16; $ldn++) {
2875    # Select logical device
2876    outb($addrreg, $superio{logdevreg});
2877    outb($datareg, $ldn);
2878
2879    # Read base I/O address
2880    outb($addrreg, $superio{basereg});
2881    $addr = inb($datareg) << 8;
2882    outb($addrreg, $superio{basereg} + 1);
2883    $addr |= inb($datareg);
2884    next unless ($addr & 0xfff8) == $typical_addr;
2885
2886    printf "    (logical device \%X has address 0x\%x, could be sensors)\n",
2887           $ldn, $addr;
2888    last;
2889  }
2890
2891  # Be nice, restore original logical device
2892  outb($addrreg, $superio{logdevreg});
2893  outb($datareg, $oldldn);
2894}
2895
2896sub probe_superio($$$)
2897{
2898  my ($addrreg, $datareg, $chip) = @_;
2899  my ($val, $addr);
2900
2901  printf "\%-60s",  "Found `$chip->{name}'";
2902
2903  # Does it have hardware monitoring capabilities?
2904  if (!exists $chip->{driver}) {
2905    print "\n    (no information available)\n";
2906    return;
2907  }
2908  if ($chip->{driver} eq "not-a-sensor") {
2909    print "\n    (no hardware monitoring capabilities)\n";
2910    return;
2911  }
2912
2913  # Switch to the sensor logical device
2914  outb($addrreg, $superio{logdevreg});
2915  outb($datareg, $chip->{logdev});
2916
2917  # Check the activation register
2918  outb($addrreg, $superio{actreg});
2919  $val = inb($datareg);
2920  if (!($val & $superio{actmask})) {
2921    print "\n    (but not activated)\n";
2922    return;
2923  }
2924
2925  # Get the IO base register
2926  outb($addrreg, $superio{basereg});
2927  $addr = inb($datareg);
2928  outb($addrreg, $superio{basereg} + 1);
2929  $addr = ($addr << 8) | inb($datareg);
2930  if ($addr == 0) {
2931    print "\n    (but no address specified)\n";
2932    return;
2933  }
2934  print "Success!\n";
2935  printf "    (address 0x\%x, driver `%s')\n", $addr, $chip->{driver};
2936  my $new_hash = { conf => 9,
2937                   isa_addr => $addr,
2938                   chipname => $chip->{name}
2939                 };
2940  add_isa_to_chips_detected $chip->{alias_detect},$chip->{driver},
2941                                        $new_hash;
2942}
2943
2944# The following are taken from the PNP ISA spec (so it's supposed
2945# to be common to all Super I/0 chips):
2946#  devidreg: The device ID register(s)
2947#  logdevreg: The logical device register
2948#  actreg: The activation register within the logical device
2949#  actmask: The activation bit in the activation register
2950#  basereg: The I/O base register within the logical device
2951sub scan_superio
2952{
2953  my ($addrreg, $datareg) = @_;
2954  my ($val, $found);
2955
2956  printf("Probing for Super-I/O at 0x\%x/0x\%x\n", $addrreg, $datareg);
2957
2958  FAMILY:
2959  foreach my $family (@superio_ids) {
2960    printf("\%-60s", "Trying family `$family->{family}'... ");
2961# write the password
2962    foreach $val (@{$family->{enter}->{$addrreg}}) {
2963      outb($addrreg, $val);
2964    }
2965# did it work?
2966    outb($addrreg, $superio{devidreg});
2967    $val = inb($datareg);
2968    outb($addrreg, $superio{devidreg} + 1);
2969    $val = ($val << 8) | inb($datareg);
2970    if ($val == 0x0000 || $val == 0xffff) {
2971      print "No\n";
2972      next FAMILY;
2973    }
2974    print "Yes\n";
2975
2976    $found = 0;
2977    foreach my $chip (@{$family->{chips}}) {
2978      if (($chip->{devid} > 0xff && ($val & ($chip->{devid_mask} || 0xffff)) == $chip->{devid})
2979       || ($chip->{devid} <= 0xff && ($val >> 8) == $chip->{devid})) {
2980        probe_superio($addrreg, $datareg, $chip);
2981        $found++;
2982      }
2983    }
2984
2985    if (!$found) {
2986      printf("Found unknown chip with ID 0x%04x\n", $val);
2987      # Guess if a logical device could correspond to sensors
2988      guess_superio_ld($addrreg, $datareg, $family->{guess})
2989        if defined $family->{guess};
2990    }
2991
2992    exit_superio($addrreg, $datareg);
2993  }
2994}
2995
2996
2997##################
2998# CHIP DETECTION #
2999##################
3000
3001# This routine allows you to select which chips are optionally added to the
3002# chip detection list. The most common use is to allow for different chip
3003# detection/drivers based on different linux kernels
3004# This routine follows the pattern of the SiS adapter special cases
3005sub chip_special_cases
3006{
3007        # Based on the kernel, add the appropriate chip structure to the
3008        # chip_ids detection list
3009        if (kernel_version_at_least(2, 6, 0)) {
3010                push @chip_ids, $chip_kern26_w83791d;
3011        } else {
3012                push @chip_ids, $chip_kern24_w83791d;
3013        }
3014}
3015
3016# Each function returns a confidence value. The higher this value, the more
3017# sure we are about this chip. A Winbond W83781D, for example, will be
3018# detected as a LM78 too; but as the Winbond detection has a higher confidence
3019# factor, you should identify it as a Winbond.
3020
3021# Each function returns a list. The first element is the confidence value;
3022# Each element after it is an SMBus address. In this way, we can detect
3023# chips with several SMBus addresses. The SMBus address for which the
3024# function was called is never returned.
3025
3026# If there are devices which get confused if they are only read from, then
3027# this program will surely confuse them. But we guarantee never to write to
3028# any of these devices.
3029
3030
3031# $_[0]: A reference to the file descriptor to access this chip.
3032#        We may assume an i2c_set_slave_addr was already done.
3033# $_[1]: Address
3034# Returns: undef if not detected, (7) if detected.
3035# Registers used: 0x58
3036sub mtp008_detect
3037{
3038  my ($file,$addr) = @_;
3039  return if (i2c_smbus_read_byte_data($file,0x58)) != 0xac;
3040  return (8);
3041}
3042 
3043# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3044# $_[1]: A reference to the file descriptor to access this chip.
3045#        We may assume an i2c_set_slave_addr was already done.
3046# $_[2]: Address
3047# Returns: undef if not detected, (6) if detected.
3048# Registers used:
3049#   0x40: Configuration
3050#   0x48: Full I2C Address
3051#   0x49: Device ID
3052# Note that this function is always called through a closure, so the
3053# arguments are shifted by one place.
3054sub lm78_detect
3055{
3056  my $reg;
3057  my ($chip,$file,$addr) = @_;
3058  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
3059  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
3060  $reg = i2c_smbus_read_byte_data($file,0x49);
3061  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
3062                    ($chip == 1 and $reg == 0x40) or
3063                    ($chip == 2 and ($reg & 0xfe) == 0xc0);
3064  return (6);
3065}
3066
3067# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3068# $_[1]: Address
3069# Returns: undef if not detected, 6 if detected.
3070# Note: Only address 0x290 is scanned at this moment.
3071sub lm78_isa_detect
3072{
3073  my ($chip,$addr) = @_ ;
3074  my $val = inb ($addr + 1);
3075  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
3076            inb ($addr + 7) != $val;
3077
3078  $val = inb($addr + 5) & 0x7f;
3079  outb($addr + 5, ~$val & 0xff);
3080  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
3081    outb($addr+5,$val);
3082    return;
3083  }
3084  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
3085  return unless (&$readproc(0x40) & 0x80) == 0x00;
3086  my $reg = &$readproc(0x49);
3087  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
3088                ($chip == 1 and $reg == 0x40) or
3089                ($chip == 2 and ($reg & 0xfe) == 0xc0);
3090
3091  # Explicitely prevent misdetection of Winbond chips
3092  $reg = &$readproc(0x4f);
3093  return if $reg == 0xa3 || $reg == 0x5c;
3094
3095  # Explicitely prevent misdetection of ITE chips
3096  $reg = &$readproc(0x58);
3097  return if $reg == 0x90;
3098
3099  return 6;
3100}
3101
3102
3103# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3104# $_[1]: ISA address
3105# $_[2]: I2C file handle
3106# $_[3]: I2C address
3107sub lm78_alias_detect
3108{
3109  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
3110  my $i;
3111  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
3112  return 0 unless &$readproc(0x48) == $i2c_addr;
3113  for ($i = 0x2b; $i <= 0x3d; $i ++) {
3114    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
3115  }
3116  return 1;
3117}
3118
3119# $_[0]: A reference to the file descriptor to access this chip.
3120#        We assume an i2c_set_slave_addr was already done.
3121# $_[1]: Address
3122# Returns: undef if not detected, 3 or 6 if detected;
3123#   6 means that the temperatures make sense;
3124#   3 means that the temperatures look strange;
3125# Registers used:
3126#   0x00: Temperature
3127#   0x01: Configuration
3128#   0x02: Hysteresis
3129#   0x03: Overtemperature Shutdown
3130#   0x04-0x07: No registers
3131# The first detection step is based on the fact that the LM75 has only
3132# four registers, and cycles addresses over 8-byte boundaries. We use the
3133# 0x04-0x07 addresses (unused) to improve the reliability. These are not
3134# real registers and will always return the last returned value. This isn't
3135# documented.
3136# Note that register 0x00 may change, so we can't use the modulo trick on it.
3137sub lm75_detect
3138{
3139  my $i;
3140  my ($file,$addr) = @_;
3141  my $cur = i2c_smbus_read_word_data($file,0x00);
3142  my $cur_varies = 0;
3143  my $conf = i2c_smbus_read_byte_data($file,0x01);
3144
3145  my $hyst = i2c_smbus_read_word_data($file,0x02);
3146  return if i2c_smbus_read_word_data($file,0x04) != $hyst;
3147  return if i2c_smbus_read_word_data($file,0x05) != $hyst;
3148  return if i2c_smbus_read_word_data($file,0x06) != $hyst;
3149  return if i2c_smbus_read_word_data($file,0x07) != $hyst;
3150
3151  my $os = i2c_smbus_read_word_data($file,0x03);
3152  return if i2c_smbus_read_word_data($file,0x04) != $os;
3153  return if i2c_smbus_read_word_data($file,0x05) != $os;
3154  return if i2c_smbus_read_word_data($file,0x06) != $os;
3155  return if i2c_smbus_read_word_data($file,0x07) != $os;
3156
3157  for ($i = 0x00; $i < 0xff; $i += 8) {
3158    return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf;
3159    return if i2c_smbus_read_word_data($file, $i + 0x02) != $hyst;
3160    return if i2c_smbus_read_word_data($file, $i + 0x04) != $hyst;
3161    return if i2c_smbus_read_word_data($file, $i + 0x05) != $hyst;
3162    return if i2c_smbus_read_word_data($file, $i + 0x06) != $hyst;
3163    return if i2c_smbus_read_word_data($file, $i + 0x07) != $hyst;
3164    return if i2c_smbus_read_word_data($file, $i + 0x03) != $os;
3165    return if i2c_smbus_read_word_data($file, $i + 0x04) != $os;
3166    return if i2c_smbus_read_word_data($file, $i + 0x05) != $os;
3167    return if i2c_smbus_read_word_data($file, $i + 0x06) != $os;
3168    return if i2c_smbus_read_word_data($file, $i + 0x07) != $os;
3169        $cur_varies = 1
3170      if (! $cur_varies) and
3171        i2c_smbus_read_word_data($file, $i) != $cur;
3172  }
3173
3174  # All registers hold the same value, obviously a misdetection
3175  return if (! $cur_varies) and $conf == ($cur & 0xff) and $cur == $hyst
3176    and $cur == $os;
3177
3178  $cur = swap_bytes($cur);
3179  $hyst = swap_bytes($hyst);
3180  $os = swap_bytes($os);
3181  # Unused bits
3182  return if ($conf & 0xe0);
3183
3184  $cur = $cur >> 8;
3185  $hyst = $hyst >> 8;
3186  $os = $os >> 8;
3187  # Most probable value ranges
3188  return 6 if $cur <= 100 and ($hyst >= 10 && $hyst <= 125)
3189    and ($os >= 20 && $os <= 127) and $hyst < $os;
3190  return 3;
3191}
3192
3193# $_[0]: A reference to the file descriptor to access this chip.
3194#        We assume an i2c_set_slave_addr was already done.
3195# $_[1]: Address
3196# Returns: undef if not detected, 3 or 6 if detected;
3197#   6 means that the temperatures make sense;
3198#   3 means that the temperatures look strange;
3199# Registers used:
3200#   0x00: Temperature
3201#   0x01: Configuration
3202#   0x02: Hysteresis
3203#   0x03: Overtemperature Shutdown
3204#   0x04: Low limit
3205#   0x05: High limit
3206#   0x04-0x07: No registers
3207# The first detection step is based on the fact that the LM77 has only
3208# six registers, and cycles addresses over 8-byte boundaries. We use the
3209# 0x06-0x07 addresses (unused) to improve the reliability. These are not
3210# real registers and will always return the last returned value. This isn't
3211# documented.
3212# Note that register 0x00 may change, so we can't use the modulo trick on it.
3213sub lm77_detect
3214{
3215  my $i;
3216  my ($file,$addr) = @_;
3217  my $cur = i2c_smbus_read_word_data($file,0x00);
3218  my $cur_varies = 0;
3219  my $conf = i2c_smbus_read_byte_data($file,0x01);
3220  my $hyst = i2c_smbus_read_word_data($file,0x02);
3221  my $os = i2c_smbus_read_word_data($file,0x03);
3222
3223  my $low = i2c_smbus_read_word_data($file,0x04);
3224  return if i2c_smbus_read_word_data($file,0x06) != $low;
3225  return if i2c_smbus_read_word_data($file,0x07) != $low;
3226
3227  my $high = i2c_smbus_read_word_data($file,0x05);
3228  return if i2c_smbus_read_word_data($file,0x06) != $high;
3229  return if i2c_smbus_read_word_data($file,0x07) != $high;
3230
3231  for ($i = 0x00; $i < 0xff; $i += 8) {
3232    return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf;
3233    return if i2c_smbus_read_word_data($file, $i + 0x02) != $hyst;
3234    return if i2c_smbus_read_word_data($file, $i + 0x03) != $os;
3235    return if i2c_smbus_read_word_data($file, $i + 0x04) != $low;
3236    return if i2c_smbus_read_word_data($file, $i + 0x06) != $low;
3237    return if i2c_smbus_read_word_data($file, $i + 0x07) != $low;
3238    return if i2c_smbus_read_word_data($file, $i + 0x05) != $high;
3239    return if i2c_smbus_read_word_data($file, $i + 0x06) != $high;
3240    return if i2c_smbus_read_word_data($file, $i + 0x07) != $high;
3241    $cur_varies = 1
3242      if (! $cur_varies) and
3243        i2c_smbus_read_word_data($file, $i) != $cur;
3244  }
3245
3246  # All registers hold the same value, obviously a misdetection
3247  return if (! $cur_varies) and $conf == ($cur & 0xff) and $cur == $hyst
3248    and $cur == $os and $cur == $low and $cur == $high;
3249
3250  $cur = swap_bytes($cur);
3251  $os = swap_bytes($os);
3252  $hyst = swap_bytes($hyst);
3253  $low = swap_bytes($low);
3254  $high = swap_bytes($high);
3255  # Unused bits
3256  return if ($conf & 0xe0)
3257    or (($cur >> 12) != 0 && ($cur >> 12) != 0xf)
3258    or (($hyst >> 12) != 0 && ($hyst >> 12) != 0xf)
3259    or (($os >> 12) != 0 && ($os >> 12) != 0xf)
3260    or (($low >> 12) != 0 && ($low >> 12) != 0xf)
3261    or (($high >> 12) != 0 && ($high >> 12) != 0xf);
3262
3263  $cur /= 16;
3264  $hyst /= 16;
3265  $os /= 16;
3266  $high /= 16;
3267  $low /= 16;
3268
3269  # Most probable value ranges
3270  return 6 if $cur <= 100 and $hyst <= 40
3271    and ($os >= 20 && $os <= 127) and ($high >= 20 && $high <= 127);
3272  return 3;
3273}
3274
3275# $_[0]: Chip to detect (0 = LM92, 1 = LM76, 2 = MAX6633/MAX6634/MAX6635)
3276# $_[1]: A reference to the file descriptor to access this chip.
3277#        We may assume an i2c_set_slave_addr was already done.
3278# $_[2]: Address
3279# Returns: undef if not detected, 2 or 4 if detected;
3280# Registers used:
3281#   0x01: Configuration (National Semiconductor only)
3282#   0x02: Hysteresis
3283#   0x03: Critical Temp
3284#   0x04: Low Limit
3285#   0x05: High Limit
3286#   0x07: Manufacturer ID (LM92 only)
3287# One detection step is based on the fact that the LM92 and clones have a
3288# limited number of registers, which cycle modulo 16 address values.
3289# Note that register 0x00 may change, so we can't use the modulo trick on it.
3290sub lm92_detect
3291{
3292  my ($chip, $file, $addr) = @_;
3293
3294  my $conf = i2c_smbus_read_byte_data($file, 0x01);
3295  my $hyst = i2c_smbus_read_word_data($file, 0x02);
3296  my $crit = i2c_smbus_read_word_data($file, 0x03);
3297  my $low = i2c_smbus_read_word_data($file, 0x04);
3298  my $high = i2c_smbus_read_word_data($file, 0x05);
3299
3300  return if $chip == 0
3301        and i2c_smbus_read_word_data($file, 0x07) != 0x0180;
3302 
3303  return if ($chip == 0 || $chip == 1)
3304        and ($conf & 0xE0);
3305
3306  for (my $i = 0; $i < 8; $i++) {
3307    return if i2c_smbus_read_byte_data($file, $i*16+0x01) != $conf;
3308    return if i2c_smbus_read_word_data($file, $i*16+0x02) != $hyst;
3309    return if i2c_smbus_read_word_data($file, $i*16+0x03) != $crit;
3310    return if i2c_smbus_read_word_data($file, $i*16+0x04) != $low;
3311    return if i2c_smbus_read_word_data($file, $i*16+0x05) != $high;
3312  }
3313 
3314  foreach my $temp ($hyst, $crit, $low, $high) {
3315    return if $chip == 2 and ($temp & 0x7F00);
3316    return if $chip != 2 and ($temp & 0x0700);
3317  }
3318
3319  return 4 if $chip == 0;
3320  return 2;
3321}
3322 
3323# $_[0]: A reference to the file descriptor to access this chip.
3324#        We may assume an i2c_set_slave_addr was already done.
3325# $_[1]: Address
3326# Returns: undef if not detected, 3 if detected
3327# Registers used:
3328#   0xAA: Temperature
3329#   0xA1: High limit
3330#   0xA2: Low limit
3331#   0xAC: Configuration
3332# Detection is weak. We check if bit 4 (NVB) is clear, because it is
3333# unlikely to be set (would mean that EEPROM is currently being accessed).
3334# Temperature checkings will hopefully prevent LM75 or other chips from
3335# being detected as a DS1621.
3336sub ds1621_detect
3337{
3338  my $i;
3339  my ($file,$addr) = @_;
3340  my $temp = i2c_smbus_read_word_data($file,0xAA);
3341  my $high = i2c_smbus_read_word_data($file,0xA1);
3342  my $low = i2c_smbus_read_word_data($file,0xA2);
3343  return if ($temp | $high | $low) & 0x7F00;
3344  my $conf = i2c_smbus_read_byte_data($file,0xAC);
3345  return if ($temp == 0 && $high == 0 && $low == 0 && $conf == 0);
3346  return 3 if ($conf & 0x10) == 0x00;
3347  return;
3348}
3349
3350# $_[0]: A reference to the file descriptor to access this chip.
3351#        We may assume an i2c_set_slave_addr was already done.
3352# $_[1]: Address
3353# Returns: undef if not detected, 1 to 3 if detected.
3354# Registers used:
3355#   0x00: Configuration register
3356#   0x02: Interrupt state register
3357#   0x2a-0x3d: Limits registers
3358# This one is easily misdetected since it doesn't provide identification
3359# registers. So we have to use some tricks:
3360#   - 6-bit addressing, so limits readings modulo 0x40 should be unchanged
3361#   - positive temperature limits
3362#   - limits order correctness
3363# Hopefully this should limit the rate of false positives, without increasing
3364# the rate of false negatives.
3365# Thanks to Lennard Klein for testing on a non-LM80 chip, which was
3366# previously misdetected, and isn't anymore. For reference, it scored
3367# a final confidence of 0, and changing from strict limit comparisons
3368# to loose comparisons did not change the score.
3369sub lm80_detect
3370{
3371  my ($i,$reg);
3372  my ($file,$addr) = @_;
3373
3374  return if (i2c_smbus_read_byte_data($file,0x00) & 0x80) != 0;
3375  return if (i2c_smbus_read_byte_data($file,0x02) & 0xc0) != 0;
3376
3377  for ($i = 0x2a; $i <= 0x3d; $i++) {
3378    $reg = i2c_smbus_read_byte_data($file,$i);
3379    return if i2c_smbus_read_byte_data($file,$i+0x40) != $reg;
3380    return if i2c_smbus_read_byte_data($file,$i+0x80) != $reg;
3381    return if i2c_smbus_read_byte_data($file,$i+0xc0) != $reg;
3382  }
3383 
3384  # Refine a bit by checking wether limits are in the correct order
3385  # (min<max for voltages, hyst<max for temperature). Since it is still
3386  # possible that the chip is an LM80 with limits not properly set,
3387  # a few "errors" are tolerated.
3388  my $confidence = 0;
3389  for ($i = 0x2a; $i <= 0x3a; $i++) {
3390    $confidence++
3391      if i2c_smbus_read_byte_data($file,$i) < i2c_smbus_read_byte_data($file,$i+1);
3392  }
3393  # hot temp<OS temp
3394  $confidence++
3395    if i2c_smbus_read_byte_data($file,0x38) < i2c_smbus_read_byte_data($file,0x3a);
3396
3397  # Negative temperature limits are unlikely.
3398  for ($i = 0x3a; $i <= 0x3d; $i++) {
3399    $confidence++ if (i2c_smbus_read_byte_data($file,$i) & 0x80) == 0;
3400  }
3401
3402  # $confidence is between 0 and 14
3403  $confidence = ($confidence >> 1) - 4;
3404  # $confidence is now between -4 and 3
3405
3406  return unless $confidence > 0;
3407
3408  return $confidence;
3409}
3410
3411# $_[0]: Chip to detect
3412#   (0 = LM82/LM83)
3413# $_[1]: A reference to the file descriptor to access this chip.
3414#        We may assume an i2c_set_slave_addr was already done.
3415# $_[2]: Address
3416# Returns: undef if not detected, 4 to 8 if detected.
3417# Registers used:
3418#   0x02: Status 1
3419#   0x03: Configuration
3420#   0x04: Company ID of LM84
3421#   0x35: Status 2
3422#   0xfe: Manufacturer ID
3423#   0xff: Chip ID / die revision
3424# We can use the LM84 Company ID register because the LM83 and the LM82 are
3425# compatible with the LM84.
3426# The LM83 chip ID is missing from the datasheet and was contributed by
3427# Magnus Forsstrom: 0x03.
3428# At least some revisions of the LM82 seem to be repackaged LM83, so they
3429# have the same chip ID, and temp2/temp4 will be stuck in "OPEN" state.
3430# For this reason, we don't even try to distinguish between both chips.
3431# Thanks to Ben Gardner for reporting.
3432sub lm83_detect
3433{
3434  my ($chip, $file) = @_;
3435  return if i2c_smbus_read_byte_data($file,0xfe) != 0x01;
3436  my $chipid = i2c_smbus_read_byte_data($file,0xff);
3437  return if $chipid != 0x01 && $chipid != 0x03;
3438
3439  my $confidence = 4;
3440  $confidence++
3441    if (i2c_smbus_read_byte_data($file,0x02) & 0xa8) == 0x00;
3442  $confidence++
3443    if (i2c_smbus_read_byte_data($file,0x03) & 0x41) == 0x00;
3444  $confidence++
3445    if i2c_smbus_read_byte_data($file,0x04) == 0x00;
3446  $confidence++
3447    if (i2c_smbus_read_byte_data($file,0x35) & 0x48) == 0x00;
3448
3449  return $confidence;
3450}
3451
3452# $_[0]: Chip to detect
3453#   (0 = LM90, 1=LM89/LM99, 2=LM86, 3=ADM1032, 4=MAX6657/MAX6658/MAX6659,
3454#    5 = ADT7461)
3455# $_[1]: A reference to the file descriptor to access this chip.
3456#        We may assume an i2c_set_slave_addr was already done.
3457# $_[2]: Address
3458# Returns: undef if not detected, 4, 6 or 8 if detected.
3459#   The Maxim chips have a low confidence value (4)
3460#   because they don't have a die revision register.
3461# Registers used:
3462#   0x03: Configuration
3463#   0x04: Conversion rate
3464#   0xfe: Manufacturer ID
3465#   0xff: Chip ID / die revision
3466sub lm90_detect
3467{
3468  my ($chip, $file, $addr) = @_;
3469  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
3470  my $cid = i2c_smbus_read_byte_data($file, 0xff);
3471  my $conf = i2c_smbus_read_byte_data($file, 0x03);
3472  my $rate = i2c_smbus_read_byte_data($file, 0x04);
3473
3474  if ($chip == 0) {
3475    return if ($conf & 0x2a) != 0;
3476    return if $rate > 0x09;
3477    return if $mid != 0x01;     # National Semiconductor
3478    return 8 if $cid == 0x21;   # LM90
3479    return 6 if ($cid & 0x0f) == 0x20;
3480  }
3481  if ($chip == 1) {
3482    return if ($conf & 0x2a) != 0;
3483    return if $rate > 0x09;
3484    return if $mid != 0x01;     # National Semiconductor
3485    return 8 if $addr == 0x4c and $cid == 0x31; # LM89/LM99
3486    return 8 if $addr == 0x4d and $cid == 0x34; # LM89-1/LM99-1
3487    return 6 if ($cid & 0x0f) == 0x30;
3488  }
3489  if ($chip == 2) {
3490    return if ($conf & 0x2a) != 0;
3491    return if $rate > 0x09;
3492    return if $mid != 0x01;     # National Semiconductor
3493    return 8 if $cid == 0x11;   # LM86
3494    return 6 if ($cid & 0xf0) == 0x10;
3495  }
3496  if ($chip == 3) {
3497    return if ($conf & 0x3f) != 0;
3498    return if $rate > 0x0a;
3499    return if $mid != 0x41;     # Analog Devices
3500    return 8 if ($cid & 0xf0) == 0x40; # ADM1032
3501  }
3502  if ($chip == 4) {
3503    return if ($conf & 0x1f) != ($mid & 0x0f); # No low nibble,
3504                                               # returns previous low nibble
3505    return if $rate > 0x09;
3506    return if $mid != 0x4d;     # Maxim
3507    return if $cid != 0x4d;     # No register, returns previous value
3508    return 4;
3509  }
3510  if ($chip == 5) {
3511    return if ($conf & 0x1b) != 0;
3512    return if $rate > 0x0a;
3513    return if $mid != 0x41;     # Analog Devices
3514    return 8 if $cid == 0x61;   # ADT7461
3515  }
3516  return;
3517}
3518
3519# $_[0]: Chip to detect
3520#   (1 = LM63, 2 = F75363SG)
3521# $_[1]: A reference to the file descriptor to access this chip.
3522#        We may assume an i2c_set_slave_addr was already done.
3523# $_[2]: Address (unused)
3524# Returns: undef if not detected, 8 if detected.
3525# Registers used:
3526#   0xfe: Manufacturer ID
3527#   0xff: Chip ID / die revision
3528#   0x03: Configuration (two or three unused bits)
3529#   0x16: Alert mask (two or three unused bits)
3530#   0x03-0x0e: Mirrored registers (five pairs)
3531sub lm63_detect
3532{
3533  my ($chip, $file, $addr) = @_;
3534
3535  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
3536  my $cid = i2c_smbus_read_byte_data($file, 0xff);
3537  my $conf = i2c_smbus_read_byte_data($file, 0x03);
3538  my $mask = i2c_smbus_read_byte_data($file, 0x16);
3539
3540  if ($chip == 1) {
3541    return if $mid != 0x01    # National Semiconductor
3542           || $cid != 0x41;   # LM63
3543    return if ($conf & 0x18) != 0x00
3544           || ($mask & 0xa4) != 0xa4;
3545  } elsif ($chip == 2) {
3546    return if $mid != 0x23    # Fintek
3547           || $cid != 0x20;   # F75363SG
3548    return if ($conf & 0x1a) != 0x00
3549           || ($mask & 0x84) != 0x00; 
3550  }
3551
3552  # For compatibility with the LM86, some registers are mirrored
3553  # to alternative locations
3554  return if $conf != i2c_smbus_read_byte_data($file, 0x09);
3555  foreach my $i (0x04, 0x05, 0x07, 0x08) {
3556    return if i2c_smbus_read_byte_data($file, $i)
3557           != i2c_smbus_read_byte_data($file, $i+6);
3558  }
3559
3560  return 8;
3561}
3562
3563# $_[0]: Chip to detect
3564#   (0 = ADM1029)
3565# $_[1]: A reference to the file descriptor to access this chip.
3566#        We may assume an i2c_set_slave_addr was already done.
3567# $_[2]: Address
3568# Returns: undef if not detected, 3 to 9 if detected.
3569# Registers used:
3570#   0x02, 0x03: Fan support
3571#   0x05: GPIO config
3572#   0x07, 0x08, 0x09: Fan config
3573#   0x0d: Manufacturer ID
3574#   0x0e: Chip ID / die revision
3575sub adm1029_detect
3576{
3577  my ($chip, $file, $addr) = @_;
3578  my $mid = i2c_smbus_read_byte_data($file, 0x0d);
3579  my $cid = i2c_smbus_read_byte_data($file, 0x0e);
3580  my $fansc = i2c_smbus_read_byte_data($file, 0x02);
3581  my $fanss = i2c_smbus_read_byte_data($file, 0x03);
3582  my $gpio = i2c_smbus_read_byte_data($file, 0x05);
3583  my $fanas = i2c_smbus_read_byte_data($file, 0x07);
3584  my $fanhps = i2c_smbus_read_byte_data($file, 0x08);
3585  my $fanfs = i2c_smbus_read_byte_data($file, 0x09);
3586  my $confidence = 3;
3587
3588  if ($chip == 0) {
3589    return if $mid != 0x41;     # Analog Devices
3590    $confidence++ if ($cid & 0xF0) == 0x00; # ADM1029
3591    $confidence+=2 if ($fansc & 0xFC) == 0x00
3592                   && ($fanss & 0xFC) == 0x00;
3593    $confidence+=2 if ($fanas & 0xFC) == 0x00
3594                   && ($fanhps & 0xFC) == 0x00
3595                   && ($fanfs & 0xFC) == 0x00;
3596    $confidence++ if ($gpio & 0x80) == 0x00;
3597    return $confidence;
3598  }
3599  return;
3600}
3601
3602# $_[0]: Chip to detect
3603#   (0 = ADM1030, 1=ADM1031)
3604# $_[1]: A reference to the file descriptor to access this chip.
3605#        We may assume an i2c_set_slave_addr was already done.
3606# $_[2]: Address
3607# Returns: undef if not detected, 3 to 7 (ADM1031) or 9 (ADM1030)
3608#          if detected.
3609# Registers used:
3610#   0x01: Config 2
3611#   0x03: Status 2
3612#   0x0d, 0x0e, 0x0f: Temperature offsets
3613#   0x22: Fan speed config
3614#   0x3d: Chip ID
3615#   0x3e: Manufacturer ID
3616#   0x3f: Die revision
3617sub adm1031_detect
3618{
3619  my ($chip, $file, $addr) = @_;
3620  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3621  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3622  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3623  my $conf2 = i2c_smbus_read_byte_data($file, 0x01);
3624  my $stat2 = i2c_smbus_read_byte_data($file, 0x03);
3625  my $fsc = i2c_smbus_read_byte_data($file, 0x22);
3626  my $lto = i2c_smbus_read_byte_data($file, 0x0d);
3627  my $r1to = i2c_smbus_read_byte_data($file, 0x0e);
3628  my $r2to = i2c_smbus_read_byte_data($file, 0x0f);
3629  my $confidence = 3;
3630
3631  if ($chip == 0) {
3632    return if $mid != 0x41;     # Analog Devices
3633    return if $cid != 0x30;     # ADM1030
3634    $confidence++ if ($drev & 0x70) == 0x00;
3635    $confidence++ if ($conf2 & 0x4A) == 0x00;
3636    $confidence++ if ($stat2 & 0x3F) == 0x00;
3637    $confidence++ if ($fsc & 0xF0) == 0x00;
3638    $confidence++ if ($lto & 0x70) == 0x00;
3639    $confidence++ if ($r1to & 0x70) == 0x00;
3640    return $confidence;
3641  }
3642  if ($chip == 1) {
3643    return if $mid != 0x41;     # Analog Devices
3644    return if $cid != 0x31;     # ADM1031
3645    $confidence++ if ($drev & 0x70) == 0x00;
3646    $confidence++ if ($lto & 0x70) == 0x00;
3647    $confidence++ if ($r1to & 0x70) == 0x00;
3648    $confidence++ if ($r2to & 0x70) == 0x00;
3649    return $confidence;
3650  }
3651  return;
3652}
3653
3654# $_[0]: Chip to detect
3655#   (0 = ADM1033, 1 = ADM1034)
3656# $_[1]: A reference to the file descriptor to access this chip.
3657# $_[2]: Address (unused)
3658# Returns: undef if not detected, 4 or 6 if detected.
3659# Registers used:
3660#   0x3d: Chip ID
3661#   0x3e: Manufacturer ID
3662#   0x3f: Die revision
3663sub adm1034_detect
3664{
3665  my ($chip, $file, $addr) = @_;
3666  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3667  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3668  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3669
3670  if ($chip == 0) {
3671    return if $mid != 0x41;     # Analog Devices
3672    return if $cid != 0x33;     # ADM1033
3673    return if ($drev & 0xf8) != 0x00;
3674    return 6 if $drev == 0x02;
3675    return 4;
3676  }
3677  if ($chip == 1) {
3678    return if $mid != 0x41;     # Analog Devices
3679    return if $cid != 0x34;     # ADM1034
3680    return if ($drev & 0xf8) != 0x00;
3681    return 6 if $drev == 0x02;
3682    return 4;
3683  }
3684  return
3685}
3686
3687# $_[0]: Chip to detect
3688#   (0 = ADT7467/ADT7468, 1 = ADT7476, 2 = ADT7462, 3 = ADT7466,
3689#    4 = ADT7470)
3690# $_[1]: A reference to the file descriptor to access this chip.
3691#        We may assume an i2c_set_slave_addr was already done.
3692# $_[2]: Address
3693# Returns: undef if not detected, 5 or 7 if detected.
3694# Registers used:
3695#   0x3d: Chip ID
3696#   0x3e: Manufacturer ID
3697#   0x3f: Die revision
3698sub adt7467_detect
3699{
3700  my ($chip, $file, $addr) = @_;
3701  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3702  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3703  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3704
3705  if ($chip == 0) {
3706    return if $mid != 0x41;     # Analog Devices
3707    return if $cid != 0x68;     # ADT7467
3708    return if ($drev & 0xf0) != 0x70;
3709    return 7 if ($drev == 0x71 || $drev == 0x72);
3710    return 5;
3711  }
3712  if ($chip == 1) {
3713    return if $mid != 0x41;     # Analog Devices
3714    return if $cid != 0x76;     # ADT7476
3715    return if ($drev & 0xf0) != 0x60;
3716    return 7 if ($drev == 0x69);
3717    return 5;
3718  }
3719  if ($chip == 2) {
3720    return if $mid != 0x41;     # Analog Devices
3721    return if $cid != 0x62;     # ADT7462
3722    return if ($drev & 0xf0) != 0x00;
3723    return 7 if ($drev == 0x04);
3724    return 5;
3725  }
3726  if ($chip == 3) {
3727    return if $mid != 0x41;     # Analog Devices
3728    return if $cid != 0x66;     # ADT7466
3729    return if ($drev & 0xf0) != 0x00;
3730    return 7 if ($drev == 0x02);
3731    return 5;
3732  }
3733  if ($chip == 4) {
3734    return if $mid != 0x41;     # Analog Devices
3735    return if $cid != 0x70;     # ADT7470
3736    return if ($drev & 0xf0) != 0x00;
3737    return 7 if ($drev == 0x00);
3738    return 5;
3739  }
3740  return
3741}
3742
3743# $_[0]: Chip to detect
3744#   (0 = ADT7473, 1 = ADT7475)
3745# $_[1]: A reference to the file descriptor to access this chip.
3746# $_[2]: Address (unused)
3747# Returns: undef if not detected, 5 if detected.
3748# Registers used:
3749#   0x3d: Chip ID
3750#   0x3e: Manufacturer ID
3751sub adt7473_detect
3752{
3753  my ($chip, $file, $addr) = @_;
3754  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3755  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3756
3757  if ($chip == 0) {
3758    return if $mid != 0x41;     # Analog Devices
3759    return if $cid != 0x73;     # ADT7473
3760    return 5;
3761  }
3762  if ($chip == 1) {
3763    return if $mid != 0x41;     # Analog Devices
3764    return if $cid != 0x75;     # ADT7475
3765    return 5;
3766  }
3767  return
3768}
3769
3770# $_[0]: Vendor to check for
3771#   (0x01 = National Semi, 0x41 = Analog Dev, 0x5c = SMSC)
3772# $_[1]: A reference to the file descriptor to access this chip.
3773# #_[2]: Base address.
3774# Returns: undef if not detected, (7) or (8) if detected.
3775# Registers used: 0x3e == Vendor register.
3776#                 0x3d == Device ID register (Analog Devices only).
3777#                 0x3f == Version/Stepping register.
3778# Constants used: 0x01 == National Semiconductor Vendor Id.
3779#                 0x41 == Analog Devices Vendor Id.
3780#                 0x5c == SMSC Vendor Id.
3781#                 0x60 == Version number. The lower 4 stepping
3782#                         bits are masked and ignored.
3783sub lm85_detect
3784{
3785  my ($vendor,$file,$addr) = @_;
3786  return if (i2c_smbus_read_byte_data($file,0x3e)) != $vendor ;
3787  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) != 0x60;
3788
3789  if ($vendor == 0x41) # Analog Devices
3790  {
3791    return if i2c_smbus_read_byte_data($file, 0x3d) != 0x27;
3792    return (8);
3793  }
3794
3795  return (7);
3796}
3797
3798# $_[0]: A reference to the file descriptor to access this chip.
3799#        We may assume an i2c_set_slave_addr was already done.
3800# $_[1]: Address
3801# Returns: undef if not detected, (7) if detected.
3802# Registers used: 0x3E, 0x3F
3803#        Assume lower 2 bits of reg 0x3F are for revisions.
3804sub lm87_detect
3805{
3806  my ($file,$addr) = @_;
3807  return if (i2c_smbus_read_byte_data($file,0x3e)) != 0x02;
3808  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xfc) != 0x04;
3809  return (7);
3810}
3811 
3812# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S,
3813#                        3 = W83627HF, 4 = AS99127F (rev.1),
3814#                        5 = AS99127F (rev.2), 6 = ASB100, 7 = W83791D,
3815#                        8 = W83792D, 9 = W83627EHF 10 = W83627DHG)
3816# $_[1]: A reference to the file descriptor to access this chip.
3817#        We may assume an i2c_set_slave_addr was already done.
3818# $_[2]: Address
3819# Returns: undef if not detected, (8,addr1,addr2) if detected, but only
3820#          if the LM75 chip emulation is enabled.
3821# Registers used:
3822#   0x48: Full I2C Address
3823#   0x4a: I2C addresses of emulated LM75 chips
3824#   0x4e: Vendor ID byte selection, and bank selection
3825#   0x4f: Vendor ID
3826#   0x58: Device ID (only when in bank 0)
3827# Note: Fails if the W8378xD is not in bank 0!
3828# Note: Detection overrules a previous LM78 detection
3829# Note: Asus chips do not have their I2C address at register 0x48?
3830#       AS99127F rev.1 and ASB100 have 0x00, confirmation wanted for
3831#       AS99127F rev.2.
3832sub w83781d_detect
3833{
3834  my ($reg1,$reg2,@res);
3835  my ($chip,$file,$addr) = @_;
3836
3837  return unless (i2c_smbus_read_byte_data($file,0x48) == $addr)
3838    or ($chip >= 4 && $chip <= 6);
3839
3840  $reg1 = i2c_smbus_read_byte_data($file,0x4e);
3841  $reg2 = i2c_smbus_read_byte_data($file,0x4f);
3842  if ($chip == 4) { # Asus AS99127F (rev.1)
3843    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or 
3844                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x12);
3845  } elsif ($chip == 6) { # Asus ASB100
3846    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0x94) or 
3847                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x06);
3848  } else { # Winbond and Asus AS99127F (rev.2)
3849    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
3850                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
3851  }
3852
3853  return unless ($reg1 & 0x07) == 0x00;
3854
3855  $reg1 = i2c_smbus_read_byte_data($file,0x58);
3856  return if $chip == 0 and ($reg1 != 0x10 && $reg1 != 0x11);
3857  return if $chip == 1 and  $reg1 != 0x30;
3858  return if $chip == 2 and  $reg1 != 0x40;
3859  return if $chip == 3 and  $reg1 != 0x21;
3860  return if $chip == 4 and  $reg1 != 0x31;
3861  return if $chip == 5 and  $reg1 != 0x31;
3862  return if $chip == 6 and  $reg1 != 0x31;
3863  return if $chip == 7 and  $reg1 != 0x71;
3864  return if $chip == 8 and  $reg1 != 0x7a;
3865  return if $chip == 9 and  $reg1 != 0xa1;
3866  return if $chip == 10 and  $reg1 != 0xa2;
3867  $reg1 = i2c_smbus_read_byte_data($file,0x4a);
3868  # Default address is 0x2d
3869  @res = ($addr != 0x2d) ? (7) : (8);
3870  return @res if $chip == 9; # No subclients
3871  push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08;
3872  push @res, (($reg1 & 0x70) >> 4) + 0x48 unless ($reg1 & 0x80 or $chip == 2);
3873  return @res;
3874}
3875 
3876# $_[0]: Chip to detect (0 = W83793)
3877# $_[1]: A reference to the file descriptor to access this chip.
3878# $_[2]: Address
3879# Returns: undef if not detected
3880#          6 if detected and bank different from 0
3881#          (8,addr1,addr2) if detected, band is 0 and LM75 chip emulation
3882#          is enabled
3883# Registers used:
3884#   0x0b: Full I2C Address
3885#   0x0c: I2C addresses of emulated LM75 chips
3886#   0x00: Vendor ID byte selection, and bank selection(Bank 0,1,2)
3887#   0x0d: Vendor ID(Bank 0,1,2)
3888#   0x0e: Device ID(Bank 0,1,2)
3889sub w83793_detect
3890{
3891  my ($bank, $reg, @res);
3892  my ($chip, $file, $addr) = @_;
3893
3894  $bank = i2c_smbus_read_byte_data($file, 0x00);
3895  $reg = i2c_smbus_read_byte_data($file, 0x0d);
3896
3897  return unless (($bank & 0x80) == 0x00 and $reg == 0xa3) or 
3898                (($bank & 0x80) == 0x80 and $reg == 0x5c);
3899
3900  $reg = i2c_smbus_read_byte_data($file, 0x0e);
3901  return if $chip == 0 and $reg != 0x7b;
3902
3903# If bank 0 is selected, we can do more checks
3904  return 6 unless ($bank & 0x07) == 0;
3905  $reg = i2c_smbus_read_byte_data($file, 0x0b);
3906  return unless ($reg == ($addr << 1));
3907
3908  $reg = i2c_smbus_read_byte_data($file, 0x0c);
3909  @res = (8);
3910  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08;
3911  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
3912  return @res;
3913}
3914
3915# $_[0]: A reference to the file descriptor to access this chip.
3916#        We assume an i2c_set_slave_addr was already done.
3917# $_[1]: Address
3918# Returns: undef if not detected, 3 if detected
3919# Registers used:
3920#   0x48: Full I2C Address
3921#   0x4e: Vendor ID byte selection
3922#   0x4f: Vendor ID
3923#   0x58: Device ID
3924# Note that the datasheet was useless and this detection routine
3925# is based on dumps we received from users. Also, the W83781SD is *NOT*
3926# a hardware monitoring chip as far as we know, but we still want to
3927# detect it so that people won't keep reporting it as an unknown chip
3928# we should investigate about.
3929sub w83791sd_detect
3930{
3931  my ($file, $addr) = @_;
3932  my ($reg1, $reg2);
3933
3934  return unless (i2c_smbus_read_byte_data($file, 0x48) == $addr);
3935
3936  $reg1 = i2c_smbus_read_byte_data($file, 0x4e);
3937  $reg2 = i2c_smbus_read_byte_data($file, 0x4f);
3938  return unless (!($reg1 & 0x80) && $reg2 == 0xa3)
3939             || (($reg1 & 0x80) && $reg2 == 0x5c);
3940
3941  $reg1 = i2c_smbus_read_byte_data($file, 0x58);
3942  return unless $reg1 == 0x72;
3943
3944  return 3;
3945}
3946
3947# $_[0]: Chip to detect (0 = ASM58, 1 = AS2K129R, 2 = ???)
3948# $_[1]: A reference to the file descriptor to access this chip
3949# $_[2]: Address (unused)
3950# Returns: undef if not detected, 5 if detected
3951# Registers used:
3952#   0x4e: Vendor ID high byte
3953#   0x4f: Vendor ID low byte
3954#   0x58: Device ID
3955# Note: The values were given by Alex van Kaam, we don't have datasheets
3956#       to confirm.
3957sub mozart_detect
3958{
3959  my ($vid,$dev);
3960  my ($chip,$file,$addr) = @_;
3961
3962  $vid = (i2c_smbus_read_byte_data($file,0x4e) << 8)
3963       +  i2c_smbus_read_byte_data($file,0x4f);
3964  $dev = i2c_smbus_read_byte_data($file,0x58);
3965
3966  return if ($chip == 0) and ($dev != 0x56 || $vid != 0x9436);
3967  return if ($chip == 1) and ($dev != 0x56 || $vid != 0x9406);
3968  return if ($chip == 2) and ($dev != 0x10 || $vid != 0x5ca3);
3969
3970  return 5;
3971}
3972
3973# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF,
3974#                        9 = W83627EHF 10 = W83627DHG)
3975# $_[1]: ISA address
3976# $_[2]: I2C file handle
3977# $_[3]: I2C address
3978sub w83781d_alias_detect
3979{
3980  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
3981  my $i;
3982  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
3983  return 0 unless &$readproc(0x48) == $i2c_addr;
3984  for ($i = 0x2b; $i <= 0x3d; $i ++) {
3985    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
3986  }
3987  return 1;
3988}
3989
3990# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF)
3991# $_[1]: Address
3992# Returns: undef if not detected, (8) if detected.
3993sub w83781d_isa_detect
3994{
3995  my ($chip,$addr) = @_ ;
3996  my ($reg1,$reg2);
3997  my $val = inb ($addr + 1);
3998  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
3999            inb ($addr + 7) != $val;
4000
4001  $val = inb($addr + 5) & 0x7f;
4002  outb($addr+5, ~$val & 0xff);
4003  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
4004    outb($addr+5,$val);
4005    return;
4006  }
4007
4008  my $read_proc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
4009  $reg1 = &$read_proc(0x4e);
4010  $reg2 = &$read_proc(0x4f);
4011  return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
4012                (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
4013  return unless ($reg1 & 0x07) == 0x00;
4014  $reg1 = &$read_proc(0x58);
4015  return if $chip == 0 and  ($reg1 & 0xfe) != 0x10;
4016  return if $chip == 1 and  ($reg1 & 0xfe) != 0x30;
4017  return if $chip == 3 and  ($reg1 & 0xfe) != 0x20;
4018
4019  return 8;
4020}
4021
4022# $_[0]: Chip to detect (0 = Revision 0x00, 1 = Revision 0x80)
4023# $_[1]: A reference to the file descriptor to access this chip.
4024#        We may assume an i2c_set_slave_addr was already done.
4025# $_[2]: Address
4026# Returns: undef if not detected, (6) if detected.
4027# Registers used:
4028#   0x00: Device ID
4029#   0x01: Revision ID
4030#   0x03: Configuration
4031# Mediocre detection
4032sub gl518sm_detect
4033{
4034  my $reg;
4035  my ($chip,$file,$addr) = @_;
4036  return unless i2c_smbus_read_byte_data($file,0x00) == 0x80;
4037  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
4038  $reg = i2c_smbus_read_byte_data($file,0x01);
4039  return unless ($chip == 0 and $reg == 0x00) or
4040                ($chip == 1 and $reg == 0x80);
4041  return (6);
4042}
4043
4044# $_[0]: A reference to the file descriptor to access this chip.
4045#        We may assume an i2c_set_slave_addr was already done.
4046# $_[1]: Address
4047# Returns: undef if not detected, (5) if detected.
4048# Registers used:
4049#   0x00: Device ID
4050#   0x01: Revision ID
4051#   0x03: Configuration
4052# Mediocre detection
4053sub gl520sm_detect
4054{
4055  my ($file,$addr) = @_;
4056  return unless i2c_smbus_read_byte_data($file,0x00) == 0x20;
4057  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
4058  # The line below must be better checked before I dare to use it.
4059  # return unless i2c_smbus_read_byte_data($file,0x01) == 0x00;
4060  return (5);
4061}
4062
4063# $_[0]: A reference to the file descriptor to access this chip.
4064#        We may assume an i2c_set_slave_addr was already done.
4065# $_[1]: Address
4066# Returns: undef if not detected, (5) if detected.
4067# Registers used:
4068#   0x00: Device ID
4069# Mediocre detection
4070sub gl525sm_detect
4071{
4072  my ($file,$addr) = @_;
4073  return unless i2c_smbus_read_byte_data($file,0x00) == 0x25;
4074  return (5);
4075}
4076
4077# $_[0]: Chip to detect (0 = ADM9240, 1 = DS1780, 2 = LM81)
4078# $_[1]: A reference to the file descriptor to access this chip.
4079#        We may assume an i2c_set_slave_addr was already done.
4080# $_[2]: Address
4081# Returns: undef if not detected, (7) if detected.
4082# Registers used:
4083#   0x3e: Company ID
4084#   0x40: Configuration
4085#   0x48: Full I2C Address
4086# Note: Detection overrules a previous LM78 detection
4087sub adm9240_detect
4088{
4089  my $reg;
4090  my ($chip, $file,$addr) = @_;
4091  $reg = i2c_smbus_read_byte_data($file,0x3e);
4092  return unless ($chip == 0 and $reg == 0x23) or
4093                ($chip == 1 and $reg == 0xda) or
4094                ($chip == 2 and $reg == 0x01);
4095  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4096  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
4097 
4098  return (7);
4099}
4100
4101# $_[0]: Chip to detect (0 = ADM1022, 1 = THMC50, 2 = ADM1028)
4102# $_[1]: A reference to the file descriptor to access this chip.
4103#        We may assume an i2c_set_slave_addr was already done.
4104# $_[2]: Address
4105# Returns: undef if not detected, (8) if detected.
4106# Registers used:
4107#   0x3e: Company ID
4108#   0x3f: Revision
4109#   0x40: Configuration
4110# Note: Detection overrules a previous LM78 or ADM9240 detection
4111sub adm1022_detect
4112{
4113  my $reg;
4114  my ($chip, $file,$addr) = @_;
4115  $reg = i2c_smbus_read_byte_data($file,0x3e);
4116  return unless ($chip == 0 and $reg == 0x41) or
4117                ($chip == 1 and $reg == 0x49) or
4118                ($chip == 2 and $reg == 0x41);
4119  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4120  $reg = i2c_smbus_read_byte_data($file, 0x3f);
4121  return unless ($reg & 0xc0) == 0xc0;
4122  return if $chip == 0 and ($reg & 0xc0) != 0xc0;
4123  return if $chip == 2 and ($reg & 0xc0) == 0xc0;
4124  return (8);
4125}
4126
4127# $_[0]: Chip to detect (0 = ADM1025, 1 = NE1619)
4128# $_[1]: A reference to the file descriptor to access this chip.
4129#        We may assume an i2c_set_slave_addr was already done.
4130# $_[2]: Address
4131# Returns: undef if not detected, (8) if detected.
4132# Registers used:
4133#   0x3e: Company ID
4134#   0x3f: Revision
4135#   0x40: Configuration
4136#   0x41: Status 1
4137#   0x42: Status 2
4138# Note: Detection overrules a previous LM78 or ADM9240 detection
4139sub adm1025_detect
4140{
4141  my $reg;
4142  my ($chip, $file,$addr) = @_;
4143
4144  $reg = i2c_smbus_read_byte_data($file,0x3e);
4145  return if ($chip == 0) and ($reg != 0x41);
4146  return if ($chip == 1) and ($reg != 0xA1);
4147
4148  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4149  return unless (i2c_smbus_read_byte_data($file,0x41) & 0xC0) == 0x00;
4150  return unless (i2c_smbus_read_byte_data($file,0x42) & 0xBC) == 0x00;
4151  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x20;
4152
4153  return (8);
4154}
4155
4156# $_[0]: Chip to detect (0 = ADM1026)
4157# $_[1]: A reference to the file descriptor to access this chip.
4158#        We may assume an i2c_set_slave_addr was already done.
4159# $_[2]: Address
4160# Returns: undef if not detected, (8) if detected.
4161# Registers used:
4162#   0x16: Company ID
4163#   0x17: Revision
4164sub adm1026_detect
4165{
4166  my $reg;
4167  my ($chip, $file,$addr) = @_;
4168  $reg = i2c_smbus_read_byte_data($file,0x16);
4169  return unless ($reg == 0x41);
4170  return unless (i2c_smbus_read_byte_data($file,0x17) & 0xf0) == 0x40;
4171  return (8);
4172}
4173
4174# $_[0]: Chip to detect (0 = ADM1024)
4175# $_[1]: A reference to the file descriptor to access this chip.
4176#        We may assume an i2c_set_slave_addr was already done.
4177# $_[2]: Address
4178# Returns: undef if not detected, (8) if detected.
4179# Registers used:
4180#   0x3e: Company ID
4181#   0x3f: Revision
4182#   0x40: Configuration
4183sub adm1024_detect
4184{
4185  my $reg;
4186  my ($chip, $file,$addr) = @_;
4187  $reg = i2c_smbus_read_byte_data($file,0x3e);
4188  return unless ($reg == 0x41);
4189  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4190  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x10;
4191  return (8);
4192}
4193
4194# $_[0]: Chip to detect
4195#   (0 = ADM1021, 1 = ADM1021A/ADM1023, 2 = MAX1617, 3 = MAX1617A, 4 = THMC10,
4196#    5 = LM84, 6 = GL523, 7 = MC1066)
4197# $_[1]: A reference to the file descriptor to access this chip.
4198#        We may assume an i2c_set_slave_addr was already done.
4199# $_[2]: Address
4200# Returns: undef if not detected, 3 if simply detected, 5 if detected and
4201#          manufacturer ID matches, 7 if detected and manufacturer ID and
4202#          revision match
4203# Registers used:
4204#   0x04: Company ID (LM84 only)
4205#   0xfe: Company ID (all but LM84 and MAX1617)
4206#   0xff: Revision (ADM1021, ADM1021A/ADM1023 and MAX1617A)
4207#   0x02: Status
4208#   0x03: Configuration
4209#   0x04: Conversion rate
4210#   0x00-0x01, 0x05-0x08: Temperatures (MAX1617 and LM84)
4211# Note: Especially the MAX1617 has very bad detection; we give it a low
4212# confidence value.
4213sub adm1021_detect
4214{
4215  my ($chip, $file, $addr) = @_;
4216  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
4217  my $rev = i2c_smbus_read_byte_data($file, 0xff);
4218  my $conf = i2c_smbus_read_byte_data($file, 0x03);
4219  my $status = i2c_smbus_read_byte_data($file, 0x02);
4220  my $convrate = i2c_smbus_read_byte_data($file, 0x04);
4221
4222  # Check manufacturer IDs and product revisions when available
4223  return if $chip == 0 and $man_id != 0x41 ||
4224                          ($rev & 0xf0) != 0x00;
4225  return if $chip == 1 and $man_id != 0x41 ||
4226                          ($rev & 0xf0) != 0x30;
4227  return if $chip == 3 and $man_id != 0x4d ||
4228                           $rev != 0x01;
4229  return if $chip == 4 and $man_id != 0x49;
4230  return if $chip == 5 and $convrate != 0x00;
4231  return if $chip == 6 and $man_id != 0x23;
4232  return if $chip == 7 and $man_id != 0x54;
4233
4234  # Check unused bits
4235  if ($chip == 5) # LM84
4236  {
4237    return if ($status & 0xab) != 0;
4238    return if ($conf & 0x7f) != 0;
4239  }
4240  else
4241  {
4242    return if ($status & 0x03) != 0;
4243    return if ($conf & 0x3f) != 0;
4244    return if ($convrate & 0xf8) != 0;
4245  }
4246
4247  # Extra checks for MAX1617 and LM84, since those are often misdetected
4248  # We verify several assertions (6 for the MAX1617, 4 for the LM84) and
4249  # discard the chip if any fail. Note that these checks are not done
4250  # by the adm1021 driver.
4251  if ($chip == 2 || $chip == 5)
4252  {
4253    my $lte = i2c_smbus_read_byte_data($file, 0x00);
4254    my $rte = i2c_smbus_read_byte_data($file, 0x01);
4255    my $lhi = i2c_smbus_read_byte_data($file, 0x05);
4256    my $rhi = i2c_smbus_read_byte_data($file, 0x07);
4257    my $llo = i2c_smbus_read_byte_data($file, 0x06);
4258    my $rlo = i2c_smbus_read_byte_data($file, 0x08);
4259
4260    # If all registers hold the same value, it has to be a misdetection
4261    return if $lte == $rte and $lte == $lhi and $lte == $rhi
4262           and $lte == $llo and $lte == $rlo;
4263
4264    # Negative temperatures
4265    return if ($lte & 0x80) or ($rte & 0x80);
4266    # Negative high limits
4267    return if ($lhi & 0x80) or ($rhi & 0x80);
4268    # Low limits over high limits
4269    if ($chip != 5) # LM84 doesn't have low limits
4270    {
4271      $llo-=256 if ($llo & 0x80);
4272      $rlo-=256 if ($rlo & 0x80);
4273      return if ($llo > $lhi) or ($rlo > $rhi);
4274    }
4275  }
4276
4277  return 3 if ($chip == 2) or ($chip == 5);
4278  return 7 if $chip <= 3;
4279  return 5;
4280}
4281
4282# $_[0]: Chip to detect
4283#   (0 = MAX1619)
4284# $_[1]: A reference to the file descriptor to access this chip.
4285#        We may assume an i2c_set_slave_addr was already done.
4286# $_[2]: Address
4287# Returns: undef if not detected, 7 if detected
4288# Registers used:
4289#   0xfe: Company ID
4290#   0xff: Device ID
4291#   0x02: Status
4292#   0x03: Configuration
4293#   0x04: Conversion rate
4294sub max1619_detect
4295{
4296  my ($chip, $file, $addr) = @_;
4297  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
4298  my $dev_id = i2c_smbus_read_byte_data($file, 0xff);
4299  my $conf = i2c_smbus_read_byte_data($file, 0x03);
4300  my $status = i2c_smbus_read_byte_data($file, 0x02);
4301  my $convrate = i2c_smbus_read_byte_data($file, 0x04);
4302
4303  return if $man_id != 0x4D
4304    or $dev_id != 0x04
4305    or ($conf & 0x03)
4306    or ($status & 0x61)
4307    or $convrate >= 8;
4308
4309  return 7;
4310}
4311
4312# $_[0]: A reference to the file descriptor to access this chip.
4313# $_[1]: Address (unused)
4314# Returns: undef if not detected, 6 if detected.
4315# Registers used:
4316#   0x28: User ID
4317#   0x29: User ID2
4318#   0x2A: Version ID
4319
4320sub ite_overclock_detect
4321{
4322  my ($file, $addr) = @_;
4323
4324  my $uid1 = i2c_smbus_read_byte_data($file, 0x28);
4325  my $uid2 = i2c_smbus_read_byte_data($file, 0x29);
4326  return if $uid1 != 0x83
4327         || $uid2 != 0x12;
4328
4329  return 6;
4330}
4331
4332# $_[0]: Chip to detect (0 = IT8712F)
4333# $_[1]: A reference to the file descriptor to access this chip.
4334#        We may assume an i2c_set_slave_addr was already done.
4335# $_[2]: Address
4336# Returns: undef if not detected, 7 or 8 if detected (tops LM78).
4337# Registers used:
4338#   0x00: Configuration
4339#   0x48: Full I2C Address
4340#   0x58: Mfr ID
4341#   0x5b: Device ID (not on IT8705)
4342# Note that this function is always called through a closure, so the
4343# arguments are shifted by one place.
4344sub ite_detect
4345{
4346  my $reg;
4347  my ($chip,$file,$addr) = @_;
4348  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
4349  return unless (i2c_smbus_read_byte_data($file, 0x00) & 0x90) == 0x10;
4350  return unless i2c_smbus_read_byte_data($file,0x58) == 0x90;
4351  return if $chip == 0 and i2c_smbus_read_byte_data($file,0x5b) != 0x12;
4352  return (7 + ($addr == 0x2d));
4353}
4354
4355
4356# $_[0]: Chip to detect (0 = IT8712F)
4357# $_[1]: ISA address
4358# $_[2]: I2C file handle
4359# $_[3]: I2C address
4360sub ite_alias_detect
4361{
4362  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
4363  my $i;
4364  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
4365  return 0 unless &$readproc(0x48) == $i2c_addr;
4366  for ($i = 0x30; $i <= 0x45; $i++) {
4367    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
4368  }
4369  return 1;
4370}
4371
4372# $_[0]: Chip to detect (0 = SPD EEPROM, 1 = Sony Vaio EEPROM,
4373#                        2 = SPD EEPROM with Software Write Protect)
4374# $_[1]: A reference to the file descriptor to access this chip
4375# $_[2]: Address
4376# Returns: 8 for a memory eeprom (9 if write-protect register found),
4377#          4 to 9 for a Sony Vaio eeprom,
4378#          1 for an unknown eeprom (2 if write-protect register found)
4379# Registers used:
4380#   0-63: SPD Data and Checksum
4381#   0x80-0x83: Sony Vaio Data ("PCG-")
4382#   0xe2, 0xe5, 0xe8, 0xeb, Oxee: Sony Vaio Timestamp constant bytes.
4383#   0x1a-0x1c: Sony Vaio MAC address
4384# This detection function is a bit tricky; this is to workaround
4385# wrong misdetection messages that would else arise.
4386sub eeprom_detect
4387{
4388  my ($chip,$file,$addr) = @_;
4389  my $checksum = 0;
4390
4391  # Check the checksum for validity (works for most DIMMs and RIMMs)
4392  if ($chip != 1) {
4393          for (my $i = 0; $i <= 62; $i ++) {
4394            $checksum += i2c_smbus_read_byte_data($file,$i);
4395          }
4396          $checksum &= 255;
4397          $checksum -= i2c_smbus_read_byte_data($file,63);
4398  }     
4399  if ($chip == 0) {
4400        if($checksum == 0) {
4401                return 8;
4402        } else {
4403                return 1;
4404        }
4405  }     
4406  if ($chip == 2) {
4407        # check for 'shadow' write-protect register at 0x30-0x37
4408        # could be dangerous
4409        i2c_set_slave_addr($file,$addr - 0x20);
4410        if(i2c_smbus_write_quick($file, SMBUS_WRITE) >= 0 &&
4411           i2c_smbus_read_byte_data($file,0x80) == -1) {
4412                i2c_set_slave_addr($file,$addr);
4413                if($checksum == 0) {
4414                        return (9, $addr - 0x20);
4415                } else {
4416                        return (2, $addr - 0x20);
4417                }
4418        }
4419        i2c_set_slave_addr($file,$addr);
4420        return;
4421  }
4422
4423  # Look for a Sony Vaio EEPROM ($chip == 1)
4424  my $vaioconf = 1;
4425  $vaioconf += 4
4426    if i2c_smbus_read_byte_data($file,0x80) == 0x50
4427    && i2c_smbus_read_byte_data($file,0x81) == 0x43
4428    && i2c_smbus_read_byte_data($file,0x82) == 0x47
4429    && i2c_smbus_read_byte_data($file,0x83) == 0x2d;
4430  $vaioconf += 5
4431    if i2c_smbus_read_byte_data($file,0xe2) == 0x2f
4432    && i2c_smbus_read_byte_data($file,0xe5) == 0x2f
4433    && i2c_smbus_read_byte_data($file,0xe8) == 0x20
4434    && i2c_smbus_read_byte_data($file,0xeb) == 0x3a
4435    && i2c_smbus_read_byte_data($file,0xee) == 0x3a;
4436  $vaioconf += 3
4437    if i2c_smbus_read_byte_data($file,0x1a) == 0x08
4438    && i2c_smbus_read_byte_data($file,0x1b) == 0x00
4439    && i2c_smbus_read_byte_data($file,0x1c) == 0x46;
4440  $vaioconf = 9
4441    if $vaioconf > 9;
4442
4443  if ($vaioconf > 1) {
4444    return $vaioconf;
4445  }
4446  return;
4447}
4448
4449# $_[0]: A reference to the file descriptor to access this chip.
4450#        We may assume an i2c_set_slave_addr was already done.
4451# $_[1]: Address
4452# Returns: undef if not detected, (1) if detected.
4453# Registers used:
4454#   0x00..0x07: DDC signature
4455#   0x08..0x7E: checksumed area
4456#   0x7F:       checksum
4457sub ddcmonitor_detect
4458{
4459  my ($file,$addr) = @_;
4460  my $i;
4461
4462  return unless
4463    i2c_smbus_read_byte_data($file,0x00) == 0x00 and
4464    i2c_smbus_read_byte_data($file,0x01) == 0xFF and
4465    i2c_smbus_read_byte_data($file,0x02) == 0xFF and
4466    i2c_smbus_read_byte_data($file,0x03) == 0xFF and
4467    i2c_smbus_read_byte_data($file,0x04) == 0xFF and
4468    i2c_smbus_read_byte_data($file,0x05) == 0xFF and
4469    i2c_smbus_read_byte_data($file,0x06) == 0xFF and
4470    i2c_smbus_read_byte_data($file,0x07) == 0x00;
4471
4472  # Check the checksum for validity.
4473  my $checksum = 0;
4474  for ($i = 0; $i <= 127; $i = $i + 1) {
4475    $checksum = $checksum + i2c_smbus_read_byte_data($file,$i);
4476  }
4477  $checksum=$checksum & 255;
4478  if ($checksum != 0) {
4479    # I have one such monitor...
4480    return (2,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
4481  }
4482  return (8,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
4483}
4484
4485# $_[0]: A reference to the file descriptor to access this chip.
4486#        We may assume an i2c_set_slave_addr was already done.
4487# $_[1]: Address
4488# Returns: undef if not detected, (8) if detected.
4489# Registers used:
4490#   0x00-0x02: Identification ('P','E','G' -> Pegasus ? :-)
4491sub fscpos_detect
4492{
4493  my ($file,$addr) = @_;
4494  # check the first 3 registers
4495  if (i2c_smbus_read_byte_data($file,0x00) != 0x50) {
4496        return;
4497  }
4498  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
4499        return;
4500  }
4501  if (i2c_smbus_read_byte_data($file,0x02) != 0x47) {
4502        return;
4503  }
4504  return (8);
4505}
4506
4507# $_[0]: A reference to the file descriptor to access this chip.
4508#        We may assume an i2c_set_slave_addr was already done.
4509# $_[1]: Address
4510# Returns: undef if not detected, (8) if detected.
4511# Registers used:
4512#   0x00-0x02: Identification ('S','C','Y')
4513sub fscscy_detect
4514{
4515  my ($file,$addr) = @_;
4516  # check the first 3 registers
4517  if (i2c_smbus_read_byte_data($file,0x00) != 0x53) {
4518        return;
4519  }
4520  if (i2c_smbus_read_byte_data($file,0x01) != 0x43) {
4521        return;
4522  }
4523  if (i2c_smbus_read_byte_data($file,0x02) != 0x59) {
4524        return;
4525  }
4526  return (8);
4527}
4528
4529# $_[0]: A reference to the file descriptor to access this chip.
4530#        We may assume an i2c_set_slave_addr was already done.
4531# $_[1]: Address
4532# Returns: undef if not detected, (8) if detected.
4533# Registers used:
4534#   0x00-0x02: Identification ('H','E','R')
4535sub fscher_detect
4536{
4537  my ($file,$addr) = @_;
4538  # check the first 3 registers
4539  if (i2c_smbus_read_byte_data($file,0x00) != 0x48) {
4540        return;
4541  }
4542  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
4543        return;
4544  }
4545  if (i2c_smbus_read_byte_data($file,0x02) != 0x52) {
4546        return;
4547  }
4548  return (8);
4549}
4550
4551# $_[0]: A reference to the file descriptor to access this chip.
4552#        We assume an i2c_set_slave_addr was already done.
4553# $_[1]: Address (unused)
4554# Returns: undef if not detected, 5 if detected.
4555# Registers used:
4556#   0x3E: Manufacturer ID
4557#   0x3F: Version/Stepping
4558sub lm93_detect
4559{
4560  my $file = shift;
4561  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x01
4562            and i2c_smbus_read_byte_data($file, 0x3F) == 0x73;
4563  return 5;
4564}
4565
4566# $_[0]: A reference to the file descriptor to access this chip.
4567#        We may assume an i2c_set_slave_addr was already done.
4568# $_[1]: Address
4569# Returns: undef if not detected, (7) if detected.
4570# Registers used:
4571#   0x3F: Revision ID
4572#   0x48: Address
4573#   0x4A, 0x4B, 0x4F, 0x57, 0x58: Reserved bits.
4574# We do not use 0x49's reserved bits on purpose. The register is named
4575# "VID4/Device ID" so it is doubtful bits 7-1 are really unused.
4576sub m5879_detect
4577{
4578  my ($file, $addr) = @_;
4579
4580  return
4581    unless i2c_smbus_read_byte_data($file, 0x3F) == 0x01;
4582 
4583  return
4584    unless i2c_smbus_read_byte_data($file, 0x48) == $addr;
4585 
4586  return
4587    unless (i2c_smbus_read_byte_data($file, 0x4A) & 0x06) == 0
4588       and (i2c_smbus_read_byte_data($file, 0x4B) & 0xFC) == 0
4589       and (i2c_smbus_read_byte_data($file, 0x4F) & 0xFC) == 0
4590       and (i2c_smbus_read_byte_data($file, 0x57) & 0xFE) == 0
4591       and (i2c_smbus_read_byte_data($file, 0x58) & 0xEF) == 0;
4592
4593  return (7);
4594}
4595
4596# $_[0]: A reference to the file descriptor to access this chip.
4597#        We assume an i2c_set_slave_addr was already done.
4598# $_[1]: Address
4599# Returns: undef if not detected, 5 or 6 if detected.
4600# Registers used:
4601#   0x3E: Manufacturer ID
4602#   0x3F: Version/Stepping
4603#   0x47: VID (3 reserved bits)
4604#   0x49: VID4 (7 reserved bits)
4605sub smsc47m192_detect
4606{
4607  my ($file, $addr) = @_;
4608  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x55
4609           and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF0) == 0x20
4610           and (i2c_smbus_read_byte_data($file, 0x47) & 0x70) == 0x00
4611           and (i2c_smbus_read_byte_data($file, 0x49) & 0xFE) == 0x80;
4612  return ($addr == 0x2d ? 6 : 5);
4613}
4614
4615# $_[0]: A reference to the file descriptor to access this chip.
4616#        We assume an i2c_set_slave_addr was already done.
4617# $_[1]: Address
4618# Returns: undef if not detected, 5 or 6 if detected.
4619# Registers used:
4620#   0x3E: Manufacturer ID
4621#   0x3F: Version/Stepping
4622#   0x40: Configuration (2 reserved bits)
4623#   0x42: Interrupt Status 2 (1 reserved bit)
4624#   0x43: VID (2 reserved bits)
4625sub dme1737_detect
4626{
4627  my ($file, $addr) = @_;
4628  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x55
4629           and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF8) == 0x88
4630           and (i2c_smbus_read_byte_data($file, 0x40) & 0xC4) == 0x04
4631           and (i2c_smbus_read_byte_data($file, 0x42) & 0x02) == 0x00
4632           and (i2c_smbus_read_byte_data($file, 0x43) & 0xC0) == 0x00;
4633  return ($addr == 0x2e ? 6 : 5);
4634}
4635
4636# $_[0]: Chip to detect
4637#   (1 = F75111R/RG/N, 2 = F75121R/F75122R/RG, 3 = F75373S/SG,
4638#    4 = F75375S/SP, 5 = F75387SG/RG, 6 = F75383M/S/F75384M/S,
4639#    7 = custom power control IC)
4640# $_[1]: A reference to the file descriptor to access this chip.
4641#        We assume an i2c_set_slave_addr was already done.
4642# $_[2]: Address (unused)
4643# Returns: undef if not detected, 7 if detected.
4644# Registers used:
4645#   0x5A-0x5B: Chip ID
4646#   0x5D-0x5E: Vendor ID
4647sub fintek_detect
4648{
4649  my ($chip, $file, $addr) = @_;
4650  my $chipid = (i2c_smbus_read_byte_data($file, 0x5A) << 8)
4651             | i2c_smbus_read_byte_data($file, 0x5B);
4652  my $vendid = (i2c_smbus_read_byte_data($file, 0x5D) << 8)
4653             | i2c_smbus_read_byte_data($file, 0x5E);
4654
4655  return unless $vendid == 0x1934; # Fintek ID
4656
4657  if ($chip == 1) { # F75111R/RG/N
4658    return unless $chipid == 0x0300;
4659  } elsif ($chip == 2) { # F75121R/F75122R/RG
4660    return unless $chipid == 0x0301;
4661  } elsif ($chip == 3) { # F75373S/SG
4662    return unless $chipid == 0x0204;
4663  } elsif ($chip == 4) { # F75375S/SP
4664    return unless $chipid == 0x0306;
4665  } elsif ($chip == 5) { # F75387SG/RG
4666    return unless $chipid == 0x0410;
4667  } elsif ($chip == 6) { # F75383M/S/F75384M/S
4668    # The datasheet has 0x0303, but Fintek say 0x0413 is also possible
4669    return unless $chipid == 0x0303 || $chipid == 0x0413;
4670  } elsif ($chip == 7) { # custom power control IC
4671    return unless $chipid == 0x0302;
4672  }
4673
4674  return 7;
4675}
4676
4677# $_[0]: A reference to the file descriptor to access this chip.
4678#        We may assume an i2c_set_slave_addr was already done.
4679# $_[1]: Address
4680# Returns: undef if not detected, 4 or 7 if detected
4681# Detection is based on the fact that the SAA1064 has only one readable
4682# register, and thus ignores the read address. This register can have value
4683# 0x80 (first read since power-up) or 0x00.
4684sub saa1064_detect
4685{
4686        my ($file,$addr) = @_;
4687        my $status = i2c_smbus_read_byte_data ($file, 0x00);
4688
4689        return if ($status & 0x7f) != 0x00;
4690
4691        for (my $i=0 ; $i<256; $i++) {
4692                return if i2c_smbus_read_byte_data ($file, $i) != 0x00;
4693        }
4694
4695        return 7
4696                if $status == 0x80;
4697        return 4;
4698}
4699
4700# $_[0]: A reference to the file descriptor to access this chip.
4701#        We may assume an i2c_set_slave_addr was already done.
4702# $_[1]: Address
4703# Returns: undef if not detected, 1 if detected
4704# Detection is rather difficult, since the PCA9540 has a single register.
4705# Fortunately, no other device is known to live at this address.
4706sub pca9540_detect
4707{
4708        my ($file, $addr) = @_;
4709        my $reg = i2c_smbus_read_byte($file);
4710
4711        return if ($reg & 0xfa);
4712        return if $reg != i2c_smbus_read_byte($file);
4713        return if $reg != i2c_smbus_read_byte($file);
4714        return if $reg != i2c_smbus_read_byte($file);
4715
4716        return 1;
4717}
4718
4719# $_[0]: A reference to the file descriptor to access this chip.
4720#        We assume an i2c_set_slave_addr was already done.
4721# $_[1]: Address (unused)
4722# Returns: undef if not detected, 1 if detected
4723# Detection is rather difficult, since the PCA9556 only has 4 registers
4724# and no unused bit. We use the fact that the registers cycle over
4725# 4 addresses boundaries, and the logic rules between registers.
4726sub pca9556_detect
4727{
4728        my ($file, $addr) = @_;
4729        my $input = i2c_smbus_read_byte_data($file, 0x00);
4730        my $output = i2c_smbus_read_byte_data($file, 0x01);
4731        my $invert = i2c_smbus_read_byte_data($file, 0x02);
4732        my $config = i2c_smbus_read_byte_data($file, 0x03);
4733
4734        # Pins configured for output (config = 0) must obey the following
4735        # rule: input = output ^ invert
4736
4737        return unless ($input & ~$config) == (($output ^ $invert) & ~$config);
4738
4739        for (my $i = 5; $i < 254 ; $i+=4) {
4740                return unless i2c_smbus_read_byte_data($file, $i) == $output;
4741                return unless i2c_smbus_read_byte_data($file, $i+1) == $invert;
4742                return unless i2c_smbus_read_byte_data($file, $i+2) == $config;
4743        }
4744
4745        return 1;
4746}
4747
4748# $_[0]: A reference to the file descriptor to access this chip.
4749#        We may assume an i2c_set_slave_addr was already done.
4750# $_[1]: Address
4751# Returns: undef if not detected, 3 if detected
4752sub max6900_detect
4753{
4754        my ($file,$addr) = @_;
4755        my $reg;
4756       
4757        # SEC
4758        $reg = i2c_smbus_read_byte_data ($file, 0x81);
4759        return if
4760                ($reg & 0xF0) > 0x50 or
4761                ($reg & 0x0F) > 9;
4762
4763        # MIN
4764        $reg = i2c_smbus_read_byte_data ($file, 0x83);
4765        return if
4766                ($reg & 0xF0) > 0x50 or
4767                ($reg & 0x0F) > 9;
4768
4769        # HR
4770        $reg = i2c_smbus_read_byte_data ($file, 0x85);
4771        return if
4772                ($reg & 0x40) != 0x00 or
4773                ($reg & 0x0F) > 9;
4774
4775        # DATE
4776        $reg = i2c_smbus_read_byte_data ($file, 0x87);
4777        return if
4778                $reg == 0x00 or
4779                ($reg & 0xF0) > 0x30 or
4780                ($reg & 0x0F) > 9;
4781
4782        # MONTH
4783        $reg = i2c_smbus_read_byte_data ($file, 0x89);
4784        return if
4785                $reg == 0x00 or
4786                ($reg & 0xF0) > 0x10 or
4787                ($reg & 0x0F) > 9;
4788
4789        # DAY
4790        $reg = i2c_smbus_read_byte_data ($file, 0x8B);
4791        return if
4792                $reg == 0 or
4793                $reg > 7;
4794
4795        # YEAR
4796        $reg = i2c_smbus_read_byte_data ($file, 0x8D);
4797        return if
4798                ($reg & 0xF0) > 0x90 or
4799                ($reg & 0x0F) > 9;
4800
4801        # CONTROL
4802        $reg = i2c_smbus_read_byte_data ($file, 0x8F);
4803        return if
4804                ($reg & 0x7F) != 0x00;
4805
4806        # CENTURY
4807        $reg = i2c_smbus_read_byte_data ($file, 0x93);
4808        return if
4809                ($reg & 0xF0) > 0x90 or
4810                ($reg & 0x0F) > 9;
4811
4812        return 3;
4813}
4814
4815# $_[0]: A reference to the file descriptor to access this chip.
4816#        We may assume an i2c_set_slave_addr was already done.
4817# $_[1]: Address
4818# Returns: 1
4819# This is a placeholder so we get a report if any device responds
4820# to the SMBus Device Default Address (0x61), which is used for
4821# ARP in SMBus 2.0.
4822sub arp_detect
4823{
4824  return (1);
4825}
4826
4827# This checks for non-FFFF values for SpecInfo and Status.
4828# The address (0x09) is specified by the SMBus standard so it's likely
4829# that this really is a smart battery charger.
4830# $_[0]: A reference to the file descriptor to access this chip.
4831#        We may assume an i2c_set_slave_addr was already done.
4832# $_[1]: Address
4833# Returns: 5
4834sub smartbatt_chgr_detect
4835{
4836  my ($file,$addr) = @_;
4837  # check some registers
4838  if (i2c_smbus_read_word_data($file,0x11) == 0xffff) {
4839        return;
4840  }
4841  if (i2c_smbus_read_word_data($file,0x13) == 0xffff) {
4842        return;
4843  }
4844  return (5);
4845}
4846
4847# This checks for non-FFFF values for State and Info.
4848# The address (0x0a) is specified by the SMBus standard so it's likely
4849# that this really is a smart battery manager/selector.
4850# $_[0]: A reference to the file descriptor to access this chip.
4851#        We may assume an i2c_set_slave_addr was already done.
4852# $_[1]: Address
4853# Returns: 5
4854sub smartbatt_mgr_detect
4855{
4856  my ($file,$addr) = @_;
4857  # check some registers
4858  if (i2c_smbus_read_word_data($file,0x01) == 0xffff) {
4859        return;
4860  }
4861  if (i2c_smbus_read_word_data($file,0x04) == 0xffff) {
4862        return;
4863  }
4864  return (5);
4865}
4866
4867# This checks for non-FFFF values for temperature, voltage, and current.
4868# The address (0x0b) is specified by the SMBus standard so it's likely
4869# that this really is a smart battery.
4870# $_[0]: A reference to the file descriptor to access this chip.
4871#        We may assume an i2c_set_slave_addr was already done.
4872# $_[1]: Address
4873# Returns: 5
4874sub smartbatt_detect
4875{
4876  my ($file,$addr) = @_;
4877  # check some registers
4878  if (i2c_smbus_read_word_data($file,0x08) == 0xffff) {
4879        return;
4880  }
4881  if (i2c_smbus_read_word_data($file,0x09) == 0xffff) {
4882        return;
4883  }
4884  if (i2c_smbus_read_word_data($file,0x0a) == 0xffff) {
4885        return;
4886  }
4887  return (5);
4888}
4889
4890# Returns: 4
4891# These are simple detectors that only look for a register at the
4892# standard location. No writes are performed.
4893# For KCS, use the STATUS register. For SMIC, use the FLAGS register.
4894sub ipmi_kcs_detect
4895{
4896  return if inb (0x0ca3) == 0xff;
4897  return (4);
4898}
4899
4900sub ipmi_smic_detect
4901{
4902  return if inb (0x0cab) == 0xff;
4903  return (4);
4904}
4905
4906# $_[0]: Chip to detect (0 = W83L784R/AR, 1 = W83L785R)
4907# $_[1]: A reference to the file descriptor to access this chip.
4908# $_[2]: Address
4909# Returns: undef if not detected, 6 or 8 if detected
4910# Registers used:
4911#   0x40: Configuration
4912#   0x4a: Full I2C Address (not W83L785R)
4913#   0x4b: I2C addresses of emulated LM75 chips (not W83L785R)
4914#   0x4c: Winbond Vendor ID (Low Byte)
4915#   0x4d: Winbond Vendor ID (High Byte)
4916#   0x4e: Chip ID
4917# Note that this function is always called through a closure, so the
4918# arguments are shifted by one place.
4919sub w83l784r_detect
4920{
4921  my ($reg,@res);
4922  my ($chip,$file,$addr) = @_;
4923
4924  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4925  return if $chip == 0
4926    and i2c_smbus_read_byte_data($file,0x4a) != $addr;
4927  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
4928  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
4929  return if $chip == 0
4930    and i2c_smbus_read_byte_data($file,0x4e) != 0x50;
4931  return if $chip == 1
4932    and i2c_smbus_read_byte_data($file,0x4e) != 0x60;
4933
4934  $reg = i2c_smbus_read_byte_data($file,0x4b);
4935
4936  return 6 if $chip == 1; # W83L785R doesn't have subclients
4937 
4938  @res = (8);
4939  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08 ;
4940  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
4941  return @res;
4942}
4943
4944# $_[0]: Chip to detect (0 = W83L785TS-S)
4945# $_[1]: A reference to the file descriptor to access this chip.
4946#        We may assume an i2c_set_slave_addr was already done.
4947# $_[2]: Address
4948# Returns: undef if not detected, 8 if detected
4949# Registers used:
4950#   0x4C-4E: Mfr and Chip ID
4951# Note that this function is always called through a closure, so the
4952# arguments are shifted by one place.
4953sub w83l785ts_detect
4954{
4955  my ($chip,$file,$addr) = @_;
4956  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
4957  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
4958  return unless i2c_smbus_read_byte_data($file,0x4e) == 0x70;
4959  return (8);
4960}
4961
4962# $_[0]: Chip to detect. Always zero for now, but available for future use
4963#        if somebody finds a way to distinguish MAX6650 and MAX6651.
4964# $_[1]: A reference to the file descriptor to access this chip.
4965#        We may assume an i2c_set_slave_addr was already done.
4966# $_[2]: Address
4967# Returns: undef if not detected, 4 if detected.
4968#
4969# The max6650 has no device ID register. However, a few registers have
4970# spare bits, which are documented as being always zero on read. We read
4971# all of these registers check the spare bits. Any non-zero means this
4972# is not a max6650/1.
4973#
4974# The always zero bits are:
4975#   configuration byte register (0x02) - top 2 bits
4976#   gpio status register (0x14) - top 3 bits
4977#   alarm enable register (0x08) - top 3 bits
4978#   alarm status register (0x0A) - top 3 bits
4979#   tachometer count time register (0x16) - top 6 bits
4980# Additionally, not all values are possible for lower 3 bits of
4981# the configuration register.
4982sub max6650_detect
4983{
4984  my ($chip, $file) = @_;
4985
4986  my $conf = i2c_smbus_read_byte_data($file,0x02);
4987 
4988  return if i2c_smbus_read_byte_data($file,0x16) & 0xFC;
4989  return if i2c_smbus_read_byte_data($file,0x0A) & 0xE0;
4990  return if i2c_smbus_read_byte_data($file,0x08) & 0xE0;
4991  return if i2c_smbus_read_byte_data($file,0x14) & 0xE0;
4992  return if ($conf & 0xC0) or ($conf & 0x07) > 4;
4993
4994  return 4;
4995}
4996
4997# $_[0]: Chip to detect (0 = VT1211)
4998# $_[1]: A reference to the file descriptor to access this chip.
4999#        We may assume an i2c_set_slave_addr was already done.
5000# $_[2]: Address
5001#
5002# This isn't very good detection.
5003# Verify the i2c address, and the stepping ID (which is 0xb0 on
5004# my chip but could be different for others...
5005#
5006sub vt1211_i2c_detect
5007{
5008  my ($chip,$file,$addr) = @_;
5009  return unless (i2c_smbus_read_byte_data($file,0x48) & 0x7f) == $addr;
5010  return unless i2c_smbus_read_byte_data($file,0x3f) == 0xb0;
5011  return 2;
5012}
5013
5014# $_[0]: Chip to detect (0 = VT1211)
5015# $_[1]: ISA address
5016# $_[2]: I2C file handle
5017# $_[3]: I2C address
5018sub vt1211_alias_detect
5019{
5020  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
5021  my $i;
5022  return 0 unless (inb($isa_addr + 0x48) & 0x7f) == $i2c_addr;
5023  return 0 unless (i2c_smbus_read_byte_data($file,0x48) & 0x7f) == $i2c_addr;
5024  for ($i = 0x2b; $i <= 0x3d; $i ++) {
5025    return 0 unless inb($isa_addr + $i) == i2c_smbus_read_byte_data($file,$i);
5026  }
5027  return 1;
5028}
5029
5030
5031######################
5032# PCI CHIP DETECTION #
5033######################
5034
5035# Returns: undef if not detected, (7) or (9) if detected.
5036# The address is encoded in PCI space. We could decode it and print it.
5037# For Linux 2.4 we should probably check for invalid matches (SiS645).
5038sub sis5595_pci_detect
5039{
5040        return unless exists $pci_list{'1039:0008'};
5041        return (kernel_version_at_least(2, 6, 0) ? 9 : 7);
5042}
5043
5044# Returns: undef if not detected, (9) if detected.
5045# The address is encoded in PCI space. We could decode it and print it.
5046sub via686a_pci_detect
5047{
5048        return unless exists $pci_list{'1106:3057'};
5049        return 9;
5050}
5051
5052# Returns: undef if not detected, (9) if detected.
5053# The address is encoded in PCI space. We could decode it and print it.
5054sub via8231_pci_detect
5055{
5056        return unless exists $pci_list{'1106:8235'};
5057        return 9;
5058}
5059
5060# Returns: undef if not detected, (9) if detected.
5061sub k8temp_pci_detect
5062{
5063        return unless exists $pci_list{'1022:1103'};
5064        return 9;
5065}
5066
5067
5068################
5069# MAIN PROGRAM #
5070################
5071
5072# $_[0]: reference to a list of chip hashes
5073sub print_chips_report 
5074{
5075  my ($listref) = @_;
5076  my $data;
5077 
5078  foreach $data (@$listref) {
5079    my $is_i2c = exists $data->{i2c_addr};
5080    my $is_isa = exists $data->{isa_addr};
5081    print "  * ";
5082    if ($is_i2c) {
5083      printf "Bus `%s'\n", $data->{i2c_adap};
5084      printf "    Busdriver `%s', I2C address 0x%02x", 
5085             $data->{i2c_driver}, $data->{i2c_addr};
5086      if (exists $data->{i2c_sub_addrs}) {
5087        print " (and";
5088        my $sub_addr;
5089        foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
5090          printf " 0x%02x",$sub_addr;
5091        }
5092        print ")"
5093      }
5094      print "\n";
5095    }
5096    if ($is_isa) {
5097      print "    " if  $is_i2c;
5098      if ($data->{isa_addr}) {
5099        printf "ISA bus address 0x%04x (Busdriver `i2c-isa')\n", 
5100               $data->{isa_addr};
5101      } else {
5102        print "ISA bus, undetermined address (Busdriver `i2c-isa')\n";
5103      }
5104    }
5105    printf "    Chip `%s' (confidence: %d)\n",
5106           $data->{chipname},  $data->{conf};
5107  }
5108}
5109
5110# $_[0]: 1 if ISA bus is prefered, 0 for SMBus
5111# We build here an array adapters, indexed on the number the adapter has
5112# at this moment (we assume only loaded adapters are interesting at all;
5113# everything that got scanned also got loaded). Each entry is a reference
5114# to a hash containing:
5115#  driver: Name of the adapter driver
5116#  nr_now: Number of the bus now
5117#  nr_later: Number of the bus when the modprobes are done (not included if the
5118#        driver should not be loaded)
5119# A second array, called
5120sub generate_modprobes
5121{
5122  my ($prefer_isa) = @_;
5123
5124  my ($chip,$detection,$nr,$i,@optionlist,@probelist,$driver,$isa,$adap);
5125  my $bmcsensors = 0;
5126  my @adapters;
5127  my $modprobes = "";
5128  my $configfile = "";
5129
5130  # These are always needed
5131  $configfile .= "# I2C module options\n";
5132  $configfile .= "alias char-major-89 i2c-dev\n";
5133
5134  # Collect all loaded adapters
5135  # i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
5136  open(local *INPUTFILE, "i2cdetect -l |") or die "Couldn't find i2cdetect program!!";
5137  local $_;
5138  while (<INPUTFILE>) {
5139    my ($dev_nr, $type, $adap) = /^i2c-(\d+)\s+(\S+)\s+(.*?) *(\t|$)/;
5140    next if ($type eq "dummy" || $type eq "isa");
5141    $adapters[$dev_nr]->{driver} = find_adapter_driver($adap);
5142    $adapters[$dev_nr]->{adapname} = $adap;
5143  }
5144  close INPUTFILE;
5145
5146  # Collect all adapters used
5147  $nr = 0;
5148  $isa = 0;
5149  $modprobes .= "# I2C adapter drivers\n";
5150  foreach $chip (@chips_detected) {
5151    foreach $detection (@{$chip->{detected}}) {
5152      # If there is more than one bus detected by a driver, they are
5153      # still all added. So we number them in the correct order
5154      if (exists $detection->{i2c_driver} and
5155          not exists $adapters[$detection->{i2c_devnr}]->{nr_later} and 
5156          not (exists $detection->{isa_addr} and $prefer_isa)) {
5157         foreach $adap (@adapters) {
5158           next unless exists $adap->{driver};
5159           $adap->{nr_later} = $nr++ if $adap->{driver} eq $detection->{i2c_driver};
5160         }
5161      }
5162      if (exists $detection->{isa_addr} and
5163          not (exists $detection->{i2c_driver} and not $prefer_isa)) {
5164           $isa=1;
5165      }
5166      if ($chip->{driver} eq "bmcsensors") {
5167           $bmcsensors=1;
5168      }
5169    }
5170  }
5171
5172  for ($i = 0; $i < $nr; $i++) {
5173    foreach $adap (@adapters) {
5174      next unless exists $adap->{nr_later} and $adap->{nr_later} == $i;
5175      if ($adap->{driver} eq "UNKNOWN") {
5176        $modprobes .= "# modprobe unknown adapter ".$adap->{adapname}."\n";
5177      } elsif ($adap->{driver} eq "DISABLED") {
5178        $modprobes .= "# modprobe disabled adapter ".$adap->{adapname}."\n";
5179      } elsif ($adap->{driver} eq "to-be-written") {
5180        $modprobes .= "# no driver available for adapter ".$adap->{adapname}."\n";
5181      } else {
5182        $modprobes .= "modprobe $adap->{driver}\n"
5183          unless $modprobes =~ /modprobe $adap->{driver}\n/;
5184      }
5185      last;
5186    }
5187  }
5188  # i2c-isa is loaded automatically (as a dependency) since 2.6.14,
5189  # and will soon be gone.
5190  $modprobes .= "modprobe i2c-isa\n" if ($isa && !kernel_version_at_least(2, 6, 18));
5191  if ($bmcsensors) {
5192    $modprobes .= "# You must also install and load the IPMI modules\n";
5193    $modprobes .= "modprobe i2c-ipmi\n";
5194  }
5195
5196  # Now determine the chip probe lines
5197  $modprobes .= "# Chip drivers\n";
5198  foreach $chip (@chips_detected) {
5199    next if not @{$chip->{detected}};
5200    next if $chip->{driver} eq "not-a-sensor";   
5201    next if $chip->{driver} eq "use-isa-instead";
5202    if ($chip->{driver} eq "to-be-written") {
5203      $modprobes .= "# no driver for $chip->{detected}[0]{chipname} yet\n";
5204    } else {
5205       # need the * for 2.4 kernels, won't necessarily be an exact match
5206       open(local *INPUTFILE, "modprobe -l $chip->{driver}\\* 2>/dev/null |");
5207       local $_;
5208       my $modulefound = 0;
5209       while (<INPUTFILE>) {
5210         if(m@/@) {
5211           $modulefound = 1;
5212           last;
5213         }
5214       }
5215       close INPUTFILE;
5216       #check return value from modprobe in case modprobe -l isn't supported
5217       if((($? >> 8) == 0) && ! $modulefound) {
5218         $modprobes .= "# Warning: the required module $chip->{driver} is not currently installed\n".
5219                       "# on your system. For status of 2.6 kernel ports check\n".
5220                       "# http://www.lm-sensors.org/wiki/Devices. If driver is built\n".
5221                       "# into the kernel, or unavailable, comment out the following line.\n";
5222       }
5223       $modprobes .= "modprobe $chip->{driver}\n";
5224    }
5225
5226    # Handle misdetects
5227    foreach $detection (@{$chip->{misdetected}}) {
5228      push @optionlist, $adapters[$detection->{i2c_devnr}]->{nr_later},
5229                       $detection->{i2c_addr}
5230           if exists $detection->{i2c_addr} and
5231              exists $adapters[$detection->{i2c_devnr}]->{nr_later};
5232      push @optionlist, -1, $detection->{isa_addr}
5233           if exists $detection->{isa_addr} and $isa;
5234    }
5235
5236    # Handle aliases
5237    foreach $detection (@{$chip->{detected}}) {
5238      if (exists $detection->{i2c_driver} and 
5239          exists $detection->{isa_addr} and
5240          exists $adapters[$detection->{i2c_devnr}]->{nr_later} and
5241          $isa) {
5242        if ($prefer_isa) {
5243          push @optionlist,$adapters[$detection->{i2c_devnr}]->{nr_later},
5244                           $detection->{i2c_addr};
5245        } else {
5246          push @optionlist, -1, $detection->{isa_addr}
5247        }
5248      }
5249    }
5250
5251    next if not (@probelist or @optionlist);
5252    $configfile .= "options $chip->{driver}";
5253    $configfile .= sprintf " ignore=%d,0x%02x",shift @optionlist, 
5254                                               shift @optionlist
5255                  if @optionlist;
5256    $configfile .= sprintf ",%d,0x%02x",shift @optionlist, shift @optionlist
5257                  while @optionlist;
5258    $configfile .= sprintf " probe=%d,0x%02x",shift @probelist,
5259                                              shift @probelist
5260                  if @probelist;
5261    $configfile .= sprintf ",%d,0x%02x",shift @probelist, shift @probelist
5262                  while @probelist;
5263    $configfile .= "\n";
5264  }
5265
5266  return ($modprobes,$configfile);
5267 
5268}
5269
5270sub main
5271{
5272  my (@adapters,$res,$did_adapter_detection,$adapter);
5273
5274  # We won't go very far if not root
5275  unless ($> == 0) {
5276    print "You need to be root to run this script.\n";
5277    exit -1;
5278  }
5279
5280  initialize_conf;
5281  initialize_proc_pci;
5282  initialize_modules_list;
5283  initialize_modules_supported;
5284  initialize_kernel_version;
5285
5286  print "# sensors-detect revision $revision\n\n";
5287
5288  print "This program will help you determine which kernel modules you need\n",
5289        "to load to use lm_sensors most effectively. It is generally safe\n",
5290        "and recommended to accept the default answers to all questions,\n",
5291        "unless you know what you're doing.\n";
5292  print "You need to have i2c and lm_sensors installed before running this\n",
5293        "program.\n"
5294    unless kernel_version_at_least(2, 6, 0);
5295  print "\n";
5296
5297  print "We can start with probing for (PCI) I2C or SMBus adapters.\n";
5298  print "Do you want to probe now? (YES/no): ";
5299  @adapters = adapter_pci_detection
5300                        if ($did_adapter_detection = not <STDIN> =~ /\s*[Nn]/);
5301  print "\n";
5302
5303  if (not $did_adapter_detection) {
5304    print "As you skipped adapter detection, we will only scan already loaded\n".
5305          "adapter modules.\n";
5306  } else {
5307    print "We will now try to load each adapter module in turn.\n";
5308    foreach $adapter (@adapters) {
5309      next if $adapter eq "DISABLED";
5310      next if $adapter eq "to-be-tested";
5311      if (exists($modules_list{$adapter})) {
5312        print "Module `$adapter' already loaded.\n";
5313      } else {
5314        print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
5315        unless (<STDIN> =~ /^\s*[Nn]/) {
5316          if (system ("modprobe", $adapter)) {
5317            print "Loading failed... skipping.\n";
5318          } else {
5319            print "Module loaded successfully.\n";
5320          }
5321        }
5322      }
5323    }
5324  }
5325
5326  print "If you have undetectable or unsupported adapters, you can have them\n".
5327        "scanned by manually loading the modules before running this script.\n\n";
5328
5329  if (!exists($modules_list{"i2c-dev"})
5330   && !(defined $sysfs_root && -e "$sysfs_root/class/i2c-dev")) {
5331    print "To continue, we need module `i2c-dev' to be loaded.\n";
5332    print "If it is built-in into your kernel, you can safely skip this.\n"
5333      unless kernel_version_at_least(2, 6, 0);
5334    print "Do you want to load `i2c-dev' now? (YES/no): ";
5335    if (<STDIN> =~ /^\s*n/i) {
5336      print "Well, you will know best.\n";
5337    } elsif (system "modprobe", "i2c-dev") {
5338      print "Loading failed, expect problems later on.\n";
5339    } else {
5340      print "Module loaded successfully.\n";
5341    }
5342    print "\n";
5343  }
5344
5345  # Before looking for chips, make sure any special case chips are
5346  # added to the chip_ids list
5347  chip_special_cases();
5348
5349  print "We are now going to do the I2C/SMBus adapter probings. Some chips may\n",
5350        "be double detected; we choose the one with the highest confidence\n",
5351        "value in that case.\n",
5352        "If you found that the adapter hung after probing a certain address,\n",
5353        "you can specify that address to remain unprobed.\n";
5354
5355  my ($inp,@not_to_scan,$inp2);
5356  # i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
5357  open(local *INPUTFILE, "i2cdetect -l |") or die "Couldn't find i2cdetect program!!";
5358  local $_;
5359  while (<INPUTFILE>) {
5360    my ($dev_nr, $type, $adap) = /^i2c-(\d+)\s+(\S+)\s+(.*?) *(\t|$)/;
5361    next if ($type eq "dummy" || $type eq "isa");
5362    print "\n";
5363    print "Next adapter: $adap\n";
5364    print "Do you want to scan it? (YES/no/selectively): ";
5365   
5366    $inp = <STDIN>;
5367    if ($inp =~ /^\s*[Ss]/) {
5368      print "Please enter one or more addresses not to scan. Separate them ",
5369            "with comma's.\n",
5370            "You can specify a range by using dashes. Addresses may be ",
5371            "decimal (like 54)\n",
5372            "or hexadecimal (like 0x33).\n",
5373            "Addresses: ";
5374      $inp2 = <STDIN>;
5375      chop $inp2;
5376      @not_to_scan = parse_not_to_scan 0,0x7f,$inp2;
5377    }
5378    scan_adapter $dev_nr, $adap, find_adapter_driver($adap),
5379                 \@not_to_scan   unless $inp =~ /^\s*[Nn]/;
5380  }
5381  print "\n";
5382
5383  print "Some chips are also accessible through the ISA I/O ports. We have to\n".
5384        "write to arbitrary I/O ports to probe them. This is usually safe though.\n".
5385        "Yes, you do have ISA I/O ports even if you do not have any ISA slots!\n";
5386  print "Do you want to scan the ISA I/O ports? (YES/no): ";
5387  unless (<STDIN> =~ /^\s*n/i) {
5388    initialize_ioports();
5389    scan_isa_bus();
5390    close_ioports();
5391  }
5392  print "\n";
5393
5394  print "Some Super I/O chips may also contain sensors. We have to write to\n".
5395        "standard I/O ports to probe them. This is usually safe.\n";
5396  print "Do you want to scan for Super I/O sensors? (YES/no): ";
5397  unless (<STDIN> =~ /^\s*n/i) {
5398    initialize_ioports();
5399    scan_superio(0x2e, 0x2f);
5400    scan_superio(0x4e, 0x4f);
5401    close_ioports();
5402  }
5403  print "\n";
5404
5405  if(! @chips_detected) {
5406    print "Sorry, no sensors were detected.\n",
5407          "Either your sensors are not supported, or they are connected to an\n",
5408          "I2C or SMBus adapter that is not supported. See doc/FAQ,\n",
5409          "doc/lm_sensors-FAQ.html or http://www.lm-sensors.org/wiki/FAQ\n",
5410          "(FAQ #4.24.3) for further information.\n",
5411          "If you find out what chips are on your board, check\n",
5412          "http://www.lm-sensors.org/wiki/Devices for driver status.\n";
5413    exit;
5414  }
5415
5416  print "Now follows a summary of the probes I have just done.\n".
5417        "Just press ENTER to continue: ";
5418  <STDIN>;
5419
5420  my ($chip,$data);
5421  foreach $chip (@chips_detected) {
5422    next if $chip->{driver} eq "not-a-sensor";
5423    next if $chip->{driver} eq "use-isa-instead";
5424    print "\nDriver `$chip->{driver}' ";
5425    if (@{$chip->{detected}}) {
5426      if (@{$chip->{misdetected}}) {
5427        print "(should be inserted but causes problems):\n";
5428      } else {
5429        print "(should be inserted):\n";
5430      }
5431    } else {
5432      if (@{$chip->{misdetected}}) {
5433        print "(may not be inserted):\n";
5434      } else {
5435        print "(should not be inserted, but is harmless):\n";
5436      }
5437    }
5438    if (@{$chip->{detected}}) {
5439      print "  Detects correctly:\n";
5440      print_chips_report $chip->{detected};
5441    }
5442    if (@{$chip->{misdetected}}) {
5443      print "  Misdetects:\n";
5444      print_chips_report $chip->{misdetected};
5445    }
5446
5447    # People are easily confused
5448    if ($chip->{driver} eq "eeprom") {
5449      print "\n  EEPROMs are *NOT* sensors! They are data storage chips commonly\n",
5450            "  found on memory modules (SPD), in monitors (EDID), or in some\n",
5451            "  laptops, for example.\n";
5452    }
5453  }
5454  print "\n";
5455
5456  print "I will now generate the commands needed to load the required modules.\n".
5457        "Just press ENTER to continue: ";
5458  <STDIN>;
5459     
5460  print "\n";
5461  my ($modprobes, $configfile) = generate_modprobes 1;  # 1 == prefer ISA
5462  print "To make the sensors modules behave correctly, add these lines to\n".
5463        "$modules_conf:\n\n";
5464  print "#----cut here----\n".
5465        $configfile.
5466        "#----cut here----\n\n";
5467
5468  print "To load everything that is needed, add this to some /etc/rc* file:\n\n";
5469  print "#----cut here----\n".
5470        $modprobes.
5471        "# sleep 2 # optional\n".
5472        "/usr/local/bin/sensors -s # recommended\n".
5473        "#----cut here----\n\n";
5474
5475  print "If you have some drivers built into your kernel, the list above will\n".
5476        "contain too many modules. Skip the appropriate ones! You really\n".
5477        "should try these commands right now to make sure everything is\n".
5478        "working properly. Monitoring programs won't work until the needed\n".
5479        "modules are loaded.\n\n";
5480 
5481  my $have_sysconfig = -d '/etc/sysconfig';
5482  printf "Do you want to \%s /etc/sysconfig/lm_sensors? (\%s): ",
5483         (-e '/etc/sysconfig/lm_sensors' ? 'overwrite' : 'generate'),
5484         ($have_sysconfig ? 'YES/no' : 'yes/NO');
5485  $_ = <STDIN>;
5486  if (($have_sysconfig and not m/^\s*n/i) or m/^\s*y/i) {
5487    unless ($have_sysconfig) {
5488      mkdir '/etc/sysconfig', 0777
5489        or die "Sorry, can't create /etc/sysconfig ($!)";
5490    }
5491    open(local *SYSCONFIG, ">/etc/sysconfig/lm_sensors")
5492      or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)";
5493    print SYSCONFIG <<'EOT';
5494#    /etc/sysconfig/lm_sensors - Defines modules loaded by
5495#                                /etc/init.d/lm_sensors
5496#    Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>
5497#
5498#    This program is free software; you can redistribute it and/or modify
5499#    it under the terms of the GNU General Public License as published by
5500#    the Free Software Foundation; either version 2 of the License, or
5501#    (at your option) any later version.
5502#
5503#    This program is distributed in the hope that it will be useful,
5504#    but WITHOUT ANY WARRANTY; without even the implied warranty of
5505#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5506#    GNU General Public License for more details.
5507#
5508#    You should have received a copy of the GNU General Public License
5509#    along with this program; if not, write to the Free Software
5510#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5511#
5512#
5513# See also the lm_sensors homepage at:
5514#     http://www.lm-sensors.org/
5515#
5516# This file is used by /etc/init.d/lm_sensors and defines the modules to
5517# be loaded/unloaded. This file is sourced into /etc/init.d/lm_sensors.
5518#
5519# The format of this file is a shell script that simply defines the modules
5520# in order as normal variables with the special names:
5521#    MODULE_0, MODULE_1, MODULE_2, etc.
5522#
5523# List the modules that are to be loaded for your system
5524#
5525EOT
5526    print SYSCONFIG
5527      "# Generated by sensors-detect on " . scalar localtime() . "\n";
5528    my @modules = grep /^modprobe /, split "\n", $modprobes;
5529    my $i = 0;
5530    my $sysconfig = "";
5531    foreach (@modules) {
5532      s/^modprobe //;
5533      $sysconfig .= "MODULE_$i=$_\n";
5534      $i++;
5535    }
5536    print SYSCONFIG $sysconfig;
5537
5538    print "Copy prog/init/lm_sensors.init to /etc/init.d/lm_sensors\n".
5539          "for initialization at boot time.\n"
5540      unless -f "/etc/init.d/lm_sensors";
5541  }
5542}
5543
5544main;
Note: See TracBrowser for help on using the browser.