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

Revision 2323, 133.7 KB (checked in by khali, 9 years ago)

Fix broken superio exit sequence handling.

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