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

Revision 2650, 151.1 KB (checked in by khali, 9 years ago)

Detect the LM63.

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