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

Revision 2640, 150.8 KB (checked in by khali, 9 years ago)

Perl cleanups as suggested by ton of #perl@ircnet (part 2).

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