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

Revision 4079, 170.3 KB (checked in by khali, 7 years ago)

Typo fix, thanks to Brian C for reporting.

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