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

Revision 4084, 168.7 KB (checked in by khali, 7 years ago)

Detect the upcoming IT8718F Super-I/O chip. Support will most certainly go
into the it87 driver at some point.

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