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

Revision 4241, 169.6 KB (checked in by khali, 7 years ago)

Add Fintek F71882FG detection. The EPoX EP1308 appears to be a clone
of this chip (same ID, same register map.)

  • 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 @cpu_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 => "Philips Semiconductors SAA1064",
1389       driver => "saa1064",
1390       i2c_addrs => [0x38..0x3b],
1391       i2c_detect => sub { saa1064_detect(@_); },
1392     },
1393     {
1394       name => "Philips Semiconductors PCA9540",
1395       driver => "pca9540",
1396       i2c_addrs => [0x70],
1397       i2c_detect => sub { pca9540_detect(@_); },
1398     },
1399     {
1400       name => "Philips Semiconductors PCA9556",
1401       driver => "to-be-written",
1402       i2c_addrs => [0x18..0x1f],
1403       i2c_detect => sub { pca9556_detect(@_); },
1404     },
1405     {
1406       name => "Maxim MAX6900",
1407       driver => "to-be-written",
1408       i2c_addrs => [0x50],
1409       i2c_detect => sub { max6900_detect(@_); },
1410     },
1411     {
1412       name => "SMBus 2.0 ARP-Capable Device",
1413       driver => "not-a-sensor",
1414       i2c_addrs => [0x61],
1415       i2c_detect => sub { arp_detect(@_); },
1416     },
1417     {
1418       name => "IPMI BMC KCS",
1419       driver => "bmcsensors",
1420       isa_addrs => [ 0x0ca0 ],
1421       isa_detect => sub { ipmi_kcs_detect(@_); },
1422     },
1423     {
1424       name => "IPMI BMC SMIC",
1425       driver => "bmcsensors",
1426       isa_addrs => [ 0x0ca8 ],
1427       isa_detect => sub { ipmi_smic_detect(@_); },
1428     },
1429     {
1430       name => "Smart Battery Charger",
1431       driver => "to-be-written",
1432       i2c_addrs => [0x09],
1433       i2c_detect => sub { smartbatt_chgr_detect(@_); },
1434     },
1435     {
1436       name => "Smart Battery Manager/Selector",
1437       driver => "to-be-written",
1438       i2c_addrs => [0x0a],
1439       i2c_detect => sub { smartbatt_mgr_detect(@_); },
1440     },
1441     {
1442       name => "Smart Battery",
1443       driver => "smartbatt",
1444       i2c_addrs => [0x0b],
1445       i2c_detect => sub { smartbatt_detect(@_); },
1446     },
1447);
1448
1449# Special case chip information goes here and would be included in
1450# the chip_special_cases routine below
1451use vars qw($chip_kern24_w83791d $chip_kern26_w83791d);
1452$chip_kern24_w83791d = {
1453        name => "Winbond W83791D",
1454        driver => "w83781d",
1455        i2c_addrs => [0x2c..0x2f],
1456        i2c_detect => sub { w83781d_detect(7, @_); },
1457};
1458
1459$chip_kern26_w83791d = {
1460        name => "Winbond W83791D",
1461        driver => "w83791d",
1462        i2c_addrs => [0x2c..0x2f],
1463        i2c_detect => sub { w83781d_detect(7, @_); },
1464};
1465
1466# This is a list of all recognized superio chips.
1467# Each entry must have the following fields:
1468#  name: The full chip name
1469#  driver: The driver name (without .o extension). Put in
1470#      "to-be-written" if it is not yet available.
1471#      Put in "not-a-sensor" if the chip doesn't have hardware monitoring
1472#      capabilities (listing such chips here removes the need of manual
1473#      lookup when people report them).
1474#  devid: The device ID(s) we have to match (base device)
1475#  devid_mask (optional): Bitmask to apply before checking the device ID
1476#  logdev: The logical device containing the sensors
1477#  alias_detect (optional): For chips which can be both on the ISA and the
1478#      I2C bus, a function which detectes whether two entries are the same.
1479#      The function should take three parameters: The ISA address, the
1480#      I2C bus number, and the I2C address.
1481# Entries are grouped by family. Each family entry has the following fields:
1482#  family: The family name
1483#  guess (optional): Typical logical device address. This lets us do
1484#      generic probing if we fail to recognize the chip.
1485#  enter: The password sequence to write to the address register
1486#  chips: Array of chips
1487@superio_ids = (
1488  {
1489    family => "ITE",
1490    guess => 0x290,
1491    enter =>
1492    {
1493      0x2e => [0x87, 0x01, 0x55, 0x55],
1494      0x4e => [0x87, 0x01, 0x55, 0xaa],
1495    },
1496    chips =>
1497    [
1498      {
1499        name => "ITE IT8702F Super IO Sensors",
1500        driver => "to-be-written",
1501        devid => 0x8702,
1502        logdev => 0x04,
1503      },
1504      {
1505        name => "ITE IT8705F Super IO Sensors",
1506        driver => "it87",
1507        devid => 0x8705,
1508        logdev => 0x04,
1509      },
1510      {
1511        name => "ITE IT8712F Super IO Sensors",
1512        driver => "it87",
1513        devid => 0x8712,
1514        logdev => 0x04,
1515        alias_detect => sub { ite_alias_detect(0, @_); },
1516      },
1517      {
1518        name => "ITE IT8716F Super IO Sensors",
1519        driver => "it87",
1520        devid => 0x8716,
1521        logdev => 0x04,
1522      },
1523      {
1524        name => "ITE IT8718F Super IO Sensors",
1525        driver => "it87",
1526        devid => 0x8718,
1527        logdev => 0x04,
1528      },
1529    ],
1530  },
1531  {
1532    family => "National Semiconductor",
1533    enter =>
1534    {
1535      0x2e => [],
1536      0x4e => [],
1537    },
1538    chips =>
1539    [
1540      {
1541        name => "Nat. Semi. PC87351 Super IO Fan Sensors",
1542        driver => "to-be-written",
1543        devid => 0xe2,
1544        logdev => 0x08,
1545      },
1546      {
1547        name => "Nat. Semi. PC87360 Super IO Fan Sensors",
1548        driver => "pc87360",
1549        devid => 0xe1,
1550        logdev => 0x09,
1551      },
1552      {
1553        name => "Nat. Semi. PC87363 Super IO Fan Sensors",
1554        driver => "pc87360",
1555        devid => 0xe8,
1556        logdev => 0x09,
1557      },
1558      {
1559        name => "Nat. Semi. PC87364 Super IO Fan Sensors",
1560        driver => "pc87360",
1561        devid => 0xe4,
1562        logdev => 0x09,
1563      },
1564      {
1565        name => "Nat. Semi. PC87365 Super IO Fan Sensors",
1566        driver => "pc87360",
1567        devid => 0xe5,
1568        logdev => 0x09,
1569      },
1570      {
1571        name => "Nat. Semi. PC87365 Super IO Voltage Sensors",
1572        driver => "pc87360",
1573        devid => 0xe5,
1574        logdev => 0x0d,
1575      },
1576      {
1577        name => "Nat. Semi. PC87365 Super IO Thermal Sensors",
1578        driver => "pc87360",
1579        devid => 0xe5,
1580        logdev => 0x0e,
1581      },
1582      {
1583        name => "Nat. Semi. PC87366 Super IO Fan Sensors",
1584        driver => "pc87360",
1585        devid => 0xe9,
1586        logdev => 0x09,
1587      },
1588      {
1589        name => "Nat. Semi. PC87366 Super IO Voltage Sensors",
1590        driver => "pc87360",
1591        devid => 0xe9,
1592        logdev => 0x0d,
1593      },
1594      {
1595        name => "Nat. Semi. PC87366 Super IO Thermal Sensors",
1596        driver => "pc87360",
1597        devid => 0xe9,
1598        logdev => 0x0e,
1599      },
1600      {
1601        name => "Nat. Semi. PC87372 Super IO Fan Sensors",
1602        driver => "to-be-written",
1603        devid => 0xf0,
1604        logdev => 0x09,
1605      },
1606      {
1607        name => "Nat. Semi. PC87373 Super IO Fan Sensors",
1608        driver => "to-be-written",
1609        devid => 0xf3,
1610        logdev => 0x09,
1611      },
1612      {
1613        name => "Nat. Semi. PC87591 Super IO",
1614        driver => "to-be-written",
1615        devid => 0xec,
1616        logdev => 0x0f,
1617      },
1618      {
1619        name => "Nat. Semi. PC87371 Super IO",
1620        driver => "not-a-sensor",
1621        devid => 0xd0,
1622      },
1623      {
1624        name => "Nat. Semi. PC97371 Super IO",
1625        driver => "not-a-sensor",
1626        devid => 0xdf,
1627      },
1628      {
1629        name => "Nat. Semi. PC8739x Super IO",
1630        driver => "not-a-sensor",
1631        devid => 0xea,
1632      },
1633      {
1634        name => "Nat. Semi. PC8741x Super IO",
1635        driver => "not-a-sensor",
1636        devid => 0xee,
1637      },
1638      {
1639        name => "Nat. Semi. PC87427 Super IO Fan Sensors",
1640        driver => "pc87427",
1641        devid => 0xf2,
1642        logdev => 0x09,
1643      },
1644      {
1645        name => "Nat. Semi. PC87427 Super IO Health Sensors",
1646        driver => "to-be-written",
1647        devid => 0xf2,
1648        logdev => 0x14,
1649      },
1650    ],
1651  },
1652  {
1653    family => "SMSC",
1654    enter =>
1655    {
1656      0x2e => [0x55],
1657      0x4e => [0x55],
1658    },
1659    chips =>
1660    [
1661      {
1662        name => "SMSC LPC47B27x Super IO Fan Sensors",
1663        driver => "smsc47m1",
1664        devid => 0x51,
1665        logdev => 0x0a,
1666      },
1667      {
1668        name => "SMSC LPC47M10x/112/13x Super IO Fan Sensors",
1669        driver => "smsc47m1",
1670        devid => 0x59,
1671        logdev => 0x0a,
1672      },
1673      {
1674        name => "SMSC LPC47M14x Super IO Fan Sensors",
1675        driver => "smsc47m1",
1676        devid => 0x5f,
1677        logdev => 0x0a,
1678      },
1679      {
1680        name => "SMSC LPC47M15x/192/997 Super IO Fan Sensors",
1681        driver => "smsc47m1",
1682        devid => 0x60,
1683        logdev => 0x0a,
1684      },
1685      {
1686        name => "SMSC LPC47S42x Super IO Fan Sensors",
1687        driver => "to-be-written",
1688        devid => 0x57,
1689        logdev => 0x0a,
1690      },
1691      {
1692        name => "SMSC LPC47S45x Super IO Fan Sensors",
1693        driver => "to-be-written",
1694        devid => 0x62,
1695        logdev => 0x0a,
1696      },
1697      {
1698        name => "SMSC LPC47M172 Super IO Fan Sensors",
1699        driver => "to-be-written",
1700        devid => 0x14,
1701        logdev => 0x0a,
1702      },
1703      {
1704        name => "SMSC LPC47M182 Super IO Fan Sensors",
1705        driver => "to-be-written",
1706        devid => 0x74,
1707        logdev => 0x0a,
1708      },
1709      {
1710        name => "SMSC LPC47B397-NC Super IO",
1711        driver => "smsc47b397",
1712        devid => 0x6f,
1713        logdev => 0x08,
1714      },
1715      {
1716        name => "SMSC SCH5307-NS Super IO",
1717        driver => "smsc47b397",
1718        devid => 0x81,
1719        logdev => 0x08,
1720      },
1721      {
1722        name => "SMSC LPC47M584-NC Super IO",
1723        # No datasheet
1724        devid => 0x76,
1725      },
1726      {
1727        name => "SMSC DME1737 Super IO",
1728        # Hardware monitoring features are accessed on the SMBus
1729        driver => "not-a-sensor",
1730        devid => 0x78,
1731      },
1732    ],
1733  },
1734  {
1735    family => "VIA/Winbond/Fintek",
1736    guess => 0x290,
1737    enter =>
1738    {
1739      0x2e => [0x87, 0x87],
1740      0x4e => [0x87, 0x87],
1741    },
1742    chips =>
1743    [
1744      {
1745        name => "VIA VT1211 Super IO Sensors",
1746        driver => "vt1211",
1747        devid => 0x3c,
1748        logdev => 0x0b,
1749        alias_detect => sub { vt1211_alias_detect(0, @_); },
1750      },
1751      {
1752        name => "Winbond W83627HF Super IO Sensors",
1753        driver => "w83627hf",
1754        devid => 0x52,
1755        logdev => 0x0b,
1756      },
1757      {
1758        name => "Winbond W83627THF Super IO Sensors",
1759        driver => "w83627hf",
1760        devid => 0x82,
1761        logdev => 0x0b,
1762      },
1763      {
1764        name => "Winbond W83637HF Super IO Sensors",
1765        driver => "w83627hf",
1766        devid => 0x70,
1767        logdev => 0x0b,
1768      },
1769      {
1770        name => "Winbond W83687THF Super IO Sensors",
1771        driver => "w83627hf",
1772        devid => 0x85,
1773        logdev => 0x0b,
1774      },
1775      {
1776        name => "Winbond W83697HF Super IO Sensors",
1777        driver => "w83627hf",
1778        devid => 0x60,
1779        logdev => 0x0b,
1780      },
1781      {
1782        name => "Winbond W83697SF/UF Super IO PWM",
1783        driver => "to-be-written",
1784        devid => 0x68,
1785        logdev => 0x0b,
1786      },
1787      {
1788        name => "Winbond W83627EHF/EHG Super IO Sensors",
1789        driver => "w83627ehf",
1790        # W83627EHF datasheet says 0x886x but 0x8853 was seen, thus the
1791        # broader mask. W83627EHG was seen with ID 0x8863.
1792        devid => 0x8840,
1793        devid_mask => 0xFFC0,
1794        logdev => 0x0b,
1795        alias_detect => sub { w83781d_alias_detect(9, @_); },
1796      },
1797      {
1798        name => "Winbond W83627DHG Super IO Sensors",
1799        driver => "w83627ehf",
1800        devid => 0xA020,
1801        devid_mask => 0xFFF0,
1802        logdev => 0x0b,
1803        alias_detect => sub { w83781d_alias_detect(10, @_); },
1804      },
1805      {
1806        name => "Winbond W83L517D Super IO",
1807        driver => "not-a-sensor",
1808        devid => 0x61,
1809      },
1810      {
1811        name => "Fintek F71805F/FG Super IO Sensors",
1812        driver => "f71805f",
1813        devid => 0x0406,
1814        logdev => 0x04,
1815      },
1816      {
1817        name => "Fintek F71872F/FG Super IO Sensors",
1818        driver => "f71805f",
1819        devid => 0x0341,
1820        logdev => 0x04,
1821      },
1822      {
1823        name => "Fintek F81218D Super IO",
1824        driver => "not-a-sensor",
1825        devid => 0x0206,
1826      },
1827      {
1828        name => "Fintek F71882FG Super IO Sensors",
1829        driver => "to-be-written",
1830        devid => 0x0541,
1831        logdev => 0x04,
1832      },
1833      {
1834        # Shouldn't be in this family, but seems to be still.
1835        name => "ITE IT8708F Super IO",
1836        driver => "not-a-sensor",
1837        devid => 0x8708,
1838      },
1839    ],
1840  },
1841);
1842
1843# Drivers for CPU embedded sensors
1844# Each entry must have the following fields:
1845#  name: The CPU family name
1846#  driver: The driver name. Put "to-be-written" if no driver is available.
1847#  detect: Detection callback function. No parameter will be passed to
1848#          this function, it must use global lists of PCI devices, CPU,
1849#          etc. It must return a confidence value, undef if no supported
1850#          CPU is found.
1851@cpu_ids = (
1852  {
1853    name => "AMD K8 thermal sensors",
1854    driver => "k8temp",
1855    detect => sub { k8temp_pci_detect(); },
1856  },
1857  {
1858    name => "Intel Core family thermal sensor",
1859    driver => "coretemp",
1860    detect => sub { coretemp_detect(); },
1861  },
1862);
1863
1864#######################
1865# AUXILIARY FUNCTIONS #
1866#######################
1867
1868sub swap_bytes
1869{
1870  return (($_[0] & 0xff00) >> 8) + (($_[0] & 0x00ff) << 8)
1871}
1872
1873# $_[0] is the sought value
1874# @_[1..] is the list to seek in
1875# Returns: 0 on failure, 1 if found.
1876# Note: Every use of this sub probably indicates the use of the wrong
1877#       datastructure
1878sub contains
1879{
1880  my $sought = shift;
1881  foreach (@_) {
1882    return 1 if $sought eq $_;
1883  }
1884  return 0;
1885}
1886
1887sub parse_not_to_scan
1888{
1889  my ($min,$max,$to_parse) = @_;
1890  my @ranges = split /\s*,\s*/, $to_parse;
1891  my @res;
1892  my $range;
1893  foreach $range (@ranges) {
1894    my ($start,$end) = split /\s*-s*/, $range;
1895    $start = oct $start if $start =~ /^0/;
1896    if (defined $end) {
1897      $end = oct $end if $end =~ /^0/;
1898      $start = $min if $start < $min;
1899      $end = $max if $end > $max;
1900      push @res, ($start+0..$end+0);
1901    } else {
1902      push @res, $start+0 if $start >= $min and $start <= $max;
1903    }
1904  }
1905  return sort { $a <=> $b } @res;
1906}
1907
1908# @_[0]: Reference to list 1
1909# @_[1]: Reference to list 2
1910# Result: 0 if they have no elements in common, 1 if they have
1911# Elements must be numeric.
1912sub any_list_match
1913{
1914  my ($list1,$list2) = @_;
1915  my ($el1,$el2);
1916  foreach $el1 (@$list1) {
1917    foreach $el2 (@$list2) {
1918      return 1 if $el1 == $el2;
1919    }
1920  }
1921  return 0;
1922}
1923
1924###################
1925# I/O port access #
1926###################
1927
1928sub initialize_ioports
1929{
1930  sysopen (IOPORTS, "/dev/port", O_RDWR)
1931    or die "/dev/port: $!\n";
1932  binmode IOPORTS;
1933}
1934
1935sub close_ioports
1936{
1937  close (IOPORTS)
1938    or print "Warning: $!\n";
1939}
1940
1941# $_[0]: port to read
1942# Returns: -1 on failure, read value on success.
1943sub inb
1944{
1945  my ($res,$nrchars);
1946  sysseek IOPORTS, $_[0], 0 or return -1;
1947  $nrchars = sysread IOPORTS, $res, 1;
1948  return -1 if not defined $nrchars or $nrchars != 1;
1949  $res = unpack "C",$res ;
1950  return $res;
1951}
1952
1953# $_[0]: port to write
1954# $_[1]: value to write
1955# Returns: -1 on failure, 0 on success.
1956sub outb
1957{
1958  if ($_[1] > 0xff)
1959  {
1960    my ($package, $filename, $line, $sub) = caller(1);
1961    print "\n*** Called outb with value=$_[1] from line $line\n",
1962          "*** (in $sub). PLEASE REPORT!\n",
1963          "*** Terminating.\n";
1964    exit(-1);
1965  }
1966  my $towrite = pack "C", $_[1];
1967  sysseek IOPORTS, $_[0], 0 or return -1;
1968  my $nrchars = syswrite IOPORTS, $towrite, 1;
1969  return -1 if not defined $nrchars or $nrchars != 1;
1970  return 0;
1971}
1972
1973# $_[0]: Address register
1974# $_[1]: Data register
1975# $_[2]: Register to read
1976# Returns: read value
1977sub isa_read_byte
1978{
1979  outb $_[0],$_[2];
1980  return inb $_[1];
1981}
1982
1983# $_[0]: Address register
1984# $_[1]: Data register
1985# $_[2]: Register to write
1986# $_[3}: Value to write
1987# Returns: nothing
1988sub isa_write_byte
1989{
1990  outb $_[0],$_[2];
1991  outb $_[1],$_[3];
1992}
1993
1994#################
1995# AUTODETECTION #
1996#################
1997
1998use vars qw($modules_conf $dev_i2c $sysfs_root);
1999
2000sub initialize_conf
2001{
2002  my $use_devfs = 0;
2003  open(local *INPUTFILE, "/proc/mounts") or die "Can't access /proc/mounts!";
2004  local $_;
2005  while (<INPUTFILE>) {
2006    if (m@^\w+ /dev devfs @) {
2007      $use_devfs = 1;
2008      $dev_i2c = '/dev/i2c/';
2009    }
2010    if (m@^\S+ (/\w+) sysfs @) {
2011      $sysfs_root = $1;
2012    }
2013  }
2014  close INPUTFILE;
2015
2016  my $use_udev = 0;
2017  if (open(*INPUTFILE, '/etc/udev/udev.conf')) {
2018    while (<INPUTFILE>) {
2019      if (m/^\s*udev_db\s*=\s*\"([^"]*)\"/ || m/^\s*udev_db\s*=\s*(\S+)/) {
2020        if (-e $1) {
2021          $use_udev = 1;
2022          $dev_i2c = '/dev/i2c-';
2023        }
2024        last;
2025      }
2026    }
2027    close INPUTFILE;
2028  }
2029 
2030  if (!$use_udev) {
2031    # Try some known default udev db locations, just in case
2032    if (-e '/dev/.udev.tdb' || -e '/dev/.udev'
2033     || -e '/dev/.udevdb') {
2034      $use_udev = 1;
2035      $dev_i2c = '/dev/i2c-';
2036    }
2037  }
2038
2039  if (-f '/etc/modules.conf') {
2040    $modules_conf = '/etc/modules.conf';
2041  } elsif (-f '/etc/conf.modules') {
2042    $modules_conf = '/etc/conf.modules';
2043  } else { # default
2044    $modules_conf = '/etc/modules.conf';
2045  }
2046
2047  if (!($use_devfs || $use_udev)) {
2048    if (-c '/dev/i2c-0') {
2049      $dev_i2c = '/dev/i2c-';
2050    } else { # default
2051      print "No i2c device files found. Use prog/mkdev/mkdev.sh to create them.\n";
2052      exit -1;
2053    }
2054  }
2055}
2056
2057# [0] -> VERSION
2058# [1] -> PATCHLEVEL
2059# [2] -> SUBLEVEL
2060# [3] -> EXTRAVERSION
2061#
2062use vars qw(@kernel_version);
2063
2064sub initialize_kernel_version
2065{
2066  `uname -r` =~ /(\d+)\.(\d+)\.(\d+)(.*)/;
2067  @kernel_version = ($1, $2, $3, $4);
2068}
2069
2070sub kernel_version_at_least
2071{
2072  my ($vers, $plvl, $slvl) = @_;
2073  return 1 if ($kernel_version[0]  > $vers ||
2074                ($kernel_version[0] == $vers && 
2075                  ($kernel_version[1]  > $plvl || 
2076                    ($kernel_version[1] == $plvl && 
2077                      ($kernel_version[2] >= $slvl)))));
2078  return 0;
2079}
2080
2081# @cpu is a list of reference to hashes, one hash per CPU.
2082# Each entry has the following keys: vendor_id, cpu family, model,
2083# model name and stepping, directly taken from /proc/cpuinfo.
2084use vars qw(@cpu);
2085
2086sub initialize_cpu_list
2087{
2088  open(local *INPUTFILE, "/proc/cpuinfo") or die "Can't access /proc/cpuinfo!";
2089  local $_;
2090  my %entry;
2091  while (<INPUTFILE>) {
2092    if (m/^processor\s*:\s*(\d+)/) {
2093      push @cpu, \%entry if scalar keys(%entry); # Previous entry
2094      %entry = (); # New entry
2095      next;
2096    }
2097    if (m/^(vendor_id|cpu family|model|model name|stepping)\s*:\s*(.+)$/) {
2098      my $k = $1;
2099      my $v = $2;
2100      $v =~ s/\s+/ /g;  # Merge multiple spaces
2101      $v =~ s/ $//;     # Trim trailing space
2102      $entry{$k} = $v;
2103      next;
2104    }
2105  }
2106  push @cpu, \%entry if scalar keys(%entry); # Last entry
2107  close INPUTFILE;
2108}
2109
2110###########
2111# MODULES #
2112###########
2113
2114use vars qw(%modules_list %modules_supported);
2115
2116sub initialize_modules_list
2117{
2118  open(local *INPUTFILE, "/proc/modules") or return;
2119  local $_;
2120  while (<INPUTFILE>) {
2121    tr/_/-/;
2122    $modules_list{$1} = 1 if m/^(\S*)/;
2123  }
2124}
2125
2126sub initialize_modules_supported
2127{
2128  foreach my $chip (@chip_ids) {
2129    $modules_supported{$chip->{driver}}++;
2130  }
2131}
2132
2133#################
2134# SYSFS HELPERS #
2135#################
2136
2137# From a sysfs device path, return the driver name, or undef
2138sub sysfs_device_driver($)
2139{
2140  my $device = shift;
2141 
2142  my $link = readlink("$device/driver");
2143  return unless defined $link;
2144  return basename($link);
2145}
2146
2147# From a sysfs device path and an attribute name, return the attribute
2148# value, or undef
2149sub sysfs_device_attribute($$)
2150{
2151  my ($device, $attr) = @_;
2152  my $value;
2153
2154  open(local *FILE, "$device/$attr") or return;
2155  return unless defined($value = <FILE>);
2156  close(FILE);
2157
2158  chomp($value);
2159  return $value;
2160}
2161
2162##############
2163# PCI ACCESS #
2164##############
2165
2166use vars qw(%pci_list);
2167
2168# This function returns a list of hashes. Each hash has some PCI information:
2169# 'domain', 'bus', 'slot' and 'func' uniquely identify a PCI device in a
2170# computer; 'vendid' and 'devid' uniquely identify a type of device.
2171# 'class' lets us spot unknown SMBus adapters.
2172# This function is used when sysfs is available (Linux 2.6).
2173sub read_sys_dev_pci($)
2174{
2175  my $devices = shift;
2176  my ($dev, @pci_list);
2177
2178  opendir(local *DEVICES, "$devices")
2179    or die "$devices: $!";
2180
2181  while (defined($dev = readdir(DEVICES))) {
2182    my %record;
2183    next unless $dev =~
2184      m/^(?:([\da-f]+):)?([\da-f]+):([\da-f]+)\.([\da-f]+)$/;
2185
2186    $record{domain} = hex $1;
2187    $record{bus} = hex $2;
2188    $record{slot} = hex $3;
2189    $record{func} = hex $4;
2190
2191    $record{vendid} = oct sysfs_device_attribute("$devices/$dev", "vendor");
2192    $record{devid} = oct sysfs_device_attribute("$devices/$dev", "device");
2193    $record{class} = (oct sysfs_device_attribute("$devices/$dev", "class"))
2194                     >> 8;
2195
2196    push @pci_list, \%record;
2197  }
2198
2199  return \@pci_list;
2200}
2201
2202# This function returns a list of hashes. Each hash has some PCI information:
2203# 'bus', 'slot' and 'func' uniquely identify a PCI device in a computer;
2204# 'vendid' and 'devid' uniquely identify a type of device.
2205# This function is used when sysfs is not available (Linux 2.4).
2206sub read_proc_dev_pci
2207{
2208  my ($dfn, $vend, @pci_list);
2209  open(local *INPUTFILE, "/proc/bus/pci/devices")
2210    or die "/proc/bus/pci/devices: $!";
2211  local $_;
2212  while (<INPUTFILE>) {
2213    my %record;
2214    ($dfn, $vend) = map { hex } (split) [0..1];
2215    $record{bus} = $dfn >> 8;
2216    $record{slot} = ($dfn & 0xf8) >> 3;
2217    $record{func} = $dfn & 0x07;
2218    $record{vendid} = $vend >> 16;
2219    $record{devid} = $vend & 0xffff;
2220   
2221    push @pci_list, \%record;
2222  }
2223  return \@pci_list;
2224}
2225
2226sub initialize_proc_pci
2227{
2228  my $pci_list;
2229
2230  if (defined $sysfs_root) {
2231    $pci_list = read_sys_dev_pci("$sysfs_root/bus/pci/devices");
2232  } else {
2233    $pci_list = read_proc_dev_pci();
2234  }
2235
2236  # Note that we lose duplicate devices at this point, but we don't
2237  # really care. What matters to us is which unique devices are present,
2238  # not how many of each.
2239  %pci_list = map {
2240    sprintf("%04x:%04x", $_->{vendid}, $_->{devid}) => $_
2241  } @{$pci_list};
2242}
2243
2244#####################
2245# ADAPTER DETECTION #
2246#####################
2247
2248sub adapter_pci_detection_sis_96x
2249{
2250  my $driver="";
2251
2252  # first, determine which driver if any...
2253  if (kernel_version_at_least(2,6,0)) {
2254    if (exists $pci_list{"1039:0016"}) {
2255      $driver = "i2c-sis96x";
2256    } elsif (exists $pci_list{"1039:0008"}) {
2257      $driver = "i2c-sis5595";
2258    }
2259  } elsif (kernel_version_at_least(2,4,0)) {
2260    if (exists $pci_list{"1039:0008"}) {
2261      if ((exists $pci_list{"1039:0645"}) ||
2262          (exists $pci_list{"1039:0646"}) ||
2263          (exists $pci_list{"1039:0648"}) ||
2264          (exists $pci_list{"1039:0650"}) ||
2265          (exists $pci_list{"1039:0651"}) ||
2266          (exists $pci_list{"1039:0655"}) ||
2267          (exists $pci_list{"1039:0661"}) ||
2268          (exists $pci_list{"1039:0735"}) ||
2269          (exists $pci_list{"1039:0745"}) ||
2270          (exists $pci_list{"1039:0746"})) {
2271        $driver = "i2c-sis645";
2272      } else {
2273        $driver = "i2c-sis5595";
2274      }
2275    } elsif ((exists $pci_list{"1039:0016"}) ||
2276             (exists $pci_list{"1039:0018"})) {
2277      $driver = "i2c-sis645";
2278    }
2279  }
2280
2281  # then, add the appropriate entries to @pci_adapters
2282  if ($driver eq "i2c-sis5595") {
2283    push @pci_adapters, @pci_adapters_sis5595;
2284  } elsif ($driver eq "i2c-sis645") {
2285    push @pci_adapters, @pci_adapters_sis645;
2286  } elsif ($driver eq "i2c-sis96x") {
2287    push @pci_adapters, @pci_adapters_sis96x;
2288  }
2289}
2290
2291# Build and return a PCI device's bus ID
2292sub pci_busid($)
2293{
2294  my $device = shift;
2295  my $busid;
2296
2297  $busid = sprintf("\%02x:\%02x.\%x",
2298                   $device->{bus}, $device->{slot}, $device->{func});
2299  $busid = sprintf("\%04x:", $device->{domain}) . $busid
2300    if defined $device->{domain};
2301
2302  return $busid;
2303}
2304
2305sub adapter_pci_detection
2306{
2307  my ($key, $device, $try, @res, %smbus);
2308  print "Probing for PCI bus adapters...\n";
2309
2310  # Custom detection routine for some SiS chipsets
2311  adapter_pci_detection_sis_96x();
2312
2313  # Build a list of detected SMBus devices
2314  foreach $key (keys %pci_list) {
2315    $device = $pci_list{$key};
2316    $smbus{$key}++
2317      if exists $device->{class} && $device->{class} == 0x0c05; # SMBus
2318  }
2319
2320  # Loop over the known I2C/SMBus adapters
2321  foreach $try (@pci_adapters) {
2322    $key = sprintf("%04x:%04x", $try->{vendid}, $try->{devid});
2323    if (exists $pci_list{$key}) {
2324        $device = $pci_list{$key};
2325        printf "Use driver `\%s' for device \%s: \%s\n",
2326               $try->{driver}, pci_busid($device), $try->{procid};
2327        if ($try->{driver} eq "to-be-tested") {
2328          print "\nWe are currently looking for testers for this adapter!\n".
2329                "Please check http://www.lm-sensors.org/wiki/Devices\n".
2330                "and/or contact us if you want to help.\n\n";
2331          print "Continue... ";
2332          <STDIN>;
2333          print "\n";
2334        }
2335        push @res,$try->{driver};
2336
2337        # Delete from detected SMBus device list
2338        delete $smbus{$key};
2339    }
2340  }
2341
2342  # Now see if there are unknown SMBus devices left
2343  foreach $key (keys %smbus) {
2344    $device = $pci_list{$key};
2345    printf "Found unknown SMBus adapter \%04x:\%04x at \%s.\n",
2346           $device->{vendid}, $device->{devid}, pci_busid($device);
2347  }
2348 
2349  if (! @res) {
2350    print "Sorry, no known PCI bus adapters found.\n";
2351  }
2352  return @res;
2353}
2354
2355# $_[0]: Adapter description as found in /proc/bus/i2c
2356sub find_adapter_driver
2357{
2358  my $adapter;
2359  for $adapter (@pci_adapters) {
2360    return $adapter->{driver}
2361      if (exists $adapter->{match} && $_[0] =~ $adapter->{match});
2362  }
2363  return "UNKNOWN";
2364}
2365
2366#############################
2367# I2C AND SMBUS /DEV ACCESS #
2368#############################
2369
2370# This should really go into a separate module/package.
2371
2372# These are copied from <linux/i2c-dev.h>
2373
2374use constant IOCTL_I2C_SLAVE    => 0x0703;
2375use constant IOCTL_I2C_FUNCS    => 0x0705;
2376use constant IOCTL_I2C_SMBUS    => 0x0720;
2377
2378use constant SMBUS_READ         => 1;
2379use constant SMBUS_WRITE        => 0;
2380
2381use constant SMBUS_QUICK        => 0;
2382use constant SMBUS_BYTE         => 1;
2383use constant SMBUS_BYTE_DATA    => 2;
2384use constant SMBUS_WORD_DATA    => 3;
2385
2386use constant I2C_FUNC_SMBUS_QUICK       => 0x00010000;
2387use constant I2C_FUNC_SMBUS_READ_BYTE   => 0x00020000;
2388
2389# Get the i2c adapter's functionalities
2390# $_[0]: Reference to an opened filehandle
2391# Returns: -1 on failure, functionality bitfield on success.
2392sub i2c_get_funcs($)
2393{
2394  my $file = shift;
2395  my $funcs = pack "L", 0; # Allocate space
2396
2397  ioctl $file, IOCTL_I2C_FUNCS, $funcs or return -1;
2398  $funcs = unpack "L", $funcs;
2399
2400  return $funcs;
2401}
2402
2403# Select the device to communicate with through its address.
2404# $_[0]: Reference to an opened filehandle
2405# $_[1]: Address to select
2406# Returns: 0 on failure, 1 on success.
2407sub i2c_set_slave_addr
2408{
2409  my ($file,$addr) = @_;
2410  ioctl $file, IOCTL_I2C_SLAVE, $addr or return 0;
2411  return 1;
2412}
2413
2414# i2c_smbus_access is based upon the corresponding C function (see
2415# <linux/i2c-dev.h>). You should not need to call this directly.
2416# Exact calling conventions are intricate; read i2c-dev.c if you really need
2417# to know.
2418# $_[0]: Reference to an opened filehandle
2419# $_[1]: SMBUS_READ for reading, SMBUS_WRITE for writing
2420# $_[2]: Command (usually register number)
2421# $_[3]: Transaction kind (SMBUS_BYTE, SMBUS_BYTE_DATA, etc.)
2422# $_[4]: Reference to an array used for input/output of data
2423# Returns: 0 on failure, 1 on success.
2424# Note that we need to get back to Integer boundaries through the 'x2'
2425# in the pack. This is very compiler-dependent; I wish there was some other
2426# way to do this.
2427sub i2c_smbus_access
2428{
2429  my ($file,$read_write,$command,$size,$data) = @_;
2430  my $data_array = pack "C32", @$data;
2431  my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
2432  ioctl $file, IOCTL_I2C_SMBUS, $ioctl_data or return 0;
2433  @{$_[4]} = unpack "C32",$data_array;
2434  return 1;
2435}
2436
2437# $_[0]: Reference to an opened filehandle
2438# $_[1]: Either 0 or 1
2439# Returns: -1 on failure, the 0 on success.
2440sub i2c_smbus_write_quick
2441{
2442  my ($file,$value) = @_;
2443  my @data;
2444  i2c_smbus_access $file, $value, 0, SMBUS_QUICK, \@data
2445         or return -1;
2446  return 0;
2447}
2448
2449# $_[0]: Reference to an opened filehandle
2450# Returns: -1 on failure, the read byte on success.
2451sub i2c_smbus_read_byte
2452{
2453  my ($file) = @_;
2454  my @data;
2455  i2c_smbus_access $file, SMBUS_READ, 0, SMBUS_BYTE, \@data
2456         or return -1;
2457  return $data[0];
2458}
2459
2460# $_[0]: Reference to an opened filehandle
2461# $_[1]: Command byte (usually register number)
2462# Returns: -1 on failure, the read byte on success.
2463sub i2c_smbus_read_byte_data
2464{
2465  my ($file,$command) = @_;
2466  my @data;
2467  i2c_smbus_access $file, SMBUS_READ, $command, SMBUS_BYTE_DATA, \@data
2468         or return -1;
2469  return $data[0];
2470}
2471 
2472# $_[0]: Reference to an opened filehandle
2473# $_[1]: Command byte (usually register number)
2474# Returns: -1 on failure, the read word on success.
2475# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2476# this.
2477sub i2c_smbus_read_word_data
2478{
2479  my ($file,$command) = @_;
2480  my @data;
2481  i2c_smbus_access $file, SMBUS_READ, $command, SMBUS_WORD_DATA, \@data
2482         or return -1;
2483  return $data[0] + 256 * $data[1];
2484}
2485
2486# $_[0]: Reference to an opened filehandle
2487# $_[1]: Address
2488# $_[2]: Functionalities of this i2c adapter
2489# Returns: 1 on successful probing, 0 else.
2490# This function is meant to prevent AT24RF08 corruption and write-only
2491# chips locks. This is done by choosing the best probing method depending
2492# on the address range.
2493sub i2c_probe($$$)
2494{
2495  my ($file, $addr, $funcs) = @_;
2496  my $data = [];
2497  if (($addr >= 0x50 && $addr <= 0x5F)
2498   || ($addr >= 0x30 && $addr <= 0x37)) {
2499    # This covers all EEPROMs we know of, including page protection addresses.
2500    # Note that some page protection addresses will not reveal themselves with
2501    # this, because they ack on write only, but this is probably better since
2502    # some EEPROMs write-protect themselves permanently on almost any write to
2503    # their page protection address.
2504    return 0 unless ($funcs & I2C_FUNC_SMBUS_READ_BYTE);
2505    return i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE, $data);
2506  } else {
2507    return 0 unless ($funcs & I2C_FUNC_SMBUS_QUICK);
2508    return i2c_smbus_access($file, SMBUS_WRITE, 0, SMBUS_QUICK, $data);
2509  }
2510}
2511
2512####################
2513# ADAPTER SCANNING #
2514####################
2515
2516use vars qw(@chips_detected);
2517
2518# We will build a complicated structure @chips_detected here, being:
2519# A list of
2520#  references to hashes
2521#    with field 'driver', being a string with the driver name for this chip;
2522#    with field 'detected'
2523#      being a reference to a list of
2524#        references to hashes of type 'detect_data';
2525#    with field 'misdetected'
2526#      being a reference to a list of
2527#        references to hashes of type 'detect_data'
2528
2529# Type detect_data:
2530# A hash
2531#   with field 'i2c_adap' containing an adapter string as appearing
2532#        in /proc/bus/i2c (if this is an I2C detection)
2533#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
2534#       adapter (if this is an I2C detection)
2535#  with field 'i2c_driver', containing the driver name for this adapter
2536#       (if this is an I2C detection)
2537#  with field 'i2c_addr', containing the I2C address of the detection;
2538#       (if this is an I2C detection)
2539#  with field 'i2c_sub_addrs', containing a reference to a list of
2540#       other I2C addresses (if this is an I2C detection)
2541#  with field 'isa_addr' containing the ISA address this chip is on
2542#       (if this is an ISA detection)
2543#  with field 'conf', containing the confidence level of this detection
2544#  with field 'chipname', containing the chip name
2545
2546# This adds a detection to the above structure. We do no alias detection
2547# here; so you should do ISA detections *after* all I2C detections.
2548# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
2549# In all normal cases, it should be all right.
2550# $_[0]: chip driver
2551# $_[1]: reference to data hash
2552# Returns: Nothing
2553sub add_i2c_to_chips_detected
2554{
2555  my ($chipdriver,$datahash) = @_;
2556  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2557      $main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs,
2558      $do_not_add);
2559
2560  # First determine where the hash has to be added.
2561  for ($i = 0; $i < @chips_detected; $i++) {
2562    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2563  }
2564  if ($i == @chips_detected) {
2565    push @chips_detected, { driver => $chipdriver,
2566                            detected => [],
2567                            misdetected => [] };
2568  }
2569  $new_detected_ref = $chips_detected[$i]->{detected};
2570  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2571
2572  # Find out whether our new entry should go into the detected or the
2573  # misdetected list. We compare all i2c addresses; if at least one matches,
2574  # but our conf value is lower, we assume this is a misdetect.
2575  @hash_addrs = ($datahash->{i2c_addr});
2576  push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
2577       if exists $datahash->{i2c_sub_addrs};
2578  $put_in_detected = 1;
2579  $do_not_add = 0;
2580  FIND_LOOP:
2581  foreach $main_entry (@chips_detected) {
2582    foreach $detected_entry (@{$main_entry->{detected}}) {
2583      @entry_addrs = ($detected_entry->{i2c_addr});
2584      push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
2585               if exists $detected_entry->{i2c_sub_addrs};
2586      if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
2587          any_list_match \@entry_addrs, \@hash_addrs) {
2588        if ($detected_entry->{conf} >= $datahash->{conf}) {
2589          $put_in_detected = 0;
2590        }
2591        if ($chipdriver eq $main_entry->{driver}) {
2592          $do_not_add = 1;
2593        }
2594        last FIND_LOOP;
2595      }
2596    }
2597  }
2598
2599  if ($put_in_detected) {
2600    # Here, we move all entries from detected to misdetected which
2601    # match at least in one main or sub address. This may not be the
2602    # best idea to do, as it may remove detections without replacing
2603    # them with second-best ones. Too bad.
2604    # (Khali 2003-09-13) If the driver is the same, the "misdetected"
2605    # entry is simply deleted; failing to do so cause the configuration
2606    # lines generated later to look very confusing (the driver will
2607    # be told to ignore valid addresses).
2608    @hash_addrs = ($datahash->{i2c_addr});
2609    push @hash_addrs, @{$datahash->{i2c_sub_addrs}} 
2610         if exists $datahash->{i2c_sub_addrs};
2611    foreach $main_entry (@chips_detected) {
2612      $detected_ref = $main_entry->{detected};
2613      $misdetected_ref = $main_entry->{misdetected};
2614      for ($i = @$detected_ref-1; $i >=0; $i--) {
2615        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
2616        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
2617             if exists $detected_ref->[$i]->{i2c_sub_addrs};
2618        if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} and
2619            any_list_match \@entry_addrs, \@hash_addrs) {
2620          push @$misdetected_ref,$detected_ref->[$i]
2621            unless $chipdriver eq $main_entry->{driver};
2622          splice @$detected_ref, $i, 1;
2623        }
2624      }
2625    }
2626
2627    # Now add the new entry to detected
2628    push @$new_detected_ref, $datahash;
2629  } else {
2630    # No hard work here
2631    push @$new_misdetected_ref, $datahash
2632      unless $do_not_add;
2633  }
2634}
2635
2636# This adds a detection to the above structure. We also do alias detection
2637# here; so you should do ISA detections *after* all I2C detections.
2638# $_[0]: alias detection function
2639# $_[1]: chip driver
2640# $_[2]: reference to data hash
2641# Returns: 0 if it is not an alias, datahash reference if it is.
2642sub add_isa_to_chips_detected
2643{
2644  my ($alias_detect,$chipdriver,$datahash) = @_;
2645  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2646      $main_entry,$isalias);
2647
2648  # First determine where the hash has to be added.
2649  $isalias=0;
2650  for ($i = 0; $i < @chips_detected; $i++) {
2651    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2652  }
2653  if ($i == @chips_detected) {
2654    push @chips_detected, { driver => $chipdriver,
2655                            detected => [],
2656                            misdetected => [] };
2657  }
2658  $new_detected_ref = $chips_detected[$i]->{detected};
2659  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2660
2661  # Now, we are looking for aliases. An alias can only be the same chiptype.
2662  # If an alias is found in the misdetected list, we add the new information
2663  # and terminate this function. If it is found in the detected list, we
2664  # still have to check whether another chip has claimed this ISA address.
2665  # So we remove the old entry from the detected list and put it in datahash.
2666
2667  # Misdetected alias detection:
2668  for ($i = 0; $i < @$new_misdetected_ref; $i++) {
2669    if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
2670        not exists $new_misdetected_ref->[$i]->{isa_addr} and
2671        defined $alias_detect and
2672        $new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2673      open(local *FILE, "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}") or
2674        print("Can't open $dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2675        next;
2676      binmode FILE;
2677      i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{i2c_addr} or
2678           print("Can't set I2C address for ",
2679                 "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2680           next;
2681      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2682                          $new_misdetected_ref->[$i]->{i2c_addr})) {
2683        $new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2684        return $new_misdetected_ref->[$i]; 
2685      }
2686    }
2687  }
2688
2689  # Detected alias detection:
2690  for ($i = 0; $i < @$new_detected_ref; $i++) {
2691    if (exists $new_detected_ref->[$i]->{i2c_addr} and
2692        not exists $new_detected_ref->[$i]->{isa_addr} and
2693        defined $alias_detect and
2694        $new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2695      open(local *FILE, "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}") or
2696        print("Can't open $dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2697        next;
2698      binmode FILE;
2699      i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{i2c_addr} or
2700           print("Can't set I2C address for ",
2701                 "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2702           next;
2703      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2704                          $new_detected_ref->[$i]->{i2c_addr})) {
2705        $new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2706        ($datahash) = splice (@$new_detected_ref, $i, 1);
2707        $isalias=1;
2708        last;
2709      }
2710    }
2711  }
2712
2713
2714  # Find out whether our new entry should go into the detected or the
2715  # misdetected list. We only compare main isa_addr here, of course.
2716  # (Khali 2004-05-12) If the driver is the same, the "misdetected"
2717  # entry is simply deleted; same we do for I2C chips.
2718  foreach $main_entry (@chips_detected) {
2719    $detected_ref = $main_entry->{detected};
2720    $misdetected_ref = $main_entry->{misdetected};
2721    for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
2722      if (exists $detected_ref->[$i]->{isa_addr} and
2723          exists $datahash->{isa_addr} and
2724          $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
2725        if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
2726          push @$new_misdetected_ref, $datahash
2727            unless $main_entry->{driver} eq $chipdriver;
2728        } else {
2729          push @$misdetected_ref,$detected_ref->[$i]
2730            unless $main_entry->{driver} eq $chipdriver;
2731          splice @$detected_ref, $i,1;
2732          push @$new_detected_ref, $datahash;
2733        }
2734        if ($isalias) {
2735          return $datahash;
2736        } else {
2737          return 0;
2738        }
2739      }
2740    }
2741  }
2742
2743  # Not found? OK, put it in the detected list
2744  push @$new_detected_ref, $datahash;
2745  if ($isalias) {
2746    return $datahash;
2747  } else {
2748    return 0;
2749  }
2750}
2751
2752# $_[0]: The number of the adapter to scan
2753# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
2754# $_[2]: The driver of the adapter
2755# @_[3]: Addresses not to scan (array reference)
2756sub scan_adapter
2757{
2758  my ($adapter_nr, $adapter_name, $adapter_driver, $not_to_scan) = @_;
2759  my ($funcs, $chip, $addr, $conf, @chips, $new_hash, $other_addr);
2760
2761  # As we modify it, we need a copy
2762  my @not_to_scan = @$not_to_scan;
2763
2764  open(local *FILE, "$dev_i2c$adapter_nr") or 
2765    (print "Can't open $dev_i2c$adapter_nr\n"), return;
2766  binmode FILE;
2767
2768  # Can we probe this adapter?
2769  $funcs = i2c_get_funcs(\*FILE);
2770  if ($funcs < 0) {
2771    print "Adapter failed to provide its functionalities, skipping.\n";
2772    return;
2773  }
2774  if (!($funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) {
2775    print "Adapter cannot be probed, skipping.\n";
2776    return;
2777  }
2778  if (~$funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE)) {
2779    print "Adapter doesn't support all probing functions.\n",
2780          "Some addresses won't be probed.\n";
2781  }
2782
2783  # Now scan each address in turn
2784  foreach $addr (0x03..0x77) {
2785    # As the not_to_scan list is sorted, we can check it fast
2786    if (@not_to_scan and $not_to_scan[0] == $addr) {
2787      shift @not_to_scan;
2788      next;
2789    }
2790
2791    if (!i2c_set_slave_addr(\*FILE, $addr)) {
2792      # If the address is busy, in Linux 2.6 we can find out which driver
2793      # is using it, and we assume it is the right one. In Linux 2.4 we
2794      # just give up and warn the user.
2795      my ($device, $driver);
2796      if (defined($sysfs_root)) {
2797        $device = sprintf("$sysfs_root/bus/i2c/devices/\%d-\%04x",
2798                             $adapter_nr, $addr);
2799        $driver = sysfs_device_driver($device);
2800      }
2801      if (defined($driver)) {
2802        $new_hash = {
2803          conf => 6, # Arbitrary confidence
2804          i2c_addr => $addr,
2805          chipname => sysfs_device_attribute($device, "name") || "unknown",
2806          i2c_adap => $adapter_name,
2807          i2c_driver => $adapter_driver,
2808          i2c_devnr => $adapter_nr,
2809        };
2810
2811        printf "Client found at address 0x\%02x\n", $addr;
2812        printf "Handled by driver `\%s' (already loaded), chip type `\%s'\n",
2813               $driver, $new_hash->{chipname};
2814
2815        # Only add it to the list if this is something we would have
2816        # detected, else we end up with random i2c chip drivers listed
2817        # (for example media/video drivers.)
2818        if (exists $modules_supported{$driver}) {
2819          add_i2c_to_chips_detected($driver, $new_hash);
2820        } else {
2821          print "    (note: this is probably NOT a sensor chip!)\n";
2822        }   
2823      } else {
2824        printf("Client at address 0x%02x can not be probed - ".
2825               "unload all client drivers first!\n", $addr);
2826      }
2827      next;
2828    }
2829
2830    next unless i2c_probe(\*FILE, $addr, $funcs);
2831    printf "Client found at address 0x%02x\n",$addr;
2832
2833    foreach $chip (@chip_ids) {
2834      if (exists $chip->{i2c_addrs} and contains $addr, @{$chip->{i2c_addrs}}) {
2835        printf("\%-60s", sprintf("Probing for `\%s'... ", $chip->{name}));
2836        if (($conf,@chips) = &{$chip->{i2c_detect}} (\*FILE ,$addr)) {
2837          print "Success!\n",
2838                "    (confidence $conf, driver `$chip->{driver}')";
2839          if (@chips) {
2840            print ", other addresses:";
2841            @chips = sort @chips;
2842            foreach $other_addr (sort @chips) {
2843              printf(" 0x%02x",$other_addr);
2844            }
2845          }
2846          printf "\n";
2847          $new_hash = { conf => $conf,
2848                        i2c_addr => $addr,
2849                        chipname => $chip->{name},
2850                        i2c_adap => $adapter_name,
2851                        i2c_driver => $adapter_driver,
2852                        i2c_devnr => $adapter_nr,
2853                      };
2854          if (@chips) {
2855            my @chips_copy = @chips;
2856            $new_hash->{i2c_sub_addrs} = \@chips_copy;
2857          }
2858          add_i2c_to_chips_detected $chip->{driver}, $new_hash;
2859        } else {
2860          print "No\n";
2861        }
2862      }
2863    }
2864  }
2865}
2866
2867sub scan_isa_bus
2868{
2869  my ($chip,$addr,$conf);
2870  foreach $chip (@chip_ids) {
2871    next if not exists $chip->{isa_addrs} or not exists $chip->{isa_detect};
2872    foreach $addr (@{$chip->{isa_addrs}}) {
2873      printf("\%-60s", sprintf("Probing for `\%s'\%s... ", $chip->{name},
2874                               $addr ? sprintf(" at 0x\%x", $addr) : ''));
2875      $conf = &{$chip->{isa_detect}} ($addr);
2876      print("No\n"), next if not defined $conf;
2877      print "Success!\n";
2878      printf "    (confidence %d, driver `%s')\n", $conf, $chip->{driver};
2879      my $new_hash = { conf => $conf,
2880                       isa_addr => $addr,
2881                       chipname => $chip->{name}
2882                     };
2883      $new_hash = add_isa_to_chips_detected $chip->{alias_detect},$chip->{driver},
2884                                            $new_hash;
2885      if ($new_hash) {
2886        printf "    Alias of the chip on I2C bus `%s', address 0x%04x\n",
2887                        $new_hash->{i2c_adap},$new_hash->{i2c_addr};
2888      }
2889    }
2890  }
2891}
2892
2893use vars qw(%superio);
2894
2895# The following are taken from the PNP ISA spec (so it's supposed
2896# to be common to all Super I/O chips):
2897#  devidreg: The device ID register(s)
2898#  logdevreg: The logical device register
2899#  actreg: The activation register within the logical device
2900#  actmask: The activation bit in the activation register
2901#  basereg: The I/O base register within the logical device
2902%superio = (
2903  devidreg => 0x20,
2904  logdevreg => 0x07,
2905  actreg => 0x30,
2906  actmask => 0x01,
2907  basereg => 0x60,
2908);
2909
2910sub exit_superio
2911{
2912  my ($addrreg, $datareg) = @_;
2913
2914  # Some chips (SMSC, Winbond) want this
2915  outb($addrreg, 0xaa);
2916
2917  # Return to "Wait For Key" state (PNP-ISA spec)
2918  outb($addrreg, 0x02);
2919  outb($datareg, 0x02);
2920}
2921
2922# Guess if an unknown Super-I/O chip has sensors
2923sub guess_superio_ld($$$)
2924{
2925  my ($addrreg, $datareg, $typical_addr) = @_;
2926  my ($oldldn, $ldn, $addr);
2927
2928  # Save logical device number
2929  outb($addrreg, $superio{logdevreg});
2930  $oldldn = inb($datareg);
2931
2932  for ($ldn = 0; $ldn < 16; $ldn++) {
2933    # Select logical device
2934    outb($addrreg, $superio{logdevreg});
2935    outb($datareg, $ldn);
2936
2937    # Read base I/O address
2938    outb($addrreg, $superio{basereg});
2939    $addr = inb($datareg) << 8;
2940    outb($addrreg, $superio{basereg} + 1);
2941    $addr |= inb($datareg);
2942    next unless ($addr & 0xfff8) == $typical_addr;
2943
2944    printf "    (logical device \%X has address 0x\%x, could be sensors)\n",
2945           $ldn, $addr;
2946    last;
2947  }
2948
2949  # Be nice, restore original logical device
2950  outb($addrreg, $superio{logdevreg});
2951  outb($datareg, $oldldn);
2952}
2953
2954sub probe_superio($$$)
2955{
2956  my ($addrreg, $datareg, $chip) = @_;
2957  my ($val, $addr);
2958
2959  printf "\%-60s",  "Found `$chip->{name}'";
2960
2961  # Does it have hardware monitoring capabilities?
2962  if (!exists $chip->{driver}) {
2963    print "\n    (no information available)\n";
2964    return;
2965  }
2966  if ($chip->{driver} eq "not-a-sensor") {
2967    print "\n    (no hardware monitoring capabilities)\n";
2968    return;
2969  }
2970
2971  # Switch to the sensor logical device
2972  outb($addrreg, $superio{logdevreg});
2973  outb($datareg, $chip->{logdev});
2974
2975  # Check the activation register
2976  outb($addrreg, $superio{actreg});
2977  $val = inb($datareg);
2978  if (!($val & $superio{actmask})) {
2979    print "\n    (but not activated)\n";
2980    return;
2981  }
2982
2983  # Get the IO base register
2984  outb($addrreg, $superio{basereg});
2985  $addr = inb($datareg);
2986  outb($addrreg, $superio{basereg} + 1);
2987  $addr = ($addr << 8) | inb($datareg);
2988  if ($addr == 0) {
2989    print "\n    (but no address specified)\n";
2990    return;
2991  }
2992  print "Success!\n";
2993  printf "    (address 0x\%x, driver `%s')\n", $addr, $chip->{driver};
2994  my $new_hash = { conf => 9,
2995                   isa_addr => $addr,
2996                   chipname => $chip->{name}
2997                 };
2998  add_isa_to_chips_detected $chip->{alias_detect},$chip->{driver},
2999                                        $new_hash;
3000}
3001
3002sub scan_superio
3003{
3004  my ($addrreg, $datareg) = @_;
3005  my ($val, $found);
3006
3007  printf("Probing for Super-I/O at 0x\%x/0x\%x\n", $addrreg, $datareg);
3008
3009  FAMILY:
3010  foreach my $family (@superio_ids) {
3011    printf("\%-60s", "Trying family `$family->{family}'... ");
3012# write the password
3013    foreach $val (@{$family->{enter}->{$addrreg}}) {
3014      outb($addrreg, $val);
3015    }
3016# did it work?
3017    outb($addrreg, $superio{devidreg});
3018    $val = inb($datareg);
3019    outb($addrreg, $superio{devidreg} + 1);
3020    $val = ($val << 8) | inb($datareg);
3021    if ($val == 0x0000 || $val == 0xffff) {
3022      print "No\n";
3023      next FAMILY;
3024    }
3025    print "Yes\n";
3026
3027    $found = 0;
3028    foreach my $chip (@{$family->{chips}}) {
3029      if (($chip->{devid} > 0xff && ($val & ($chip->{devid_mask} || 0xffff)) == $chip->{devid})
3030       || ($chip->{devid} <= 0xff && ($val >> 8) == $chip->{devid})) {
3031        probe_superio($addrreg, $datareg, $chip);
3032        $found++;
3033      }
3034    }
3035
3036    if (!$found) {
3037      printf("Found unknown chip with ID 0x%04x\n", $val);
3038      # Guess if a logical device could correspond to sensors
3039      guess_superio_ld($addrreg, $datareg, $family->{guess})
3040        if defined $family->{guess};
3041    }
3042
3043    exit_superio($addrreg, $datareg);
3044  }
3045}
3046
3047
3048sub scan_cpu($)
3049{
3050  my $entry = shift;
3051  my $confidence;
3052
3053  printf("\%-60s", "$entry->{name}... ");
3054  if (defined ($confidence = $entry->{detect}())) {
3055    print "Success!\n";
3056    printf "    (driver `%s')\n", $entry->{driver};
3057    my $new_hash = {
3058      conf => $confidence,
3059      chipname => $entry->{name},
3060    };
3061    add_isa_to_chips_detected(undef, $entry->{driver}, $new_hash);
3062  } else {
3063    print "No\n";
3064  }
3065}
3066
3067
3068##################
3069# CHIP DETECTION #
3070##################
3071
3072# This routine allows you to select which chips are optionally added to the
3073# chip detection list. The most common use is to allow for different chip
3074# detection/drivers based on different linux kernels
3075# This routine follows the pattern of the SiS adapter special cases
3076sub chip_special_cases
3077{
3078        # Based on the kernel, add the appropriate chip structure to the
3079        # chip_ids detection list
3080        if (kernel_version_at_least(2, 6, 0)) {
3081                push @chip_ids, $chip_kern26_w83791d;
3082        } else {
3083                push @chip_ids, $chip_kern24_w83791d;
3084        }
3085}
3086
3087# Each function returns a confidence value. The higher this value, the more
3088# sure we are about this chip. A Winbond W83781D, for example, will be
3089# detected as a LM78 too; but as the Winbond detection has a higher confidence
3090# factor, you should identify it as a Winbond.
3091
3092# Each function returns a list. The first element is the confidence value;
3093# Each element after it is an SMBus address. In this way, we can detect
3094# chips with several SMBus addresses. The SMBus address for which the
3095# function was called is never returned.
3096
3097# If there are devices which get confused if they are only read from, then
3098# this program will surely confuse them. But we guarantee never to write to
3099# any of these devices.
3100
3101
3102# $_[0]: A reference to the file descriptor to access this chip.
3103#        We may assume an i2c_set_slave_addr was already done.
3104# $_[1]: Address
3105# Returns: undef if not detected, (7) if detected.
3106# Registers used: 0x58
3107sub mtp008_detect
3108{
3109  my ($file,$addr) = @_;
3110  return if (i2c_smbus_read_byte_data($file,0x58)) != 0xac;
3111  return (8);
3112}
3113 
3114# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3115# $_[1]: A reference to the file descriptor to access this chip.
3116#        We may assume an i2c_set_slave_addr was already done.
3117# $_[2]: Address
3118# Returns: undef if not detected, (6) if detected.
3119# Registers used:
3120#   0x40: Configuration
3121#   0x48: Full I2C Address
3122#   0x49: Device ID
3123# Note that this function is always called through a closure, so the
3124# arguments are shifted by one place.
3125sub lm78_detect
3126{
3127  my $reg;
3128  my ($chip,$file,$addr) = @_;
3129  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
3130  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
3131  $reg = i2c_smbus_read_byte_data($file,0x49);
3132  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
3133                    ($chip == 1 and $reg == 0x40) or
3134                    ($chip == 2 and ($reg & 0xfe) == 0xc0);
3135  return (6);
3136}
3137
3138# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3139# $_[1]: Address
3140# Returns: undef if not detected, 6 if detected.
3141# Note: Only address 0x290 is scanned at this moment.
3142sub lm78_isa_detect
3143{
3144  my ($chip,$addr) = @_ ;
3145  my $val = inb ($addr + 1);
3146  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
3147            inb ($addr + 7) != $val;
3148
3149  $val = inb($addr + 5) & 0x7f;
3150  outb($addr + 5, ~$val & 0xff);
3151  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
3152    outb($addr+5,$val);
3153    return;
3154  }
3155  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
3156  return unless (&$readproc(0x40) & 0x80) == 0x00;
3157  my $reg = &$readproc(0x49);
3158  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
3159                ($chip == 1 and $reg == 0x40) or
3160                ($chip == 2 and ($reg & 0xfe) == 0xc0);
3161
3162  # Explicitely prevent misdetection of Winbond chips
3163  $reg = &$readproc(0x4f);
3164  return if $reg == 0xa3 || $reg == 0x5c;
3165
3166  # Explicitely prevent misdetection of ITE chips
3167  $reg = &$readproc(0x58);
3168  return if $reg == 0x90;
3169
3170  return 6;
3171}
3172
3173
3174# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3175# $_[1]: ISA address
3176# $_[2]: I2C file handle
3177# $_[3]: I2C address
3178sub lm78_alias_detect
3179{
3180  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
3181  my $i;
3182  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
3183  return 0 unless &$readproc(0x48) == $i2c_addr;
3184  for ($i = 0x2b; $i <= 0x3d; $i ++) {
3185    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
3186  }
3187  return 1;
3188}
3189
3190# $_[0]: A reference to the file descriptor to access this chip.
3191#        We assume an i2c_set_slave_addr was already done.
3192# $_[1]: Address
3193# Returns: undef if not detected, 3 or 6 if detected;
3194#   6 means that the temperatures make sense;
3195#   3 means that the temperatures look strange;
3196# Registers used:
3197#   0x00: Temperature
3198#   0x01: Configuration
3199#   0x02: Hysteresis
3200#   0x03: Overtemperature Shutdown
3201#   0x04-0x07: No registers
3202# The first detection step is based on the fact that the LM75 has only
3203# four registers, and cycles addresses over 8-byte boundaries. We use the
3204# 0x04-0x07 addresses (unused) to improve the reliability. These are not
3205# real registers and will always return the last returned value. This isn't
3206# documented.
3207# Note that register 0x00 may change, so we can't use the modulo trick on it.
3208sub lm75_detect
3209{
3210  my $i;
3211  my ($file,$addr) = @_;
3212  my $cur = i2c_smbus_read_word_data($file,0x00);
3213  my $cur_varies = 0;
3214  my $conf = i2c_smbus_read_byte_data($file,0x01);
3215
3216  my $hyst = i2c_smbus_read_word_data($file,0x02);
3217  return if i2c_smbus_read_word_data($file,0x04) != $hyst;
3218  return if i2c_smbus_read_word_data($file,0x05) != $hyst;
3219  return if i2c_smbus_read_word_data($file,0x06) != $hyst;
3220  return if i2c_smbus_read_word_data($file,0x07) != $hyst;
3221
3222  my $os = i2c_smbus_read_word_data($file,0x03);
3223  return if i2c_smbus_read_word_data($file,0x04) != $os;
3224  return if i2c_smbus_read_word_data($file,0x05) != $os;
3225  return if i2c_smbus_read_word_data($file,0x06) != $os;
3226  return if i2c_smbus_read_word_data($file,0x07) != $os;
3227
3228  for ($i = 0x00; $i < 0xff; $i += 8) {
3229    return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf;
3230    return if i2c_smbus_read_word_data($file, $i + 0x02) != $hyst;
3231    return if i2c_smbus_read_word_data($file, $i + 0x04) != $hyst;
3232    return if i2c_smbus_read_word_data($file, $i + 0x05) != $hyst;
3233    return if i2c_smbus_read_word_data($file, $i + 0x06) != $hyst;
3234    return if i2c_smbus_read_word_data($file, $i + 0x07) != $hyst;
3235    return if i2c_smbus_read_word_data($file, $i + 0x03) != $os;
3236    return if i2c_smbus_read_word_data($file, $i + 0x04) != $os;
3237    return if i2c_smbus_read_word_data($file, $i + 0x05) != $os;
3238    return if i2c_smbus_read_word_data($file, $i + 0x06) != $os;
3239    return if i2c_smbus_read_word_data($file, $i + 0x07) != $os;
3240        $cur_varies = 1
3241      if (! $cur_varies) and
3242        i2c_smbus_read_word_data($file, $i) != $cur;
3243  }
3244
3245  # All registers hold the same value, obviously a misdetection
3246  return if (! $cur_varies) and $conf == ($cur & 0xff) and $cur == $hyst
3247    and $cur == $os;
3248
3249  $cur = swap_bytes($cur);
3250  $hyst = swap_bytes($hyst);
3251  $os = swap_bytes($os);
3252  # Unused bits
3253  return if ($conf & 0xe0);
3254
3255  $cur = $cur >> 8;
3256  $hyst = $hyst >> 8;
3257  $os = $os >> 8;
3258  # Most probable value ranges
3259  return 6 if $cur <= 100 and ($hyst >= 10 && $hyst <= 125)
3260    and ($os >= 20 && $os <= 127) and $hyst < $os;
3261  return 3;
3262}
3263
3264# $_[0]: A reference to the file descriptor to access this chip.
3265#        We assume an i2c_set_slave_addr was already done.
3266# $_[1]: Address
3267# Returns: undef if not detected, 3 or 6 if detected;
3268#   6 means that the temperatures make sense;
3269#   3 means that the temperatures look strange;
3270# Registers used:
3271#   0x00: Temperature
3272#   0x01: Configuration
3273#   0x02: Hysteresis
3274#   0x03: Overtemperature Shutdown
3275#   0x04: Low limit
3276#   0x05: High limit
3277#   0x04-0x07: No registers
3278# The first detection step is based on the fact that the LM77 has only
3279# six registers, and cycles addresses over 8-byte boundaries. We use the
3280# 0x06-0x07 addresses (unused) to improve the reliability. These are not
3281# real registers and will always return the last returned value. This isn't
3282# documented.
3283# Note that register 0x00 may change, so we can't use the modulo trick on it.
3284sub lm77_detect
3285{
3286  my $i;
3287  my ($file,$addr) = @_;
3288  my $cur = i2c_smbus_read_word_data($file,0x00);
3289  my $cur_varies = 0;
3290  my $conf = i2c_smbus_read_byte_data($file,0x01);
3291  my $hyst = i2c_smbus_read_word_data($file,0x02);
3292  my $os = i2c_smbus_read_word_data($file,0x03);
3293
3294  my $low = i2c_smbus_read_word_data($file,0x04);
3295  return if i2c_smbus_read_word_data($file,0x06) != $low;
3296  return if i2c_smbus_read_word_data($file,0x07) != $low;
3297
3298  my $high = i2c_smbus_read_word_data($file,0x05);
3299  return if i2c_smbus_read_word_data($file,0x06) != $high;
3300  return if i2c_smbus_read_word_data($file,0x07) != $high;
3301
3302  for ($i = 0x00; $i < 0xff; $i += 8) {
3303    return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf;
3304    return if i2c_smbus_read_word_data($file, $i + 0x02) != $hyst;
3305    return if i2c_smbus_read_word_data($file, $i + 0x03) != $os;
3306    return if i2c_smbus_read_word_data($file, $i + 0x04) != $low;
3307    return if i2c_smbus_read_word_data($file, $i + 0x06) != $low;
3308    return if i2c_smbus_read_word_data($file, $i + 0x07) != $low;
3309    return if i2c_smbus_read_word_data($file, $i + 0x05) != $high;
3310    return if i2c_smbus_read_word_data($file, $i + 0x06) != $high;
3311    return if i2c_smbus_read_word_data($file, $i + 0x07) != $high;
3312    $cur_varies = 1
3313      if (! $cur_varies) and
3314        i2c_smbus_read_word_data($file, $i) != $cur;
3315  }
3316
3317  # All registers hold the same value, obviously a misdetection
3318  return if (! $cur_varies) and $conf == ($cur & 0xff) and $cur == $hyst
3319    and $cur == $os and $cur == $low and $cur == $high;
3320
3321  $cur = swap_bytes($cur);
3322  $os = swap_bytes($os);
3323  $hyst = swap_bytes($hyst);
3324  $low = swap_bytes($low);
3325  $high = swap_bytes($high);
3326  # Unused bits
3327  return if ($conf & 0xe0)
3328    or (($cur >> 12) != 0 && ($cur >> 12) != 0xf)
3329    or (($hyst >> 12) != 0 && ($hyst >> 12) != 0xf)
3330    or (($os >> 12) != 0 && ($os >> 12) != 0xf)
3331    or (($low >> 12) != 0 && ($low >> 12) != 0xf)
3332    or (($high >> 12) != 0 && ($high >> 12) != 0xf);
3333
3334  $cur /= 16;
3335  $hyst /= 16;
3336  $os /= 16;
3337  $high /= 16;
3338  $low /= 16;
3339
3340  # Most probable value ranges
3341  return 6 if $cur <= 100 and $hyst <= 40
3342    and ($os >= 20 && $os <= 127) and ($high >= 20 && $high <= 127);
3343  return 3;
3344}
3345
3346# $_[0]: Chip to detect (0 = LM92, 1 = LM76, 2 = MAX6633/MAX6634/MAX6635)
3347# $_[1]: A reference to the file descriptor to access this chip.
3348#        We may assume an i2c_set_slave_addr was already done.
3349# $_[2]: Address
3350# Returns: undef if not detected, 2 or 4 if detected;
3351# Registers used:
3352#   0x01: Configuration (National Semiconductor only)
3353#   0x02: Hysteresis
3354#   0x03: Critical Temp
3355#   0x04: Low Limit
3356#   0x05: High Limit
3357#   0x07: Manufacturer ID (LM92 only)
3358# One detection step is based on the fact that the LM92 and clones have a
3359# limited number of registers, which cycle modulo 16 address values.
3360# Note that register 0x00 may change, so we can't use the modulo trick on it.
3361sub lm92_detect
3362{
3363  my ($chip, $file, $addr) = @_;
3364
3365  my $conf = i2c_smbus_read_byte_data($file, 0x01);
3366  my $hyst = i2c_smbus_read_word_data($file, 0x02);
3367  my $crit = i2c_smbus_read_word_data($file, 0x03);
3368  my $low = i2c_smbus_read_word_data($file, 0x04);
3369  my $high = i2c_smbus_read_word_data($file, 0x05);
3370
3371  return if $conf == 0 and $hyst == 0 and $crit == 0
3372        and $low == 0 and $high == 0;
3373
3374  return if $chip == 0
3375        and i2c_smbus_read_word_data($file, 0x07) != 0x0180;
3376 
3377  return if ($chip == 0 || $chip == 1)
3378        and ($conf & 0xE0);
3379
3380  for (my $i = 0; $i < 8; $i++) {
3381    return if i2c_smbus_read_byte_data($file, $i*16+0x01) != $conf;
3382    return if i2c_smbus_read_word_data($file, $i*16+0x02) != $hyst;
3383    return if i2c_smbus_read_word_data($file, $i*16+0x03) != $crit;
3384    return if i2c_smbus_read_word_data($file, $i*16+0x04) != $low;
3385    return if i2c_smbus_read_word_data($file, $i*16+0x05) != $high;
3386  }
3387 
3388  foreach my $temp ($hyst, $crit, $low, $high) {
3389    return if $chip == 2 and ($temp & 0x7F00);
3390    return if $chip != 2 and ($temp & 0x0700);
3391  }
3392
3393  return 4 if $chip == 0;
3394  return 2;
3395}
3396 
3397# $_[0]: A reference to the file descriptor to access this chip.
3398#        We may assume an i2c_set_slave_addr was already done.
3399# $_[1]: Address
3400# Returns: undef if not detected, 3 if detected
3401# Registers used:
3402#   0xAA: Temperature
3403#   0xA1: High limit
3404#   0xA2: Low limit
3405#   0xAC: Configuration
3406# Detection is weak. We check if bit 4 (NVB) is clear, because it is
3407# unlikely to be set (would mean that EEPROM is currently being accessed).
3408# Temperature checkings will hopefully prevent LM75 or other chips from
3409# being detected as a DS1621.
3410sub ds1621_detect
3411{
3412  my $i;
3413  my ($file,$addr) = @_;
3414  my $temp = i2c_smbus_read_word_data($file,0xAA);
3415  my $high = i2c_smbus_read_word_data($file,0xA1);
3416  my $low = i2c_smbus_read_word_data($file,0xA2);
3417  return if ($temp | $high | $low) & 0x7F00;
3418  my $conf = i2c_smbus_read_byte_data($file,0xAC);
3419  return if ($temp == 0 && $high == 0 && $low == 0 && $conf == 0);
3420  return 3 if ($conf & 0x10) == 0x00;
3421  return;
3422}
3423
3424# $_[0]: A reference to the file descriptor to access this chip.
3425#        We may assume an i2c_set_slave_addr was already done.
3426# $_[1]: Address
3427# Returns: undef if not detected, 1 to 3 if detected.
3428# Registers used:
3429#   0x00: Configuration register
3430#   0x02: Interrupt state register
3431#   0x2a-0x3d: Limits registers
3432# This one is easily misdetected since it doesn't provide identification
3433# registers. So we have to use some tricks:
3434#   - 6-bit addressing, so limits readings modulo 0x40 should be unchanged
3435#   - positive temperature limits
3436#   - limits order correctness
3437# Hopefully this should limit the rate of false positives, without increasing
3438# the rate of false negatives.
3439# Thanks to Lennard Klein for testing on a non-LM80 chip, which was
3440# previously misdetected, and isn't anymore. For reference, it scored
3441# a final confidence of 0, and changing from strict limit comparisons
3442# to loose comparisons did not change the score.
3443sub lm80_detect
3444{
3445  my ($i,$reg);
3446  my ($file,$addr) = @_;
3447
3448  return if (i2c_smbus_read_byte_data($file,0x00) & 0x80) != 0;
3449  return if (i2c_smbus_read_byte_data($file,0x02) & 0xc0) != 0;
3450
3451  for ($i = 0x2a; $i <= 0x3d; $i++) {
3452    $reg = i2c_smbus_read_byte_data($file,$i);
3453    return if i2c_smbus_read_byte_data($file,$i+0x40) != $reg;
3454    return if i2c_smbus_read_byte_data($file,$i+0x80) != $reg;
3455    return if i2c_smbus_read_byte_data($file,$i+0xc0) != $reg;
3456  }
3457 
3458  # Refine a bit by checking wether limits are in the correct order
3459  # (min<max for voltages, hyst<max for temperature). Since it is still
3460  # possible that the chip is an LM80 with limits not properly set,
3461  # a few "errors" are tolerated.
3462  my $confidence = 0;
3463  for ($i = 0x2a; $i <= 0x3a; $i++) {
3464    $confidence++
3465      if i2c_smbus_read_byte_data($file,$i) < i2c_smbus_read_byte_data($file,$i+1);
3466  }
3467  # hot temp<OS temp
3468  $confidence++
3469    if i2c_smbus_read_byte_data($file,0x38) < i2c_smbus_read_byte_data($file,0x3a);
3470
3471  # Negative temperature limits are unlikely.
3472  for ($i = 0x3a; $i <= 0x3d; $i++) {
3473    $confidence++ if (i2c_smbus_read_byte_data($file,$i) & 0x80) == 0;
3474  }
3475
3476  # $confidence is between 0 and 14
3477  $confidence = ($confidence >> 1) - 4;
3478  # $confidence is now between -4 and 3
3479
3480  return unless $confidence > 0;
3481
3482  return $confidence;
3483}
3484
3485# $_[0]: Chip to detect
3486#   (0 = LM82/LM83)
3487# $_[1]: A reference to the file descriptor to access this chip.
3488#        We may assume an i2c_set_slave_addr was already done.
3489# $_[2]: Address
3490# Returns: undef if not detected, 4 to 8 if detected.
3491# Registers used:
3492#   0x02: Status 1
3493#   0x03: Configuration
3494#   0x04: Company ID of LM84
3495#   0x35: Status 2
3496#   0xfe: Manufacturer ID
3497#   0xff: Chip ID / die revision
3498# We can use the LM84 Company ID register because the LM83 and the LM82 are
3499# compatible with the LM84.
3500# The LM83 chip ID is missing from the datasheet and was contributed by
3501# Magnus Forsstrom: 0x03.
3502# At least some revisions of the LM82 seem to be repackaged LM83, so they
3503# have the same chip ID, and temp2/temp4 will be stuck in "OPEN" state.
3504# For this reason, we don't even try to distinguish between both chips.
3505# Thanks to Ben Gardner for reporting.
3506sub lm83_detect
3507{
3508  my ($chip, $file) = @_;
3509  return if i2c_smbus_read_byte_data($file,0xfe) != 0x01;
3510  my $chipid = i2c_smbus_read_byte_data($file,0xff);
3511  return if $chipid != 0x01 && $chipid != 0x03;
3512
3513  my $confidence = 4;
3514  $confidence++
3515    if (i2c_smbus_read_byte_data($file,0x02) & 0xa8) == 0x00;
3516  $confidence++
3517    if (i2c_smbus_read_byte_data($file,0x03) & 0x41) == 0x00;
3518  $confidence++
3519    if i2c_smbus_read_byte_data($file,0x04) == 0x00;
3520  $confidence++
3521    if (i2c_smbus_read_byte_data($file,0x35) & 0x48) == 0x00;
3522
3523  return $confidence;
3524}
3525
3526# $_[0]: Chip to detect
3527#   (0 = LM90, 1=LM89/LM99, 2=LM86, 3=ADM1032, 4=MAX6657/MAX6658/MAX6659,
3528#    5 = ADT7461)
3529# $_[1]: A reference to the file descriptor to access this chip.
3530#        We may assume an i2c_set_slave_addr was already done.
3531# $_[2]: Address
3532# Returns: undef if not detected, 4, 6 or 8 if detected.
3533#   The Maxim chips have a low confidence value (4)
3534#   because they don't have a die revision register.
3535# Registers used:
3536#   0x03: Configuration
3537#   0x04: Conversion rate
3538#   0xfe: Manufacturer ID
3539#   0xff: Chip ID / die revision
3540sub lm90_detect
3541{
3542  my ($chip, $file, $addr) = @_;
3543  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
3544  my $cid = i2c_smbus_read_byte_data($file, 0xff);
3545  my $conf = i2c_smbus_read_byte_data($file, 0x03);
3546  my $rate = i2c_smbus_read_byte_data($file, 0x04);
3547
3548  if ($chip == 0) {
3549    return if ($conf & 0x2a) != 0;
3550    return if $rate > 0x09;
3551    return if $mid != 0x01;     # National Semiconductor
3552    return 8 if $cid == 0x21;   # LM90
3553    return 6 if ($cid & 0x0f) == 0x20;
3554  }
3555  if ($chip == 1) {
3556    return if ($conf & 0x2a) != 0;
3557    return if $rate > 0x09;
3558    return if $mid != 0x01;     # National Semiconductor
3559    return 8 if $addr == 0x4c and $cid == 0x31; # LM89/LM99
3560    return 8 if $addr == 0x4d and $cid == 0x34; # LM89-1/LM99-1
3561    return 6 if ($cid & 0x0f) == 0x30;
3562  }
3563  if ($chip == 2) {
3564    return if ($conf & 0x2a) != 0;
3565    return if $rate > 0x09;
3566    return if $mid != 0x01;     # National Semiconductor
3567    return 8 if $cid == 0x11;   # LM86
3568    return 6 if ($cid & 0xf0) == 0x10;
3569  }
3570  if ($chip == 3) {
3571    return if ($conf & 0x3f) != 0;
3572    return if $rate > 0x0a;
3573    return if $mid != 0x41;     # Analog Devices
3574    return 8 if ($cid & 0xf0) == 0x40; # ADM1032
3575  }
3576  if ($chip == 4) {
3577    return if ($conf & 0x1f) != ($mid & 0x0f); # No low nibble,
3578                                               # returns previous low nibble
3579    return if $rate > 0x09;
3580    return if $mid != 0x4d;     # Maxim
3581    return if $cid != 0x4d;     # No register, returns previous value
3582    return 4;
3583  }
3584  if ($chip == 5) {
3585    return if ($conf & 0x1b) != 0;
3586    return if $rate > 0x0a;
3587    return if $mid != 0x41;     # Analog Devices
3588    return 8 if $cid == 0x61;   # ADT7461
3589  }
3590  return;
3591}
3592
3593# $_[0]: Chip to detect
3594#   (1 = LM63, 2 = F75363SG)
3595# $_[1]: A reference to the file descriptor to access this chip.
3596#        We may assume an i2c_set_slave_addr was already done.
3597# $_[2]: Address (unused)
3598# Returns: undef if not detected, 8 if detected.
3599# Registers used:
3600#   0xfe: Manufacturer ID
3601#   0xff: Chip ID / die revision
3602#   0x03: Configuration (two or three unused bits)
3603#   0x16: Alert mask (two or three unused bits)
3604#   0x03-0x0e: Mirrored registers (five pairs)
3605sub lm63_detect
3606{
3607  my ($chip, $file, $addr) = @_;
3608
3609  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
3610  my $cid = i2c_smbus_read_byte_data($file, 0xff);
3611  my $conf = i2c_smbus_read_byte_data($file, 0x03);
3612  my $mask = i2c_smbus_read_byte_data($file, 0x16);
3613
3614  if ($chip == 1) {
3615    return if $mid != 0x01    # National Semiconductor
3616           || $cid != 0x41;   # LM63
3617    return if ($conf & 0x18) != 0x00
3618           || ($mask & 0xa4) != 0xa4;
3619  } elsif ($chip == 2) {
3620    return if $mid != 0x23    # Fintek
3621           || $cid != 0x20;   # F75363SG
3622    return if ($conf & 0x1a) != 0x00
3623           || ($mask & 0x84) != 0x00; 
3624  }
3625
3626  # For compatibility with the LM86, some registers are mirrored
3627  # to alternative locations
3628  return if $conf != i2c_smbus_read_byte_data($file, 0x09);
3629  foreach my $i (0x04, 0x05, 0x07, 0x08) {
3630    return if i2c_smbus_read_byte_data($file, $i)
3631           != i2c_smbus_read_byte_data($file, $i+6);
3632  }
3633
3634  return 8;
3635}
3636
3637# $_[0]: Chip to detect
3638#   (0 = ADM1029)
3639# $_[1]: A reference to the file descriptor to access this chip.
3640#        We may assume an i2c_set_slave_addr was already done.
3641# $_[2]: Address
3642# Returns: undef if not detected, 3 to 9 if detected.
3643# Registers used:
3644#   0x02, 0x03: Fan support
3645#   0x05: GPIO config
3646#   0x07, 0x08, 0x09: Fan config
3647#   0x0d: Manufacturer ID
3648#   0x0e: Chip ID / die revision
3649sub adm1029_detect
3650{
3651  my ($chip, $file, $addr) = @_;
3652  my $mid = i2c_smbus_read_byte_data($file, 0x0d);
3653  my $cid = i2c_smbus_read_byte_data($file, 0x0e);
3654  my $fansc = i2c_smbus_read_byte_data($file, 0x02);
3655  my $fanss = i2c_smbus_read_byte_data($file, 0x03);
3656  my $gpio = i2c_smbus_read_byte_data($file, 0x05);
3657  my $fanas = i2c_smbus_read_byte_data($file, 0x07);
3658  my $fanhps = i2c_smbus_read_byte_data($file, 0x08);
3659  my $fanfs = i2c_smbus_read_byte_data($file, 0x09);
3660  my $confidence = 3;
3661
3662  if ($chip == 0) {
3663    return if $mid != 0x41;     # Analog Devices
3664    $confidence++ if ($cid & 0xF0) == 0x00; # ADM1029
3665    $confidence+=2 if ($fansc & 0xFC) == 0x00
3666                   && ($fanss & 0xFC) == 0x00;
3667    $confidence+=2 if ($fanas & 0xFC) == 0x00
3668                   && ($fanhps & 0xFC) == 0x00
3669                   && ($fanfs & 0xFC) == 0x00;
3670    $confidence++ if ($gpio & 0x80) == 0x00;
3671    return $confidence;
3672  }
3673  return;
3674}
3675
3676# $_[0]: Chip to detect
3677#   (0 = ADM1030, 1=ADM1031)
3678# $_[1]: A reference to the file descriptor to access this chip.
3679#        We may assume an i2c_set_slave_addr was already done.
3680# $_[2]: Address
3681# Returns: undef if not detected, 3 to 7 (ADM1031) or 9 (ADM1030)
3682#          if detected.
3683# Registers used:
3684#   0x01: Config 2
3685#   0x03: Status 2
3686#   0x0d, 0x0e, 0x0f: Temperature offsets
3687#   0x22: Fan speed config
3688#   0x3d: Chip ID
3689#   0x3e: Manufacturer ID
3690#   0x3f: Die revision
3691sub adm1031_detect
3692{
3693  my ($chip, $file, $addr) = @_;
3694  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3695  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3696  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3697  my $conf2 = i2c_smbus_read_byte_data($file, 0x01);
3698  my $stat2 = i2c_smbus_read_byte_data($file, 0x03);
3699  my $fsc = i2c_smbus_read_byte_data($file, 0x22);
3700  my $lto = i2c_smbus_read_byte_data($file, 0x0d);
3701  my $r1to = i2c_smbus_read_byte_data($file, 0x0e);
3702  my $r2to = i2c_smbus_read_byte_data($file, 0x0f);
3703  my $confidence = 3;
3704
3705  if ($chip == 0) {
3706    return if $mid != 0x41;     # Analog Devices
3707    return if $cid != 0x30;     # ADM1030
3708    $confidence++ if ($drev & 0x70) == 0x00;
3709    $confidence++ if ($conf2 & 0x4A) == 0x00;
3710    $confidence++ if ($stat2 & 0x3F) == 0x00;
3711    $confidence++ if ($fsc & 0xF0) == 0x00;
3712    $confidence++ if ($lto & 0x70) == 0x00;
3713    $confidence++ if ($r1to & 0x70) == 0x00;
3714    return $confidence;
3715  }
3716  if ($chip == 1) {
3717    return if $mid != 0x41;     # Analog Devices
3718    return if $cid != 0x31;     # ADM1031
3719    $confidence++ if ($drev & 0x70) == 0x00;
3720    $confidence++ if ($lto & 0x70) == 0x00;
3721    $confidence++ if ($r1to & 0x70) == 0x00;
3722    $confidence++ if ($r2to & 0x70) == 0x00;
3723    return $confidence;
3724  }
3725  return;
3726}
3727
3728# $_[0]: Chip to detect
3729#   (0 = ADM1033, 1 = ADM1034)
3730# $_[1]: A reference to the file descriptor to access this chip.
3731# $_[2]: Address (unused)
3732# Returns: undef if not detected, 4 or 6 if detected.
3733# Registers used:
3734#   0x3d: Chip ID
3735#   0x3e: Manufacturer ID
3736#   0x3f: Die revision
3737sub adm1034_detect
3738{
3739  my ($chip, $file, $addr) = @_;
3740  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3741  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3742  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3743
3744  if ($chip == 0) {
3745    return if $mid != 0x41;     # Analog Devices
3746    return if $cid != 0x33;     # ADM1033
3747    return if ($drev & 0xf8) != 0x00;
3748    return 6 if $drev == 0x02;
3749    return 4;
3750  }
3751  if ($chip == 1) {
3752    return if $mid != 0x41;     # Analog Devices
3753    return if $cid != 0x34;     # ADM1034
3754    return if ($drev & 0xf8) != 0x00;
3755    return 6 if $drev == 0x02;
3756    return 4;
3757  }
3758  return
3759}
3760
3761# $_[0]: Chip to detect
3762#   (0 = ADT7467/ADT7468, 1 = ADT7476, 2 = ADT7462, 3 = ADT7466,
3763#    4 = ADT7470)
3764# $_[1]: A reference to the file descriptor to access this chip.
3765#        We may assume an i2c_set_slave_addr was already done.
3766# $_[2]: Address
3767# Returns: undef if not detected, 5 or 7 if detected.
3768# Registers used:
3769#   0x3d: Chip ID
3770#   0x3e: Manufacturer ID
3771#   0x3f: Die revision
3772sub adt7467_detect
3773{
3774  my ($chip, $file, $addr) = @_;
3775  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3776  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3777  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3778
3779  if ($chip == 0) {
3780    return if $mid != 0x41;     # Analog Devices
3781    return if $cid != 0x68;     # ADT7467
3782    return if ($drev & 0xf0) != 0x70;
3783    return 7 if ($drev == 0x71 || $drev == 0x72);
3784    return 5;
3785  }
3786  if ($chip == 1) {
3787    return if $mid != 0x41;     # Analog Devices
3788    return if $cid != 0x76;     # ADT7476
3789    return if ($drev & 0xf0) != 0x60;
3790    return 7 if ($drev == 0x69);
3791    return 5;
3792  }
3793  if ($chip == 2) {
3794    return if $mid != 0x41;     # Analog Devices
3795    return if $cid != 0x62;     # ADT7462
3796    return if ($drev & 0xf0) != 0x00;
3797    return 7 if ($drev == 0x04);
3798    return 5;
3799  }
3800  if ($chip == 3) {
3801    return if $mid != 0x41;     # Analog Devices
3802    return if $cid != 0x66;     # ADT7466
3803    return if ($drev & 0xf0) != 0x00;
3804    return 7 if ($drev == 0x02);
3805    return 5;
3806  }
3807  if ($chip == 4) {
3808    return if $mid != 0x41;     # Analog Devices
3809    return if $cid != 0x70;     # ADT7470
3810    return if ($drev & 0xf0) != 0x00;
3811    return 7 if ($drev == 0x00);
3812    return 5;
3813  }
3814  return
3815}
3816
3817# $_[0]: Chip to detect
3818#   (0 = ADT7473, 1 = ADT7475)
3819# $_[1]: A reference to the file descriptor to access this chip.
3820# $_[2]: Address (unused)
3821# Returns: undef if not detected, 5 if detected.
3822# Registers used:
3823#   0x3d: Chip ID
3824#   0x3e: Manufacturer ID
3825sub adt7473_detect
3826{
3827  my ($chip, $file, $addr) = @_;
3828  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3829  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3830
3831  if ($chip == 0) {
3832    return if $mid != 0x41;     # Analog Devices
3833    return if $cid != 0x73;     # ADT7473
3834    return 5;
3835  }
3836  if ($chip == 1) {
3837    return if $mid != 0x41;     # Analog Devices
3838    return if $cid != 0x75;     # ADT7475
3839    return 5;
3840  }
3841  return
3842}
3843
3844# $_[0]: Vendor to check for
3845#   (0x01 = National Semi, 0x41 = Analog Dev, 0x5c = SMSC)
3846# $_[1]: A reference to the file descriptor to access this chip.
3847# #_[2]: Base address.
3848# Returns: undef if not detected, (7) or (8) if detected.
3849# Registers used: 0x3e == Vendor register.
3850#                 0x3d == Device ID register (Analog Devices only).
3851#                 0x3f == Version/Stepping register.
3852# Constants used: 0x01 == National Semiconductor Vendor Id.
3853#                 0x41 == Analog Devices Vendor Id.
3854#                 0x5c == SMSC Vendor Id.
3855#                 0x60 == Version number. The lower 4 stepping
3856#                         bits are masked and ignored.
3857sub lm85_detect
3858{
3859  my ($vendor,$file,$addr) = @_;
3860  return if (i2c_smbus_read_byte_data($file,0x3e)) != $vendor ;
3861  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) != 0x60;
3862
3863  if ($vendor == 0x41) # Analog Devices
3864  {
3865    return if i2c_smbus_read_byte_data($file, 0x3d) != 0x27;
3866    return (8);
3867  }
3868
3869  return (7);
3870}
3871
3872# $_[0]: A reference to the file descriptor to access this chip.
3873#        We may assume an i2c_set_slave_addr was already done.
3874# $_[1]: Address
3875# Returns: undef if not detected, (7) if detected.
3876# Registers used: 0x3E, 0x3F
3877#        Assume lower 2 bits of reg 0x3F are for revisions.
3878sub lm87_detect
3879{
3880  my ($file,$addr) = @_;
3881  return if (i2c_smbus_read_byte_data($file,0x3e)) != 0x02;
3882  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xfc) != 0x04;
3883  return (7);
3884}
3885 
3886# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S,
3887#                        3 = W83627HF, 4 = AS99127F (rev.1),
3888#                        5 = AS99127F (rev.2), 6 = ASB100, 7 = W83791D,
3889#                        8 = W83792D, 9 = W83627EHF 10 = W83627DHG)
3890# $_[1]: A reference to the file descriptor to access this chip.
3891#        We may assume an i2c_set_slave_addr was already done.
3892# $_[2]: Address
3893# Returns: undef if not detected, (8,addr1,addr2) if detected, but only
3894#          if the LM75 chip emulation is enabled.
3895# Registers used:
3896#   0x48: Full I2C Address
3897#   0x4a: I2C addresses of emulated LM75 chips
3898#   0x4e: Vendor ID byte selection, and bank selection
3899#   0x4f: Vendor ID
3900#   0x58: Device ID (only when in bank 0)
3901# Note: Fails if the W8378xD is not in bank 0!
3902# Note: Detection overrules a previous LM78 detection
3903# Note: Asus chips do not have their I2C address at register 0x48?
3904#       AS99127F rev.1 and ASB100 have 0x00, confirmation wanted for
3905#       AS99127F rev.2.
3906sub w83781d_detect
3907{
3908  my ($reg1,$reg2,@res);
3909  my ($chip,$file,$addr) = @_;
3910
3911  return unless (i2c_smbus_read_byte_data($file,0x48) == $addr)
3912    or ($chip >= 4 && $chip <= 6);
3913
3914  $reg1 = i2c_smbus_read_byte_data($file,0x4e);
3915  $reg2 = i2c_smbus_read_byte_data($file,0x4f);
3916  if ($chip == 4) { # Asus AS99127F (rev.1)
3917    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or 
3918                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x12);
3919  } elsif ($chip == 6) { # Asus ASB100
3920    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0x94) or 
3921                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x06);
3922  } else { # Winbond and Asus AS99127F (rev.2)
3923    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
3924                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
3925  }
3926
3927  return unless ($reg1 & 0x07) == 0x00;
3928
3929  $reg1 = i2c_smbus_read_byte_data($file,0x58);
3930  return if $chip == 0 and ($reg1 != 0x10 && $reg1 != 0x11);
3931  return if $chip == 1 and  $reg1 != 0x30;
3932  return if $chip == 2 and  $reg1 != 0x40;
3933  return if $chip == 3 and  $reg1 != 0x21;
3934  return if $chip == 4 and  $reg1 != 0x31;
3935  return if $chip == 5 and  $reg1 != 0x31;
3936  return if $chip == 6 and  $reg1 != 0x31;
3937  return if $chip == 7 and  $reg1 != 0x71;
3938  return if $chip == 8 and  $reg1 != 0x7a;
3939  return if $chip == 9 and  $reg1 != 0xa1;
3940  return if $chip == 10 and  $reg1 != 0xa2;
3941  $reg1 = i2c_smbus_read_byte_data($file,0x4a);
3942  # Default address is 0x2d
3943  @res = ($addr != 0x2d) ? (7) : (8);
3944  return @res if $chip == 9; # No subclients
3945  push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08;
3946  push @res, (($reg1 & 0x70) >> 4) + 0x48 unless ($reg1 & 0x80 or $chip == 2);
3947  return @res;
3948}
3949 
3950# $_[0]: Chip to detect (0 = W83793)
3951# $_[1]: A reference to the file descriptor to access this chip.
3952# $_[2]: Address
3953# Returns: undef if not detected
3954#          6 if detected and bank different from 0
3955#          (8,addr1,addr2) if detected, band is 0 and LM75 chip emulation
3956#          is enabled
3957# Registers used:
3958#   0x0b: Full I2C Address
3959#   0x0c: I2C addresses of emulated LM75 chips
3960#   0x00: Vendor ID byte selection, and bank selection(Bank 0,1,2)
3961#   0x0d: Vendor ID(Bank 0,1,2)
3962#   0x0e: Device ID(Bank 0,1,2)
3963sub w83793_detect
3964{
3965  my ($bank, $reg, @res);
3966  my ($chip, $file, $addr) = @_;
3967
3968  $bank = i2c_smbus_read_byte_data($file, 0x00);
3969  $reg = i2c_smbus_read_byte_data($file, 0x0d);
3970
3971  return unless (($bank & 0x80) == 0x00 and $reg == 0xa3) or 
3972                (($bank & 0x80) == 0x80 and $reg == 0x5c);
3973
3974  $reg = i2c_smbus_read_byte_data($file, 0x0e);
3975  return if $chip == 0 and $reg != 0x7b;
3976
3977# If bank 0 is selected, we can do more checks
3978  return 6 unless ($bank & 0x07) == 0;
3979  $reg = i2c_smbus_read_byte_data($file, 0x0b);
3980  return unless ($reg == ($addr << 1));
3981
3982  $reg = i2c_smbus_read_byte_data($file, 0x0c);
3983  @res = (8);
3984  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08;
3985  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
3986  return @res;
3987}
3988
3989# $_[0]: A reference to the file descriptor to access this chip.
3990#        We assume an i2c_set_slave_addr was already done.
3991# $_[1]: Address
3992# Returns: undef if not detected, 3 if detected
3993# Registers used:
3994#   0x48: Full I2C Address
3995#   0x4e: Vendor ID byte selection
3996#   0x4f: Vendor ID
3997#   0x58: Device ID
3998# Note that the datasheet was useless and this detection routine
3999# is based on dumps we received from users. Also, the W83781SD is *NOT*
4000# a hardware monitoring chip as far as we know, but we still want to
4001# detect it so that people won't keep reporting it as an unknown chip
4002# we should investigate about.
4003sub w83791sd_detect
4004{
4005  my ($file, $addr) = @_;
4006  my ($reg1, $reg2);
4007
4008  return unless (i2c_smbus_read_byte_data($file, 0x48) == $addr);
4009
4010  $reg1 = i2c_smbus_read_byte_data($file, 0x4e);
4011  $reg2 = i2c_smbus_read_byte_data($file, 0x4f);
4012  return unless (!($reg1 & 0x80) && $reg2 == 0xa3)
4013             || (($reg1 & 0x80) && $reg2 == 0x5c);
4014
4015  $reg1 = i2c_smbus_read_byte_data($file, 0x58);
4016  return unless $reg1 == 0x72;
4017
4018  return 3;
4019}
4020
4021# $_[0]: Chip to detect (0 = ASM58, 1 = AS2K129R, 2 = ???)
4022# $_[1]: A reference to the file descriptor to access this chip
4023# $_[2]: Address (unused)
4024# Returns: undef if not detected, 5 if detected
4025# Registers used:
4026#   0x4e: Vendor ID high byte
4027#   0x4f: Vendor ID low byte
4028#   0x58: Device ID
4029# Note: The values were given by Alex van Kaam, we don't have datasheets
4030#       to confirm.
4031sub mozart_detect
4032{
4033  my ($vid,$dev);
4034  my ($chip,$file,$addr) = @_;
4035
4036  $vid = (i2c_smbus_read_byte_data($file,0x4e) << 8)
4037       +  i2c_smbus_read_byte_data($file,0x4f);
4038  $dev = i2c_smbus_read_byte_data($file,0x58);
4039
4040  return if ($chip == 0) and ($dev != 0x56 || $vid != 0x9436);
4041  return if ($chip == 1) and ($dev != 0x56 || $vid != 0x9406);
4042  return if ($chip == 2) and ($dev != 0x10 || $vid != 0x5ca3);
4043
4044  return 5;
4045}
4046
4047# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF,
4048#                        9 = W83627EHF 10 = W83627DHG)
4049# $_[1]: ISA address
4050# $_[2]: I2C file handle
4051# $_[3]: I2C address
4052sub w83781d_alias_detect
4053{
4054  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
4055  my $i;
4056  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
4057  return 0 unless &$readproc(0x48) == $i2c_addr;
4058  for ($i = 0x2b; $i <= 0x3d; $i ++) {
4059    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
4060  }
4061  return 1;
4062}
4063
4064# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF)
4065# $_[1]: Address
4066# Returns: undef if not detected, (8) if detected.
4067sub w83781d_isa_detect
4068{
4069  my ($chip,$addr) = @_ ;
4070  my ($reg1,$reg2);
4071  my $val = inb ($addr + 1);
4072  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
4073            inb ($addr + 7) != $val;
4074
4075  $val = inb($addr + 5) & 0x7f;
4076  outb($addr+5, ~$val & 0xff);
4077  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
4078    outb($addr+5,$val);
4079    return;
4080  }
4081
4082  my $read_proc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
4083  $reg1 = &$read_proc(0x4e);
4084  $reg2 = &$read_proc(0x4f);
4085  return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
4086                (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
4087  return unless ($reg1 & 0x07) == 0x00;
4088  $reg1 = &$read_proc(0x58);
4089  return if $chip == 0 and  ($reg1 & 0xfe) != 0x10;
4090  return if $chip == 1 and  ($reg1 & 0xfe) != 0x30;
4091  return if $chip == 3 and  ($reg1 & 0xfe) != 0x20;
4092
4093  return 8;
4094}
4095
4096# $_[0]: Chip to detect (0 = Revision 0x00, 1 = Revision 0x80)
4097# $_[1]: A reference to the file descriptor to access this chip.
4098#        We may assume an i2c_set_slave_addr was already done.
4099# $_[2]: Address
4100# Returns: undef if not detected, (6) if detected.
4101# Registers used:
4102#   0x00: Device ID
4103#   0x01: Revision ID
4104#   0x03: Configuration
4105# Mediocre detection
4106sub gl518sm_detect
4107{
4108  my $reg;
4109  my ($chip,$file,$addr) = @_;
4110  return unless i2c_smbus_read_byte_data($file,0x00) == 0x80;
4111  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
4112  $reg = i2c_smbus_read_byte_data($file,0x01);
4113  return unless ($chip == 0 and $reg == 0x00) or
4114                ($chip == 1 and $reg == 0x80);
4115  return (6);
4116}
4117
4118# $_[0]: A reference to the file descriptor to access this chip.
4119#        We may assume an i2c_set_slave_addr was already done.
4120# $_[1]: Address
4121# Returns: undef if not detected, (5) if detected.
4122# Registers used:
4123#   0x00: Device ID
4124#   0x01: Revision ID
4125#   0x03: Configuration
4126# Mediocre detection
4127sub gl520sm_detect
4128{
4129  my ($file,$addr) = @_;
4130  return unless i2c_smbus_read_byte_data($file,0x00) == 0x20;
4131  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
4132  # The line below must be better checked before I dare to use it.
4133  # return unless i2c_smbus_read_byte_data($file,0x01) == 0x00;
4134  return (5);
4135}
4136
4137# $_[0]: A reference to the file descriptor to access this chip.
4138#        We may assume an i2c_set_slave_addr was already done.
4139# $_[1]: Address
4140# Returns: undef if not detected, (5) if detected.
4141# Registers used:
4142#   0x00: Device ID
4143# Mediocre detection
4144sub gl525sm_detect
4145{
4146  my ($file,$addr) = @_;
4147  return unless i2c_smbus_read_byte_data($file,0x00) == 0x25;
4148  return (5);
4149}
4150
4151# $_[0]: Chip to detect (0 = ADM9240, 1 = DS1780, 2 = LM81)
4152# $_[1]: A reference to the file descriptor to access this chip.
4153#        We may assume an i2c_set_slave_addr was already done.
4154# $_[2]: Address
4155# Returns: undef if not detected, (7) if detected.
4156# Registers used:
4157#   0x3e: Company ID
4158#   0x40: Configuration
4159#   0x48: Full I2C Address
4160# Note: Detection overrules a previous LM78 detection
4161sub adm9240_detect
4162{
4163  my $reg;
4164  my ($chip, $file,$addr) = @_;
4165  $reg = i2c_smbus_read_byte_data($file,0x3e);
4166  return unless ($chip == 0 and $reg == 0x23) or
4167                ($chip == 1 and $reg == 0xda) or
4168                ($chip == 2 and $reg == 0x01);
4169  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4170  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
4171 
4172  return (7);
4173}
4174
4175# $_[0]: Chip to detect (0 = ADM1022, 1 = THMC50, 2 = ADM1028)
4176# $_[1]: A reference to the file descriptor to access this chip.
4177#        We may assume an i2c_set_slave_addr was already done.
4178# $_[2]: Address
4179# Returns: undef if not detected, (8) if detected.
4180# Registers used:
4181#   0x3e: Company ID
4182#   0x3f: Revision
4183#   0x40: Configuration
4184# Note: Detection overrules a previous LM78 or ADM9240 detection
4185sub adm1022_detect
4186{
4187  my $reg;
4188  my ($chip, $file,$addr) = @_;
4189  $reg = i2c_smbus_read_byte_data($file,0x3e);
4190  return unless ($chip == 0 and $reg == 0x41) or
4191                ($chip == 1 and $reg == 0x49) or
4192                ($chip == 2 and $reg == 0x41);
4193  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4194  $reg = i2c_smbus_read_byte_data($file, 0x3f);
4195  return unless ($reg & 0xc0) == 0xc0;
4196  return if $chip == 0 and ($reg & 0xc0) != 0xc0;
4197  return if $chip == 2 and ($reg & 0xc0) == 0xc0;
4198  return (8);
4199}
4200
4201# $_[0]: Chip to detect (0 = ADM1025, 1 = NE1619)
4202# $_[1]: A reference to the file descriptor to access this chip.
4203#        We may assume an i2c_set_slave_addr was already done.
4204# $_[2]: Address
4205# Returns: undef if not detected, (8) if detected.
4206# Registers used:
4207#   0x3e: Company ID
4208#   0x3f: Revision
4209#   0x40: Configuration
4210#   0x41: Status 1
4211#   0x42: Status 2
4212# Note: Detection overrules a previous LM78 or ADM9240 detection
4213sub adm1025_detect
4214{
4215  my $reg;
4216  my ($chip, $file,$addr) = @_;
4217
4218  $reg = i2c_smbus_read_byte_data($file,0x3e);
4219  return if ($chip == 0) and ($reg != 0x41);
4220  return if ($chip == 1) and ($reg != 0xA1);
4221
4222  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4223  return unless (i2c_smbus_read_byte_data($file,0x41) & 0xC0) == 0x00;
4224  return unless (i2c_smbus_read_byte_data($file,0x42) & 0xBC) == 0x00;
4225  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x20;
4226
4227  return (8);
4228}
4229
4230# $_[0]: Chip to detect (0 = ADM1026)
4231# $_[1]: A reference to the file descriptor to access this chip.
4232#        We may assume an i2c_set_slave_addr was already done.
4233# $_[2]: Address
4234# Returns: undef if not detected, (8) if detected.
4235# Registers used:
4236#   0x16: Company ID
4237#   0x17: Revision
4238sub adm1026_detect
4239{
4240  my $reg;
4241  my ($chip, $file,$addr) = @_;
4242  $reg = i2c_smbus_read_byte_data($file,0x16);
4243  return unless ($reg == 0x41);
4244  return unless (i2c_smbus_read_byte_data($file,0x17) & 0xf0) == 0x40;
4245  return (8);
4246}
4247
4248# $_[0]: Chip to detect (0 = ADM1024)
4249# $_[1]: A reference to the file descriptor to access this chip.
4250#        We may assume an i2c_set_slave_addr was already done.
4251# $_[2]: Address
4252# Returns: undef if not detected, (8) if detected.
4253# Registers used:
4254#   0x3e: Company ID
4255#   0x3f: Revision
4256#   0x40: Configuration
4257sub adm1024_detect
4258{
4259  my $reg;
4260  my ($chip, $file,$addr) = @_;
4261  $reg = i2c_smbus_read_byte_data($file,0x3e);
4262  return unless ($reg == 0x41);
4263  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4264  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x10;
4265  return (8);
4266}
4267
4268# $_[0]: Chip to detect
4269#   (0 = ADM1021, 1 = ADM1021A/ADM1023, 2 = MAX1617, 3 = MAX1617A, 4 = THMC10,
4270#    5 = LM84, 6 = GL523, 7 = MC1066)
4271# $_[1]: A reference to the file descriptor to access this chip.
4272#        We may assume an i2c_set_slave_addr was already done.
4273# $_[2]: Address
4274# Returns: undef if not detected, 3 if simply detected, 5 if detected and
4275#          manufacturer ID matches, 7 if detected and manufacturer ID and
4276#          revision match
4277# Registers used:
4278#   0x04: Company ID (LM84 only)
4279#   0xfe: Company ID (all but LM84 and MAX1617)
4280#   0xff: Revision (ADM1021, ADM1021A/ADM1023 and MAX1617A)
4281#   0x02: Status
4282#   0x03: Configuration
4283#   0x04: Conversion rate
4284#   0x00-0x01, 0x05-0x08: Temperatures (MAX1617 and LM84)
4285# Note: Especially the MAX1617 has very bad detection; we give it a low
4286# confidence value.
4287sub adm1021_detect
4288{
4289  my ($chip, $file, $addr) = @_;
4290  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
4291  my $rev = i2c_smbus_read_byte_data($file, 0xff);
4292  my $conf = i2c_smbus_read_byte_data($file, 0x03);
4293  my $status = i2c_smbus_read_byte_data($file, 0x02);
4294  my $convrate = i2c_smbus_read_byte_data($file, 0x04);
4295
4296  # Check manufacturer IDs and product revisions when available
4297  return if $chip == 0 and $man_id != 0x41 ||
4298                          ($rev & 0xf0) != 0x00;
4299  return if $chip == 1 and $man_id != 0x41 ||
4300                          ($rev & 0xf0) != 0x30;
4301  return if $chip == 3 and $man_id != 0x4d ||
4302                           $rev != 0x01;
4303  return if $chip == 4 and $man_id != 0x49;
4304  return if $chip == 5 and $convrate != 0x00;
4305  return if $chip == 6 and $man_id != 0x23;
4306  return if $chip == 7 and $man_id != 0x54;
4307
4308  # Check unused bits
4309  if ($chip == 5) # LM84
4310  {
4311    return if ($status & 0xab) != 0;
4312    return if ($conf & 0x7f) != 0;
4313  }
4314  else
4315  {
4316    return if ($status & 0x03) != 0;
4317    return if ($conf & 0x3f) != 0;
4318    return if ($convrate & 0xf8) != 0;
4319  }
4320
4321  # Extra checks for MAX1617 and LM84, since those are often misdetected
4322  # We verify several assertions (6 for the MAX1617, 4 for the LM84) and
4323  # discard the chip if any fail. Note that these checks are not done
4324  # by the adm1021 driver.
4325  if ($chip == 2 || $chip == 5)
4326  {
4327    my $lte = i2c_smbus_read_byte_data($file, 0x00);
4328    my $rte = i2c_smbus_read_byte_data($file, 0x01);
4329    my $lhi = i2c_smbus_read_byte_data($file, 0x05);
4330    my $rhi = i2c_smbus_read_byte_data($file, 0x07);
4331    my $llo = i2c_smbus_read_byte_data($file, 0x06);
4332    my $rlo = i2c_smbus_read_byte_data($file, 0x08);
4333
4334    # If all registers hold the same value, it has to be a misdetection
4335    return if $lte == $rte and $lte == $lhi and $lte == $rhi
4336           and $lte == $llo and $lte == $rlo;
4337
4338    # Negative temperatures
4339    return if ($lte & 0x80) or ($rte & 0x80);
4340    # Negative high limits
4341    return if ($lhi & 0x80) or ($rhi & 0x80);
4342    # Low limits over high limits
4343    if ($chip != 5) # LM84 doesn't have low limits
4344    {
4345      $llo-=256 if ($llo & 0x80);
4346      $rlo-=256 if ($rlo & 0x80);
4347      return if ($llo > $lhi) or ($rlo > $rhi);
4348    }
4349  }
4350
4351  return 3 if ($chip == 2) or ($chip == 5);
4352  return 7 if $chip <= 3;
4353  return 5;
4354}
4355
4356# $_[0]: Chip to detect
4357#   (0 = MAX1619)
4358# $_[1]: A reference to the file descriptor to access this chip.
4359#        We may assume an i2c_set_slave_addr was already done.
4360# $_[2]: Address
4361# Returns: undef if not detected, 7 if detected
4362# Registers used:
4363#   0xfe: Company ID
4364#   0xff: Device ID
4365#   0x02: Status
4366#   0x03: Configuration
4367#   0x04: Conversion rate
4368sub max1619_detect
4369{
4370  my ($chip, $file, $addr) = @_;
4371  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
4372  my $dev_id = i2c_smbus_read_byte_data($file, 0xff);
4373  my $conf = i2c_smbus_read_byte_data($file, 0x03);
4374  my $status = i2c_smbus_read_byte_data($file, 0x02);
4375  my $convrate = i2c_smbus_read_byte_data($file, 0x04);
4376
4377  return if $man_id != 0x4D
4378    or $dev_id != 0x04
4379    or ($conf & 0x03)
4380    or ($status & 0x61)
4381    or $convrate >= 8;
4382
4383  return 7;
4384}
4385
4386# $_[0]: A reference to the file descriptor to access this chip.
4387# $_[1]: Address (unused)
4388# Returns: undef if not detected, 6 if detected.
4389# Registers used:
4390#   0x28: User ID
4391#   0x29: User ID2
4392#   0x2A: Version ID
4393
4394sub ite_overclock_detect
4395{
4396  my ($file, $addr) = @_;
4397
4398  my $uid1 = i2c_smbus_read_byte_data($file, 0x28);
4399  my $uid2 = i2c_smbus_read_byte_data($file, 0x29);
4400  return if $uid1 != 0x83
4401         || $uid2 != 0x12;
4402
4403  return 6;
4404}
4405
4406# $_[0]: Chip to detect (0 = IT8712F)
4407# $_[1]: A reference to the file descriptor to access this chip.
4408#        We may assume an i2c_set_slave_addr was already done.
4409# $_[2]: Address
4410# Returns: undef if not detected, 7 or 8 if detected (tops LM78).
4411# Registers used:
4412#   0x00: Configuration
4413#   0x48: Full I2C Address
4414#   0x58: Mfr ID
4415#   0x5b: Device ID (not on IT8705)
4416# Note that this function is always called through a closure, so the
4417# arguments are shifted by one place.
4418sub ite_detect
4419{
4420  my $reg;
4421  my ($chip,$file,$addr) = @_;
4422  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
4423  return unless (i2c_smbus_read_byte_data($file, 0x00) & 0x90) == 0x10;
4424  return unless i2c_smbus_read_byte_data($file,0x58) == 0x90;
4425  return if $chip == 0 and i2c_smbus_read_byte_data($file,0x5b) != 0x12;
4426  return (7 + ($addr == 0x2d));
4427}
4428
4429
4430# $_[0]: Chip to detect (0 = IT8712F)
4431# $_[1]: ISA address
4432# $_[2]: I2C file handle
4433# $_[3]: I2C address
4434sub ite_alias_detect
4435{
4436  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
4437  my $i;
4438  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
4439  return 0 unless &$readproc(0x48) == $i2c_addr;
4440  for ($i = 0x30; $i <= 0x45; $i++) {
4441    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
4442  }
4443  return 1;
4444}
4445
4446# $_[0]: Chip to detect (0 = SPD EEPROM, 1 = Sony Vaio EEPROM,
4447#                        2 = SPD EEPROM with Software Write Protect)
4448# $_[1]: A reference to the file descriptor to access this chip
4449# $_[2]: Address
4450# Returns: 8 for a memory eeprom (9 if write-protect register found),
4451#          4 to 9 for a Sony Vaio eeprom,
4452#          1 for an unknown eeprom (2 if write-protect register found)
4453# Registers used:
4454#   0-63: SPD Data and Checksum
4455#   0x80-0x83: Sony Vaio Data ("PCG-")
4456#   0xe2, 0xe5, 0xe8, 0xeb, Oxee: Sony Vaio Timestamp constant bytes.
4457#   0x1a-0x1c: Sony Vaio MAC address
4458# This detection function is a bit tricky; this is to workaround
4459# wrong misdetection messages that would else arise.
4460sub eeprom_detect
4461{
4462  my ($chip,$file,$addr) = @_;
4463  my $checksum = 0;
4464
4465  # Check the checksum for validity (works for most DIMMs and RIMMs)
4466  if ($chip != 1) {
4467          for (my $i = 0; $i <= 62; $i ++) {
4468            $checksum += i2c_smbus_read_byte_data($file,$i);
4469          }
4470          $checksum &= 255;
4471          $checksum -= i2c_smbus_read_byte_data($file,63);
4472  }     
4473  if ($chip == 0) {
4474        if($checksum == 0) {
4475                return 8;
4476        } else {
4477                return 1;
4478        }
4479  }     
4480  if ($chip == 2) {
4481        # check for 'shadow' write-protect register at 0x30-0x37
4482        # could be dangerous
4483        i2c_set_slave_addr($file,$addr - 0x20);
4484        if(i2c_smbus_write_quick($file, SMBUS_WRITE) >= 0 &&
4485           i2c_smbus_read_byte_data($file,0x80) == -1) {
4486                i2c_set_slave_addr($file,$addr);
4487                if($checksum == 0) {
4488                        return (9, $addr - 0x20);
4489                } else {
4490                        return (2, $addr - 0x20);
4491                }
4492        }
4493        i2c_set_slave_addr($file,$addr);
4494        return;
4495  }
4496
4497  # Look for a Sony Vaio EEPROM ($chip == 1)
4498  my $vaioconf = 1;
4499  $vaioconf += 4
4500    if i2c_smbus_read_byte_data($file,0x80) == 0x50
4501    && i2c_smbus_read_byte_data($file,0x81) == 0x43
4502    && i2c_smbus_read_byte_data($file,0x82) == 0x47
4503    && i2c_smbus_read_byte_data($file,0x83) == 0x2d;
4504  $vaioconf += 5
4505    if i2c_smbus_read_byte_data($file,0xe2) == 0x2f
4506    && i2c_smbus_read_byte_data($file,0xe5) == 0x2f
4507    && i2c_smbus_read_byte_data($file,0xe8) == 0x20
4508    && i2c_smbus_read_byte_data($file,0xeb) == 0x3a
4509    && i2c_smbus_read_byte_data($file,0xee) == 0x3a;
4510  $vaioconf += 3
4511    if i2c_smbus_read_byte_data($file,0x1a) == 0x08
4512    && i2c_smbus_read_byte_data($file,0x1b) == 0x00
4513    && i2c_smbus_read_byte_data($file,0x1c) == 0x46;
4514  $vaioconf = 9
4515    if $vaioconf > 9;
4516
4517  if ($vaioconf > 1) {
4518    return $vaioconf;
4519  }
4520  return;
4521}
4522
4523# $_[0]: A reference to the file descriptor to access this chip.
4524#        We may assume an i2c_set_slave_addr was already done.
4525# $_[1]: Address
4526# Returns: undef if not detected, (1) if detected.
4527# Registers used:
4528#   0x00..0x07: DDC signature
4529#   0x08..0x7E: checksumed area
4530#   0x7F:       checksum
4531sub ddcmonitor_detect
4532{
4533  my ($file,$addr) = @_;
4534  my $i;
4535
4536  return unless
4537    i2c_smbus_read_byte_data($file,0x00) == 0x00 and
4538    i2c_smbus_read_byte_data($file,0x01) == 0xFF and
4539    i2c_smbus_read_byte_data($file,0x02) == 0xFF and
4540    i2c_smbus_read_byte_data($file,0x03) == 0xFF and
4541    i2c_smbus_read_byte_data($file,0x04) == 0xFF and
4542    i2c_smbus_read_byte_data($file,0x05) == 0xFF and
4543    i2c_smbus_read_byte_data($file,0x06) == 0xFF and
4544    i2c_smbus_read_byte_data($file,0x07) == 0x00;
4545
4546  # Check the checksum for validity.
4547  my $checksum = 0;
4548  for ($i = 0; $i <= 127; $i = $i + 1) {
4549    $checksum = $checksum + i2c_smbus_read_byte_data($file,$i);
4550  }
4551  $checksum=$checksum & 255;
4552  if ($checksum != 0) {
4553    # I have one such monitor...
4554    return (2,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
4555  }
4556  return (8,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
4557}
4558
4559# $_[0]: A reference to the file descriptor to access this chip.
4560#        We may assume an i2c_set_slave_addr was already done.
4561# $_[1]: Address
4562# Returns: undef if not detected, (8) if detected.
4563# Registers used:
4564#   0x00-0x02: Identification ('P','E','G' -> Pegasus ? :-)
4565sub fscpos_detect
4566{
4567  my ($file,$addr) = @_;
4568  # check the first 3 registers
4569  if (i2c_smbus_read_byte_data($file,0x00) != 0x50) {
4570        return;
4571  }
4572  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
4573        return;
4574  }
4575  if (i2c_smbus_read_byte_data($file,0x02) != 0x47) {
4576        return;
4577  }
4578  return (8);
4579}
4580
4581# $_[0]: A reference to the file descriptor to access this chip.
4582#        We may assume an i2c_set_slave_addr was already done.
4583# $_[1]: Address
4584# Returns: undef if not detected, (8) if detected.
4585# Registers used:
4586#   0x00-0x02: Identification ('S','C','Y')
4587sub fscscy_detect
4588{
4589  my ($file,$addr) = @_;
4590  # check the first 3 registers
4591  if (i2c_smbus_read_byte_data($file,0x00) != 0x53) {
4592        return;
4593  }
4594  if (i2c_smbus_read_byte_data($file,0x01) != 0x43) {
4595        return;
4596  }
4597  if (i2c_smbus_read_byte_data($file,0x02) != 0x59) {
4598        return;
4599  }
4600  return (8);
4601}
4602
4603# $_[0]: A reference to the file descriptor to access this chip.
4604#        We may assume an i2c_set_slave_addr was already done.
4605# $_[1]: Address
4606# Returns: undef if not detected, (8) if detected.
4607# Registers used:
4608#   0x00-0x02: Identification ('H','E','R')
4609sub fscher_detect
4610{
4611  my ($file,$addr) = @_;
4612  # check the first 3 registers
4613  if (i2c_smbus_read_byte_data($file,0x00) != 0x48) {
4614        return;
4615  }
4616  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
4617        return;
4618  }
4619  if (i2c_smbus_read_byte_data($file,0x02) != 0x52) {
4620        return;
4621  }
4622  return (8);
4623}
4624
4625# $_[0]: A reference to the file descriptor to access this chip.
4626#        We assume an i2c_set_slave_addr was already done.
4627# $_[1]: Address (unused)
4628# Returns: undef if not detected, 5 if detected.
4629# Registers used:
4630#   0x3E: Manufacturer ID
4631#   0x3F: Version/Stepping
4632sub lm93_detect
4633{
4634  my $file = shift;
4635  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x01
4636            and i2c_smbus_read_byte_data($file, 0x3F) == 0x73;
4637  return 5;
4638}
4639
4640# $_[0]: A reference to the file descriptor to access this chip.
4641#        We may assume an i2c_set_slave_addr was already done.
4642# $_[1]: Address
4643# Returns: undef if not detected, (7) if detected.
4644# Registers used:
4645#   0x3F: Revision ID
4646#   0x48: Address
4647#   0x4A, 0x4B, 0x4F, 0x57, 0x58: Reserved bits.
4648# We do not use 0x49's reserved bits on purpose. The register is named
4649# "VID4/Device ID" so it is doubtful bits 7-1 are really unused.
4650sub m5879_detect
4651{
4652  my ($file, $addr) = @_;
4653
4654  return
4655    unless i2c_smbus_read_byte_data($file, 0x3F) == 0x01;
4656 
4657  return
4658    unless i2c_smbus_read_byte_data($file, 0x48) == $addr;
4659 
4660  return
4661    unless (i2c_smbus_read_byte_data($file, 0x4A) & 0x06) == 0
4662       and (i2c_smbus_read_byte_data($file, 0x4B) & 0xFC) == 0
4663       and (i2c_smbus_read_byte_data($file, 0x4F) & 0xFC) == 0
4664       and (i2c_smbus_read_byte_data($file, 0x57) & 0xFE) == 0
4665       and (i2c_smbus_read_byte_data($file, 0x58) & 0xEF) == 0;
4666
4667  return (7);
4668}
4669
4670# $_[0]: A reference to the file descriptor to access this chip.
4671#        We assume an i2c_set_slave_addr was already done.
4672# $_[1]: Address
4673# Returns: undef if not detected, 5 or 6 if detected.
4674# Registers used:
4675#   0x3E: Manufacturer ID
4676#   0x3F: Version/Stepping
4677#   0x47: VID (3 reserved bits)
4678#   0x49: VID4 (7 reserved bits)
4679sub smsc47m192_detect
4680{
4681  my ($file, $addr) = @_;
4682  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x55
4683           and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF0) == 0x20
4684           and (i2c_smbus_read_byte_data($file, 0x47) & 0x70) == 0x00
4685           and (i2c_smbus_read_byte_data($file, 0x49) & 0xFE) == 0x80;
4686  return ($addr == 0x2d ? 6 : 5);
4687}
4688
4689# $_[0]: A reference to the file descriptor to access this chip.
4690#        We assume an i2c_set_slave_addr was already done.
4691# $_[1]: Address
4692# Returns: undef if not detected, 5 or 6 if detected.
4693# Registers used:
4694#   0x3E: Manufacturer ID
4695#   0x3F: Version/Stepping
4696#   0x40: Configuration (2 reserved bits)
4697#   0x42: Interrupt Status 2 (1 reserved bit)
4698#   0x43: VID (2 reserved bits)
4699sub dme1737_detect
4700{
4701  my ($file, $addr) = @_;
4702  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x55
4703           and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF8) == 0x88
4704           and (i2c_smbus_read_byte_data($file, 0x40) & 0xC4) == 0x04
4705           and (i2c_smbus_read_byte_data($file, 0x42) & 0x02) == 0x00
4706           and (i2c_smbus_read_byte_data($file, 0x43) & 0xC0) == 0x00;
4707  return ($addr == 0x2e ? 6 : 5);
4708}
4709
4710# $_[0]: Chip to detect
4711#   (1 = F75111R/RG/N, 2 = F75121R/F75122R/RG, 3 = F75373S/SG,
4712#    4 = F75375S/SP, 5 = F75387SG/RG, 6 = F75383M/S/F75384M/S,
4713#    7 = custom power control IC)
4714# $_[1]: A reference to the file descriptor to access this chip.
4715#        We assume an i2c_set_slave_addr was already done.
4716# $_[2]: Address (unused)
4717# Returns: undef if not detected, 7 if detected.
4718# Registers used:
4719#   0x5A-0x5B: Chip ID
4720#   0x5D-0x5E: Vendor ID
4721sub fintek_detect
4722{
4723  my ($chip, $file, $addr) = @_;
4724  my $chipid = (i2c_smbus_read_byte_data($file, 0x5A) << 8)
4725             | i2c_smbus_read_byte_data($file, 0x5B);
4726  my $vendid = (i2c_smbus_read_byte_data($file, 0x5D) << 8)
4727             | i2c_smbus_read_byte_data($file, 0x5E);
4728
4729  return unless $vendid == 0x1934; # Fintek ID
4730
4731  if ($chip == 1) { # F75111R/RG/N
4732    return unless $chipid == 0x0300;
4733  } elsif ($chip == 2) { # F75121R/F75122R/RG
4734    return unless $chipid == 0x0301;
4735  } elsif ($chip == 3) { # F75373S/SG
4736    return unless $chipid == 0x0204;
4737  } elsif ($chip == 4) { # F75375S/SP
4738    return unless $chipid == 0x0306;
4739  } elsif ($chip == 5) { # F75387SG/RG
4740    return unless $chipid == 0x0410;
4741  } elsif ($chip == 6) { # F75383M/S/F75384M/S
4742    # The datasheet has 0x0303, but Fintek say 0x0413 is also possible
4743    return unless $chipid == 0x0303 || $chipid == 0x0413;
4744  } elsif ($chip == 7) { # custom power control IC
4745    return unless $chipid == 0x0302;
4746  }
4747
4748  return 7;
4749}
4750
4751# $_[0]: A reference to the file descriptor to access this chip.
4752#        We may assume an i2c_set_slave_addr was already done.
4753# $_[1]: Address
4754# Returns: undef if not detected, 4 or 7 if detected
4755# Detection is based on the fact that the SAA1064 has only one readable
4756# register, and thus ignores the read address. This register can have value
4757# 0x80 (first read since power-up) or 0x00.
4758sub saa1064_detect
4759{
4760        my ($file,$addr) = @_;
4761        my $status = i2c_smbus_read_byte_data ($file, 0x00);
4762
4763        return if ($status & 0x7f) != 0x00;
4764
4765        for (my $i=0 ; $i<256; $i++) {
4766                return if i2c_smbus_read_byte_data ($file, $i) != 0x00;
4767        }
4768
4769        return 7
4770                if $status == 0x80;
4771        return 4;
4772}
4773
4774# $_[0]: A reference to the file descriptor to access this chip.
4775#        We may assume an i2c_set_slave_addr was already done.
4776# $_[1]: Address
4777# Returns: undef if not detected, 1 if detected
4778# Detection is rather difficult, since the PCA9540 has a single register.
4779# Fortunately, no other device is known to live at this address.
4780sub pca9540_detect
4781{
4782        my ($file, $addr) = @_;
4783        my $reg = i2c_smbus_read_byte($file);
4784
4785        return if ($reg & 0xfa);
4786        return if $reg != i2c_smbus_read_byte($file);
4787        return if $reg != i2c_smbus_read_byte($file);
4788        return if $reg != i2c_smbus_read_byte($file);
4789
4790        return 1;
4791}
4792
4793# $_[0]: A reference to the file descriptor to access this chip.
4794#        We assume an i2c_set_slave_addr was already done.
4795# $_[1]: Address (unused)
4796# Returns: undef if not detected, 1 if detected
4797# Detection is rather difficult, since the PCA9556 only has 4 registers
4798# and no unused bit. We use the fact that the registers cycle over
4799# 4 addresses boundaries, and the logic rules between registers.
4800sub pca9556_detect
4801{
4802        my ($file, $addr) = @_;
4803        my $input = i2c_smbus_read_byte_data($file, 0x00);
4804        my $output = i2c_smbus_read_byte_data($file, 0x01);
4805        my $invert = i2c_smbus_read_byte_data($file, 0x02);
4806        my $config = i2c_smbus_read_byte_data($file, 0x03);
4807
4808        # Pins configured for output (config = 0) must obey the following
4809        # rule: input = output ^ invert
4810
4811        return unless ($input & ~$config) == (($output ^ $invert) & ~$config);
4812
4813        for (my $i = 5; $i < 254 ; $i+=4) {
4814                return unless i2c_smbus_read_byte_data($file, $i) == $output;
4815                return unless i2c_smbus_read_byte_data($file, $i+1) == $invert;
4816                return unless i2c_smbus_read_byte_data($file, $i+2) == $config;
4817        }
4818
4819        return 1;
4820}
4821
4822# $_[0]: A reference to the file descriptor to access this chip.
4823#        We may assume an i2c_set_slave_addr was already done.
4824# $_[1]: Address
4825# Returns: undef if not detected, 3 if detected
4826sub max6900_detect
4827{
4828        my ($file,$addr) = @_;
4829        my $reg;
4830       
4831        # SEC
4832        $reg = i2c_smbus_read_byte_data ($file, 0x81);
4833        return if
4834                ($reg & 0xF0) > 0x50 or
4835                ($reg & 0x0F) > 9;
4836
4837        # MIN
4838        $reg = i2c_smbus_read_byte_data ($file, 0x83);
4839        return if
4840                ($reg & 0xF0) > 0x50 or
4841                ($reg & 0x0F) > 9;
4842
4843        # HR
4844        $reg = i2c_smbus_read_byte_data ($file, 0x85);
4845        return if
4846                ($reg & 0x40) != 0x00 or
4847                ($reg & 0x0F) > 9;
4848
4849        # DATE
4850        $reg = i2c_smbus_read_byte_data ($file, 0x87);
4851        return if
4852                $reg == 0x00 or
4853                ($reg & 0xF0) > 0x30 or
4854                ($reg & 0x0F) > 9;
4855
4856        # MONTH
4857        $reg = i2c_smbus_read_byte_data ($file, 0x89);
4858        return if
4859                $reg == 0x00 or
4860                ($reg & 0xF0) > 0x10 or
4861                ($reg & 0x0F) > 9;
4862
4863        # DAY
4864        $reg = i2c_smbus_read_byte_data ($file, 0x8B);
4865        return if
4866                $reg == 0 or
4867                $reg > 7;
4868
4869        # YEAR
4870        $reg = i2c_smbus_read_byte_data ($file, 0x8D);
4871        return if
4872                ($reg & 0xF0) > 0x90 or
4873                ($reg & 0x0F) > 9;
4874
4875        # CONTROL
4876        $reg = i2c_smbus_read_byte_data ($file, 0x8F);
4877        return if
4878                ($reg & 0x7F) != 0x00;
4879
4880        # CENTURY
4881        $reg = i2c_smbus_read_byte_data ($file, 0x93);
4882        return if
4883                ($reg & 0xF0) > 0x90 or
4884                ($reg & 0x0F) > 9;
4885
4886        return 3;
4887}
4888
4889# $_[0]: A reference to the file descriptor to access this chip.
4890#        We may assume an i2c_set_slave_addr was already done.
4891# $_[1]: Address
4892# Returns: 1
4893# This is a placeholder so we get a report if any device responds
4894# to the SMBus Device Default Address (0x61), which is used for
4895# ARP in SMBus 2.0.
4896sub arp_detect
4897{
4898  return (1);
4899}
4900
4901# This checks for non-FFFF values for SpecInfo and Status.
4902# The address (0x09) is specified by the SMBus standard so it's likely
4903# that this really is a smart battery charger.
4904# $_[0]: A reference to the file descriptor to access this chip.
4905#        We may assume an i2c_set_slave_addr was already done.
4906# $_[1]: Address
4907# Returns: 5
4908sub smartbatt_chgr_detect
4909{
4910  my ($file,$addr) = @_;
4911  # check some registers
4912  if (i2c_smbus_read_word_data($file,0x11) == 0xffff) {
4913        return;
4914  }
4915  if (i2c_smbus_read_word_data($file,0x13) == 0xffff) {
4916        return;
4917  }
4918  return (5);
4919}
4920
4921# This checks for non-FFFF values for State and Info.
4922# The address (0x0a) is specified by the SMBus standard so it's likely
4923# that this really is a smart battery manager/selector.
4924# $_[0]: A reference to the file descriptor to access this chip.
4925#        We may assume an i2c_set_slave_addr was already done.
4926# $_[1]: Address
4927# Returns: 5
4928sub smartbatt_mgr_detect
4929{
4930  my ($file,$addr) = @_;
4931  # check some registers
4932  if (i2c_smbus_read_word_data($file,0x01) == 0xffff) {
4933        return;
4934  }
4935  if (i2c_smbus_read_word_data($file,0x04) == 0xffff) {
4936        return;
4937  }
4938  return (5);
4939}
4940
4941# This checks for non-FFFF values for temperature, voltage, and current.
4942# The address (0x0b) is specified by the SMBus standard so it's likely
4943# that this really is a smart battery.
4944# $_[0]: A reference to the file descriptor to access this chip.
4945#        We may assume an i2c_set_slave_addr was already done.
4946# $_[1]: Address
4947# Returns: 5
4948sub smartbatt_detect
4949{
4950  my ($file,$addr) = @_;
4951  # check some registers
4952  if (i2c_smbus_read_word_data($file,0x08) == 0xffff) {
4953        return;
4954  }
4955  if (i2c_smbus_read_word_data($file,0x09) == 0xffff) {
4956        return;
4957  }
4958  if (i2c_smbus_read_word_data($file,0x0a) == 0xffff) {
4959        return;
4960  }
4961  return (5);
4962}
4963
4964# Returns: 4
4965# These are simple detectors that only look for a register at the
4966# standard location. No writes are performed.
4967# For KCS, use the STATUS register. For SMIC, use the FLAGS register.
4968sub ipmi_kcs_detect
4969{
4970  return if inb (0x0ca3) == 0xff;
4971  return (4);
4972}
4973
4974sub ipmi_smic_detect
4975{
4976  return if inb (0x0cab) == 0xff;
4977  return (4);
4978}
4979
4980# $_[0]: Chip to detect (0 = W83L784R/AR, 1 = W83L785R)
4981# $_[1]: A reference to the file descriptor to access this chip.
4982# $_[2]: Address
4983# Returns: undef if not detected, 6 or 8 if detected
4984# Registers used:
4985#   0x40: Configuration
4986#   0x4a: Full I2C Address (not W83L785R)
4987#   0x4b: I2C addresses of emulated LM75 chips (not W83L785R)
4988#   0x4c: Winbond Vendor ID (Low Byte)
4989#   0x4d: Winbond Vendor ID (High Byte)
4990#   0x4e: Chip ID
4991# Note that this function is always called through a closure, so the
4992# arguments are shifted by one place.
4993sub w83l784r_detect
4994{
4995  my ($reg,@res);
4996  my ($chip,$file,$addr) = @_;
4997
4998  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4999  return if $chip == 0
5000    and i2c_smbus_read_byte_data($file,0x4a) != $addr;
5001  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
5002  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
5003  return if $chip == 0
5004    and i2c_smbus_read_byte_data($file,0x4e) != 0x50;
5005  return if $chip == 1
5006    and i2c_smbus_read_byte_data($file,0x4e) != 0x60;
5007
5008  $reg = i2c_smbus_read_byte_data($file,0x4b);
5009
5010  return 6 if $chip == 1; # W83L785R doesn't have subclients
5011 
5012  @res = (8);
5013  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08 ;
5014  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
5015  return @res;
5016}
5017
5018# $_[0]: Chip to detect (0 = W83L785TS-S)
5019# $_[1]: A reference to the file descriptor to access this chip.
5020#        We may assume an i2c_set_slave_addr was already done.
5021# $_[2]: Address
5022# Returns: undef if not detected, 8 if detected
5023# Registers used:
5024#   0x4C-4E: Mfr and Chip ID
5025# Note that this function is always called through a closure, so the
5026# arguments are shifted by one place.
5027sub w83l785ts_detect
5028{
5029  my ($chip,$file,$addr) = @_;
5030  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
5031  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
5032  return unless i2c_smbus_read_byte_data($file,0x4e) == 0x70;
5033  return (8);
5034}
5035
5036# $_[0]: Chip to detect. Always zero for now, but available for future use
5037#        if somebody finds a way to distinguish MAX6650 and MAX6651.
5038# $_[1]: A reference to the file descriptor to access this chip.
5039#        We may assume an i2c_set_slave_addr was already done.
5040# $_[2]: Address
5041# Returns: undef if not detected, 4 if detected.
5042#
5043# The max6650 has no device ID register. However, a few registers have
5044# spare bits, which are documented as being always zero on read. We read
5045# all of these registers check the spare bits. Any non-zero means this
5046# is not a max6650/1.
5047#
5048# The always zero bits are:
5049#   configuration byte register (0x02) - top 2 bits
5050#   gpio status register (0x14) - top 3 bits
5051#   alarm enable register (0x08) - top 3 bits
5052#   alarm status register (0x0A) - top 3 bits
5053#   tachometer count time register (0x16) - top 6 bits
5054# Additionally, not all values are possible for lower 3 bits of
5055# the configuration register.
5056sub max6650_detect
5057{
5058  my ($chip, $file) = @_;
5059
5060  my $conf = i2c_smbus_read_byte_data($file,0x02);
5061 
5062  return if i2c_smbus_read_byte_data($file,0x16) & 0xFC;
5063  return if i2c_smbus_read_byte_data($file,0x0A) & 0xE0;
5064  return if i2c_smbus_read_byte_data($file,0x08) & 0xE0;
5065  return if i2c_smbus_read_byte_data($file,0x14) & 0xE0;
5066  return if ($conf & 0xC0) or ($conf & 0x07) > 4;
5067
5068  return 4;
5069}
5070
5071# $_[0]: Chip to detect (0 = VT1211)
5072# $_[1]: A reference to the file descriptor to access this chip.
5073#        We may assume an i2c_set_slave_addr was already done.
5074# $_[2]: Address
5075#
5076# This isn't very good detection.
5077# Verify the i2c address, and the stepping ID (which is 0xb0 on
5078# my chip but could be different for others...
5079#
5080sub vt1211_i2c_detect
5081{
5082  my ($chip,$file,$addr) = @_;
5083  return unless (i2c_smbus_read_byte_data($file,0x48) & 0x7f) == $addr;
5084  return unless i2c_smbus_read_byte_data($file,0x3f) == 0xb0;
5085  return 2;
5086}
5087
5088# $_[0]: Chip to detect (0 = VT1211)
5089# $_[1]: ISA address
5090# $_[2]: I2C file handle
5091# $_[3]: I2C address
5092sub vt1211_alias_detect
5093{
5094  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
5095  my $i;
5096  return 0 unless (inb($isa_addr + 0x48) & 0x7f) == $i2c_addr;
5097  return 0 unless (i2c_smbus_read_byte_data($file,0x48) & 0x7f) == $i2c_addr;
5098  for ($i = 0x2b; $i <= 0x3d; $i ++) {
5099    return 0 unless inb($isa_addr + $i) == i2c_smbus_read_byte_data($file,$i);
5100  }
5101  return 1;
5102}
5103
5104
5105######################
5106# PCI CHIP DETECTION #
5107######################
5108
5109# Returns: undef if not detected, (7) or (9) if detected.
5110# The address is encoded in PCI space. We could decode it and print it.
5111# For Linux 2.4 we should probably check for invalid matches (SiS645).
5112sub sis5595_pci_detect
5113{
5114        return unless exists $pci_list{'1039:0008'};
5115        return (kernel_version_at_least(2, 6, 0) ? 9 : 7);
5116}
5117
5118# Returns: undef if not detected, (9) if detected.
5119# The address is encoded in PCI space. We could decode it and print it.
5120sub via686a_pci_detect
5121{
5122        return unless exists $pci_list{'1106:3057'};
5123        return 9;
5124}
5125
5126# Returns: undef if not detected, (9) if detected.
5127# The address is encoded in PCI space. We could decode it and print it.
5128sub via8231_pci_detect
5129{
5130        return unless exists $pci_list{'1106:8235'};
5131        return 9;
5132}
5133
5134# Returns: undef if not detected, (9) if detected.
5135sub k8temp_pci_detect
5136{
5137        return unless exists $pci_list{'1022:1103'};
5138        return 9;
5139}
5140
5141# Returns: undef if not detected, (9) if detected.
5142sub coretemp_detect
5143{
5144        my $probecpu;
5145        foreach $probecpu (@cpu) {
5146                if ($probecpu->{'vendor_id'} eq 'GenuineIntel' && 
5147                                $probecpu->{'cpu family'} == 6 &&
5148                                ($probecpu->{'model'} == 14 ||
5149                                 $probecpu->{'model'} == 15)) {
5150                        return 9;
5151                }
5152        }
5153        return;
5154}
5155
5156################
5157# MAIN PROGRAM #
5158################
5159
5160# $_[0]: reference to a list of chip hashes
5161sub print_chips_report 
5162{
5163  my ($listref) = @_;
5164  my $data;
5165 
5166  foreach $data (@$listref) {
5167    my $is_i2c = exists $data->{i2c_addr};
5168    my $is_isa = exists $data->{isa_addr};
5169    print "  * ";
5170    if ($is_i2c) {
5171      printf "Bus `%s'\n", $data->{i2c_adap};
5172      printf "    Busdriver `%s', I2C address 0x%02x", 
5173             $data->{i2c_driver}, $data->{i2c_addr};
5174      if (exists $data->{i2c_sub_addrs}) {
5175        print " (and";
5176        my $sub_addr;
5177        foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
5178          printf " 0x%02x",$sub_addr;
5179        }
5180        print ")"
5181      }
5182      print "\n    ";
5183    }
5184    if ($is_isa) {
5185      print "ISA bus";
5186      if ($data->{isa_addr}) {
5187        printf ", address 0x%x", $data->{isa_addr};
5188      }
5189      print " (Busdriver `i2c-isa')"
5190        unless kernel_version_at_least(2, 6, 18);
5191      print "\n    ";
5192    }
5193    printf "Chip `%s' (confidence: %d)\n",
5194           $data->{chipname},  $data->{conf};
5195  }
5196}
5197
5198# $_[0]: 1 if ISA bus is prefered, 0 for SMBus
5199# We build here an array adapters, indexed on the number the adapter has
5200# at this moment (we assume only loaded adapters are interesting at all;
5201# everything that got scanned also got loaded). Each entry is a reference
5202# to a hash containing:
5203#  driver: Name of the adapter driver
5204#  nr_now: Number of the bus now
5205#  nr_later: Number of the bus when the modprobes are done (not included if the
5206#        driver should not be loaded)
5207# A second array, called
5208sub generate_modprobes
5209{
5210  my ($prefer_isa) = @_;
5211
5212  my ($chip,$detection,$nr,$i,@optionlist,@probelist,$driver,$isa,$adap);
5213  my $bmcsensors = 0;
5214  my @adapters;
5215  my $modprobes = "";
5216  my $configfile = "";
5217
5218  # These are always needed
5219  $configfile .= "# I2C module options\n";
5220  $configfile .= "alias char-major-89 i2c-dev\n";
5221
5222  # Collect all loaded adapters
5223  # i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
5224  open(local *INPUTFILE, "i2cdetect -l |") or die "Couldn't find i2cdetect program!!";
5225  local $_;
5226  while (<INPUTFILE>) {
5227    my ($dev_nr, $type, $adap) = /^i2c-(\d+)\s+(\S+)\s+(.*?) *(\t|$)/;
5228    next if ($type eq "dummy" || $type eq "isa");
5229    $adapters[$dev_nr]->{driver} = find_adapter_driver($adap);
5230    $adapters[$dev_nr]->{adapname} = $adap;
5231  }
5232  close INPUTFILE;
5233
5234  # Collect all adapters used
5235  $nr = 0;
5236  $isa = 0;
5237  foreach $chip (@chips_detected) {
5238    foreach $detection (@{$chip->{detected}}) {
5239      # If there is more than one bus detected by a driver, they are
5240      # still all added. So we number them in the correct order
5241      if (exists $detection->{i2c_driver} and
5242          not exists $adapters[$detection->{i2c_devnr}]->{nr_later} and 
5243          not (exists $detection->{isa_addr} and $prefer_isa)) {
5244         foreach $adap (@adapters) {
5245           next unless exists $adap->{driver};
5246           $adap->{nr_later} = $nr++ if $adap->{driver} eq $detection->{i2c_driver};
5247         }
5248      }
5249      if (exists $detection->{isa_addr} and
5250          not (exists $detection->{i2c_driver} and not $prefer_isa)) {
5251           $isa=1;
5252      }
5253      if ($chip->{driver} eq "bmcsensors") {
5254           $bmcsensors=1;
5255      }
5256    }
5257  }
5258
5259  $modprobes .= "# I2C adapter drivers\n" if $nr;
5260  for ($i = 0; $i < $nr; $i++) {
5261    foreach $adap (@adapters) {
5262      next unless exists $adap->{nr_later} and $adap->{nr_later} == $i;
5263      if ($adap->{driver} eq "UNKNOWN") {
5264        $modprobes .= "# modprobe unknown adapter ".$adap->{adapname}."\n";
5265      } elsif ($adap->{driver} eq "DISABLED") {
5266        $modprobes .= "# modprobe disabled adapter ".$adap->{adapname}."\n";
5267      } elsif ($adap->{driver} eq "to-be-written") {
5268        $modprobes .= "# no driver available for adapter ".$adap->{adapname}."\n";
5269      } else {
5270        $modprobes .= "modprobe $adap->{driver}\n"
5271          unless $modprobes =~ /modprobe $adap->{driver}\n/;
5272      }
5273      last;
5274    }
5275  }
5276  # i2c-isa is loaded automatically (as a dependency) since 2.6.14,
5277  # and will soon be gone.
5278  $modprobes .= "modprobe i2c-isa\n" if ($isa && !kernel_version_at_least(2, 6, 18));
5279  if ($bmcsensors) {
5280    $modprobes .= "# You must also install and load the IPMI modules\n";
5281    $modprobes .= "modprobe i2c-ipmi\n";
5282  }
5283
5284  # Now determine the chip probe lines
5285  $modprobes .= "# Chip drivers\n";
5286  foreach $chip (@chips_detected) {
5287    next if not @{$chip->{detected}};
5288    next if $chip->{driver} eq "not-a-sensor";   
5289    next if $chip->{driver} eq "use-isa-instead";
5290    if ($chip->{driver} eq "to-be-written") {
5291      $modprobes .= "# no driver for $chip->{detected}[0]{chipname} yet\n";
5292    } else {
5293       # need the * for 2.4 kernels, won't necessarily be an exact match
5294       open(local *INPUTFILE, "modprobe -l $chip->{driver}\\* 2>/dev/null |");
5295       local $_;
5296       my $modulefound = 0;
5297       while (<INPUTFILE>) {
5298         if(m@/@) {
5299           $modulefound = 1;
5300           last;
5301         }
5302       }
5303       close INPUTFILE;
5304       #check return value from modprobe in case modprobe -l isn't supported
5305       if((($? >> 8) == 0) && ! $modulefound) {
5306         $modprobes .= "# Warning: the required module $chip->{driver} is not currently installed\n".
5307                       "# on your system. For status of 2.6 kernel ports check\n".
5308                       "# http://www.lm-sensors.org/wiki/Devices. If driver is built\n".
5309                       "# into the kernel, or unavailable, comment out the following line.\n";
5310       }
5311       $modprobes .= "modprobe $chip->{driver}\n";
5312    }
5313
5314    # Handle misdetects
5315    foreach $detection (@{$chip->{misdetected}}) {
5316      push @optionlist, $adapters[$detection->{i2c_devnr}]->{nr_later},
5317                       $detection->{i2c_addr}
5318           if exists $detection->{i2c_addr} and
5319              exists $adapters[$detection->{i2c_devnr}]->{nr_later};
5320      push @optionlist, -1, $detection->{isa_addr}
5321           if exists $detection->{isa_addr} and $isa;
5322    }
5323
5324    # Handle aliases
5325    foreach $detection (@{$chip->{detected}}) {
5326      if (exists $detection->{i2c_driver} and 
5327          exists $detection->{isa_addr} and
5328          exists $adapters[$detection->{i2c_devnr}]->{nr_later} and
5329          $isa) {
5330        if ($prefer_isa) {
5331          push @optionlist,$adapters[$detection->{i2c_devnr}]->{nr_later},
5332                           $detection->{i2c_addr};
5333        } else {
5334          push @optionlist, -1, $detection->{isa_addr}
5335        }
5336      }
5337    }
5338
5339    next if not (@probelist or @optionlist);
5340    $configfile .= "options $chip->{driver}";
5341    $configfile .= sprintf " ignore=%d,0x%02x",shift @optionlist, 
5342                                               shift @optionlist
5343                  if @optionlist;
5344    $configfile .= sprintf ",%d,0x%02x",shift @optionlist, shift @optionlist
5345                  while @optionlist;
5346    $configfile .= sprintf " probe=%d,0x%02x",shift @probelist,
5347                                              shift @probelist
5348                  if @probelist;
5349    $configfile .= sprintf ",%d,0x%02x",shift @probelist, shift @probelist
5350                  while @probelist;
5351    $configfile .= "\n";
5352  }
5353
5354  return ($modprobes,$configfile);
5355 
5356}
5357
5358sub main
5359{
5360  my (@adapters,$res,$did_adapter_detection,$adapter);
5361
5362  # We won't go very far if not root
5363  unless ($> == 0) {
5364    print "You need to be root to run this script.\n";
5365    exit -1;
5366  }
5367
5368  initialize_conf;
5369  initialize_proc_pci;
5370  initialize_modules_list;
5371  initialize_modules_supported;
5372  initialize_kernel_version;
5373  initialize_cpu_list();
5374
5375  print "# sensors-detect revision $revision\n\n";
5376
5377  print "This program will help you determine which kernel modules you need\n",
5378        "to load to use lm_sensors most effectively. It is generally safe\n",
5379        "and recommended to accept the default answers to all questions,\n",
5380        "unless you know what you're doing.\n";
5381  print "You need to have i2c and lm_sensors installed before running this\n",
5382        "program.\n"
5383    unless kernel_version_at_least(2, 6, 0);
5384  print "\n";
5385
5386  print "We can start with probing for (PCI) I2C or SMBus adapters.\n";
5387  print "Do you want to probe now? (YES/no): ";
5388  @adapters = adapter_pci_detection
5389                        if ($did_adapter_detection = not <STDIN> =~ /\s*[Nn]/);
5390  print "\n";
5391
5392  if (not $did_adapter_detection) {
5393    print "As you skipped adapter detection, we will only scan already loaded\n".
5394          "adapter modules.\n";
5395  } else {
5396    print "We will now try to load each adapter module in turn.\n";
5397    foreach $adapter (@adapters) {
5398      next if $adapter eq "DISABLED";
5399      next if $adapter eq "to-be-tested";
5400      if (exists($modules_list{$adapter})) {
5401        print "Module `$adapter' already loaded.\n";
5402      } else {
5403        print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
5404        unless (<STDIN> =~ /^\s*[Nn]/) {
5405          if (system ("modprobe", $adapter)) {
5406            print "Loading failed... skipping.\n";
5407          } else {
5408            print "Module loaded successfully.\n";
5409          }
5410        }
5411      }
5412    }
5413  }
5414
5415  print "If you have undetectable or unsupported adapters, you can have them\n".
5416        "scanned by manually loading the modules before running this script.\n\n";
5417
5418  if (!exists($modules_list{"i2c-dev"})
5419   && !(defined $sysfs_root && -e "$sysfs_root/class/i2c-dev")) {
5420    print "To continue, we need module `i2c-dev' to be loaded.\n";
5421    print "If it is built-in into your kernel, you can safely skip this.\n"
5422      unless kernel_version_at_least(2, 6, 0);
5423    print "Do you want to load `i2c-dev' now? (YES/no): ";
5424    if (<STDIN> =~ /^\s*n/i) {
5425      print "Well, you will know best.\n";
5426    } elsif (system "modprobe", "i2c-dev") {
5427      print "Loading failed, expect problems later on.\n";
5428    } else {
5429      print "Module loaded successfully.\n";
5430    }
5431    print "\n";
5432  }
5433
5434  # Before looking for chips, make sure any special case chips are
5435  # added to the chip_ids list
5436  chip_special_cases();
5437
5438  print "We are now going to do the I2C/SMBus adapter probings. Some chips may\n",
5439        "be double detected; we choose the one with the highest confidence\n",
5440        "value in that case.\n",
5441        "If you found that the adapter hung after probing a certain address,\n",
5442        "you can specify that address to remain unprobed.\n";
5443
5444  my ($inp,@not_to_scan,$inp2);
5445  # i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
5446  open(local *INPUTFILE, "i2cdetect -l |") or die "Couldn't find i2cdetect program!!";
5447  local $_;
5448  while (<INPUTFILE>) {
5449    my ($dev_nr, $type, $adap) = /^i2c-(\d+)\s+(\S+)\s+(.*?) *(\t|$)/;
5450    next if ($type eq "dummy" || $type eq "isa");
5451    print "\n";
5452    print "Next adapter: $adap (i2c-$dev_nr)\n";
5453    print "Do you want to scan it? (YES/no/selectively): ";
5454   
5455    $inp = <STDIN>;
5456    if ($inp =~ /^\s*[Ss]/) {
5457      print "Please enter one or more addresses not to scan. Separate them ",
5458            "with comma's.\n",
5459            "You can specify a range by using dashes. Addresses may be ",
5460            "decimal (like 54)\n",
5461            "or hexadecimal (like 0x33).\n",
5462            "Addresses: ";
5463      $inp2 = <STDIN>;
5464      chop $inp2;
5465      @not_to_scan = parse_not_to_scan 0,0x7f,$inp2;
5466    }
5467    scan_adapter $dev_nr, $adap, find_adapter_driver($adap),
5468                 \@not_to_scan   unless $inp =~ /^\s*[Nn]/;
5469  }
5470  print "\n";
5471
5472  print "Some chips are also accessible through the ISA I/O ports. We have to\n".
5473        "write to arbitrary I/O ports to probe them. This is usually safe though.\n".
5474        "Yes, you do have ISA I/O ports even if you do not have any ISA slots!\n";
5475  print "Do you want to scan the ISA I/O ports? (YES/no): ";
5476  unless (<STDIN> =~ /^\s*n/i) {
5477    initialize_ioports();
5478    scan_isa_bus();
5479    close_ioports();
5480  }
5481  print "\n";
5482
5483  print "Some Super I/O chips may also contain sensors. We have to write to\n".
5484        "standard I/O ports to probe them. This is usually safe.\n";
5485  print "Do you want to scan for Super I/O sensors? (YES/no): ";
5486  unless (<STDIN> =~ /^\s*n/i) {
5487    initialize_ioports();
5488    scan_superio(0x2e, 0x2f);
5489    scan_superio(0x4e, 0x4f);
5490    close_ioports();
5491  }
5492  print "\n";
5493
5494  print "Some CPU may also contain embedded sensors.\n";
5495  print "Do you want to scan for CPU embedded sensors? (YES/no): ";
5496  unless (<STDIN> =~ /^\s*n/i) {
5497    foreach my $entry (@cpu_ids) {
5498      scan_cpu($entry);
5499    }
5500  }
5501  print "\n";
5502
5503  if(! @chips_detected) {
5504    print "Sorry, no sensors were detected.\n",
5505          "Either your sensors are not supported, or they are connected to an\n",
5506          "I2C or SMBus adapter that is not supported. See doc/FAQ,\n",
5507          "doc/lm_sensors-FAQ.html or http://www.lm-sensors.org/wiki/FAQ\n",
5508          "(FAQ #4.24.3) for further information.\n",
5509          "If you find out what chips are on your board, check\n",
5510          "http://www.lm-sensors.org/wiki/Devices for driver status.\n";
5511    exit;
5512  }
5513
5514  print "Now follows a summary of the probes I have just done.\n".
5515        "Just press ENTER to continue: ";
5516  <STDIN>;
5517
5518  my ($chip,$data);
5519  foreach $chip (@chips_detected) {
5520    next if $chip->{driver} eq "not-a-sensor";
5521    next if $chip->{driver} eq "use-isa-instead";
5522    print "\nDriver `$chip->{driver}' ";
5523    if (@{$chip->{detected}}) {
5524      if (@{$chip->{misdetected}}) {
5525        print "(should be inserted but causes problems):\n";
5526      } else {
5527        print "(should be inserted):\n";
5528      }
5529    } else {
5530      if (@{$chip->{misdetected}}) {
5531        print "(may not be inserted):\n";
5532      } else {
5533        print "(should not be inserted, but is harmless):\n";
5534      }
5535    }
5536    if (@{$chip->{detected}}) {
5537      print "  Detects correctly:\n";
5538      print_chips_report $chip->{detected};
5539    }
5540    if (@{$chip->{misdetected}}) {
5541      print "  Misdetects:\n";
5542      print_chips_report $chip->{misdetected};
5543    }
5544
5545    # People are easily confused
5546    if ($chip->{driver} eq "eeprom") {
5547      print "\n  EEPROMs are *NOT* sensors! They are data storage chips commonly\n",
5548            "  found on memory modules (SPD), in monitors (EDID), or in some\n",
5549            "  laptops, for example.\n";
5550    }
5551  }
5552  print "\n";
5553
5554  print "I will now generate the commands needed to load the required modules.\n".
5555        "Just press ENTER to continue: ";
5556  <STDIN>;
5557     
5558  print "\n";
5559  my ($modprobes, $configfile) = generate_modprobes 1;  # 1 == prefer ISA
5560  print "To make the sensors modules behave correctly, add these lines to\n".
5561        "$modules_conf:\n\n";
5562  print "#----cut here----\n".
5563        $configfile.
5564        "#----cut here----\n\n";
5565
5566  print "To load everything that is needed, add this to some /etc/rc* file:\n\n";
5567  print "#----cut here----\n".
5568        $modprobes.
5569        "# sleep 2 # optional\n".
5570        "/usr/local/bin/sensors -s # recommended\n".
5571        "#----cut here----\n\n";
5572
5573  print "If you have some drivers built into your kernel, the list above will\n".
5574        "contain too many modules. Skip the appropriate ones! You really\n".
5575        "should try these commands right now to make sure everything is\n".
5576        "working properly. Monitoring programs won't work until the needed\n".
5577        "modules are loaded.\n\n";
5578 
5579  my $have_sysconfig = -d '/etc/sysconfig';
5580  printf "Do you want to \%s /etc/sysconfig/lm_sensors? (\%s): ",
5581         (-e '/etc/sysconfig/lm_sensors' ? 'overwrite' : 'generate'),
5582         ($have_sysconfig ? 'YES/no' : 'yes/NO');
5583  $_ = <STDIN>;
5584  if (($have_sysconfig and not m/^\s*n/i) or m/^\s*y/i) {
5585    unless ($have_sysconfig) {
5586      mkdir '/etc/sysconfig', 0777
5587        or die "Sorry, can't create /etc/sysconfig ($!)";
5588    }
5589    open(local *SYSCONFIG, ">/etc/sysconfig/lm_sensors")
5590      or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)";
5591    print SYSCONFIG <<'EOT';
5592#    /etc/sysconfig/lm_sensors - Defines modules loaded by
5593#                                /etc/init.d/lm_sensors
5594#    Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>
5595#
5596#    This program is free software; you can redistribute it and/or modify
5597#    it under the terms of the GNU General Public License as published by
5598#    the Free Software Foundation; either version 2 of the License, or
5599#    (at your option) any later version.
5600#
5601#    This program is distributed in the hope that it will be useful,
5602#    but WITHOUT ANY WARRANTY; without even the implied warranty of
5603#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5604#    GNU General Public License for more details.
5605#
5606#    You should have received a copy of the GNU General Public License
5607#    along with this program; if not, write to the Free Software
5608#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5609#
5610#
5611# See also the lm_sensors homepage at:
5612#     http://www.lm-sensors.org/
5613#
5614# This file is used by /etc/init.d/lm_sensors and defines the modules to
5615# be loaded/unloaded. This file is sourced into /etc/init.d/lm_sensors.
5616#
5617# The format of this file is a shell script that simply defines the modules
5618# in order as normal variables with the special names:
5619#    MODULE_0, MODULE_1, MODULE_2, etc.
5620#
5621# List the modules that are to be loaded for your system
5622#
5623EOT
5624    print SYSCONFIG
5625      "# Generated by sensors-detect on " . scalar localtime() . "\n";
5626    my @modules = grep /^modprobe /, split "\n", $modprobes;
5627    my $i = 0;
5628    my $sysconfig = "";
5629    foreach (@modules) {
5630      s/^modprobe //;
5631      $sysconfig .= "MODULE_$i=$_\n";
5632      $i++;
5633    }
5634    print SYSCONFIG $sysconfig;
5635
5636    print "Copy prog/init/lm_sensors.init to /etc/init.d/lm_sensors\n".
5637          "for initialization at boot time.\n"
5638      unless -f "/etc/init.d/lm_sensors";
5639  }
5640}
5641
5642main;
Note: See TracBrowser for help on using the browser.