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

Revision 3230, 160.1 KB (checked in by khali, 7 years ago)

Drop legacy ISA detection of the W83697HF chip. The w83781d driver
does not support this chip anymore.

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