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

Revision 4043, 164.9 KB (checked in by ruik, 8 years ago)

Fix my stupid error (par was missing)

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