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

Revision 2303, 133.8 KB (checked in by khali, 9 years ago)

Add GeForce? FX 5600 as supported by rivatv.

  • 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 something like
1303#      "Unwritten: <drivername>" 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 modem
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        exitreg => 0x2e,
1375        datareg => 0x2f,
1376        enter => [0x55],
1377        devidreg => 0x20,
1378        devid => 0x59,
1379        logdevreg => 0x07,
1380        logdev => 0x0a,
1381        actreg => 0x20,
1382        actmask => 0x01,
1383        basereg => 0x60,
1384        exitseq => [0x2e, 0xaa],
1385     }, 
1386     {
1387        name => "SMSC 47M14x Super IO Fan Sensors",
1388        driver => "smsc47m1",
1389        addrreg => 0x2e,
1390        exitreg => 0x2e,
1391        datareg => 0x2f,
1392        enter => [0x55],
1393        devidreg => 0x20,
1394        devid => 0x5f,
1395        logdevreg => 0x07,
1396        logdev => 0x0a,
1397        actreg => 0x20,
1398        actmask => 0x01,
1399        basereg => 0x60,
1400        exitseq => [0x2e, 0xaa],
1401     }, 
1402     {
1403        name => "VT1211 Super IO Sensors",
1404        driver => "vt1211",
1405        addrreg => 0x2e,
1406        exitreg => 0x2e,
1407        datareg => 0x2f,
1408        enter => [0x87, 0x87],
1409        devidreg => 0x20,
1410        devid => 0x3c,
1411        logdevreg => 0x07,
1412        logdev => 0x0b,
1413        actreg => 0x30,
1414        actmask => 0x01,
1415        basereg => 0x60,
1416        exitseq => [0x2e, 0xaa],
1417     }, 
1418     {
1419        name => "Winbond W83627HF Super IO Sensors",
1420        driver => "w83627hf",
1421        addrreg => 0x2e,
1422        exitreg => 0x2e,
1423        datareg => 0x2f,
1424        enter => [0x87, 0x87],
1425        devidreg => 0x20,
1426        devid => 0x52,
1427        logdevreg => 0x07,
1428        logdev => 0x0b,
1429        actreg => 0x30,
1430        actmask => 0x01,
1431        basereg => 0x60,
1432        exitseq => [0x2e, 0xaa],
1433     }, 
1434     {
1435        name => "Winbond W83627THF Super IO Sensors",
1436        driver => "w83627hf",
1437        addrreg => 0x2e,
1438        exitreg => 0x2e,
1439        datareg => 0x2f,
1440        enter => [0x87, 0x87],
1441        devidreg => 0x20,
1442        devid => 0x82,
1443        logdevreg => 0x07,
1444        logdev => 0x0b,
1445        actreg => 0x30,
1446        actmask => 0x01,
1447        basereg => 0x60,
1448        exit => 0xaa,
1449     }, 
1450     {
1451        name => "Winbond W83637HF Super IO Sensors",
1452        driver => "w83627hf",
1453        addrreg => 0x2e,
1454        exitreg => 0x2e,
1455        datareg => 0x2f,
1456        enter => [0x87, 0x87],
1457        devidreg => 0x20,
1458        devid => 0x70,
1459        logdevreg => 0x07,
1460        logdev => 0x0b,
1461        actreg => 0x30,
1462        actmask => 0x01,
1463        basereg => 0x60,
1464        exitseq => [0x2e, 0xaa],
1465     }, 
1466     {
1467        name => "Winbond W83697HF Super IO Sensors",
1468        driver => "w83627hf",
1469        addrreg => 0x2e,
1470        exitreg => 0x2e,
1471        datareg => 0x2f,
1472        enter => [0x87, 0x87],
1473        devidreg => 0x20,
1474        devid => 0x60,
1475        logdevreg => 0x07,
1476        logdev => 0x0b,
1477        actreg => 0x30,
1478        actmask => 0x01,
1479        basereg => 0x60,
1480        exit => 0xaa,
1481     }, 
1482     {
1483        name => "Winbond W83697UF Super IO PWM",
1484        driver => "to-be-written",
1485        addrreg => 0x2e,
1486        exitreg => 0x2e,
1487        datareg => 0x2f,
1488        enter => [0x87, 0x87],
1489        devidreg => 0x20,
1490        devid => 0x68,
1491        logdevreg => 0x07,
1492        logdev => 0x0b,
1493        actreg => 0x30,
1494        actmask => 0x01,
1495        basereg => 0x60,
1496        exitseq => [0x2e, 0xaa],
1497     }, 
1498);
1499
1500#######################
1501# AUXILIARY FUNCTIONS #
1502#######################
1503
1504sub swap_bytes
1505{
1506  return (($_[0] & 0xff00) >> 8) + (($_[0] & 0x00ff) << 8)
1507}
1508
1509# $_[0] is the sought value
1510# @_[1..] is the list to seek in
1511# Returns: 0 on failure, 1 if found.
1512sub contains
1513{
1514  my $sought = shift;
1515  foreach (@_) {
1516    return 1 if $sought eq $_;
1517  }
1518  return 0;
1519}
1520
1521sub parse_not_to_scan
1522{
1523  my ($min,$max,$to_parse) = @_;
1524  my @ranges = split /\s*,\s*/, $to_parse;
1525  my @res = ();
1526  my $range;
1527  foreach $range (@ranges) {
1528    my ($start,$end) = split /\s*-s*/, $range;
1529    $start = oct $start if $start =~ /^0/;
1530    if (defined $end) {
1531      $end = oct $end if $end =~ /^0/;
1532      $start = $min if $start < $min;
1533      $end = $max if $end > $max;
1534      push @res, ($start+0..$end+0);
1535    } else {
1536      push @res, $start+0 if $start >= $min and $start <= $max;
1537    }
1538  }
1539  return sort { $a <=> $b } @res;
1540}
1541
1542# @_[0]: Reference to list 1
1543# @_[1]: Reference to list 2
1544# Result: 0 if they have no elements in common, 1 if they have
1545# Elements must be numeric.
1546sub any_list_match
1547{
1548  my ($list1,$list2) = @_;
1549  my ($el1,$el2);
1550  foreach $el1 (@$list1) {
1551    foreach $el2 (@$list2) {
1552      return 1 if $el1 == $el2;
1553    }
1554  }
1555  return 0;
1556}
1557
1558###################
1559# I/O port access #
1560###################
1561
1562sub initialize_ioports
1563{
1564  sysopen (IOPORTS, "/dev/port", O_RDWR)
1565    or die "/dev/port: $!\n";
1566  binmode IOPORTS;
1567}
1568
1569sub close_ioports
1570{
1571  close (IOPORTS)
1572    or print "Warning: $!\n";
1573}
1574
1575# $_[0]: port to read
1576# Returns: -1 on failure, read value on success.
1577sub inb
1578{
1579  my ($res,$nrchars);
1580  sysseek IOPORTS, $_[0], 0 or return -1;
1581  $nrchars = sysread IOPORTS, $res, 1;
1582  return -1 if not defined $nrchars or $nrchars != 1;
1583  $res = unpack "C",$res ;
1584  return $res;
1585}
1586
1587# $_[0]: port to write
1588# $_[1]: value to write
1589# Returns: -1 on failure, 0 on success.
1590sub outb
1591{
1592  if ($_[1] > 0xff)
1593  {
1594    my ($package, $filename, $line, $sub) = caller(1);
1595    print "\n*** Called outb with value=$_[1] from line $line\n",
1596          "*** (in $sub). PLEASE REPORT!\n",
1597          "*** Terminating.\n";
1598    exit(-1);
1599  }
1600  my $towrite = pack "C", $_[1];
1601  sysseek IOPORTS, $_[0], 0 or return -1;
1602  my $nrchars = syswrite IOPORTS, $towrite, 1;
1603  return -1 if not defined $nrchars or $nrchars != 1;
1604  return 0;
1605}
1606
1607# $_[0]: Address register
1608# $_[1]: Data register
1609# $_[2]: Register to read
1610# Returns: read value
1611sub isa_read_byte
1612{
1613  outb $_[0],$_[2];
1614  return inb $_[1];
1615}
1616
1617# $_[0]: Address register
1618# $_[1]: Data register
1619# $_[2]: Register to write
1620# $_[3}: Value to write
1621# Returns: nothing
1622sub isa_write_byte
1623{
1624  outb $_[0],$_[2];
1625  outb $_[1],$_[3];
1626}
1627
1628#################
1629# AUTODETECTION #
1630#################
1631
1632use vars qw($modules_conf $dev_i2c);
1633
1634sub initialize_conf
1635{
1636  if (-f '/etc/modules.conf') {
1637    $modules_conf = '/etc/modules.conf';
1638  } elsif (-f '/etc/conf.modules') {
1639    $modules_conf = '/etc/conf.modules';
1640  } else { # default
1641    $modules_conf = '/etc/modules.conf';
1642  }
1643
1644  if (-c '/dev/i2c-0') {
1645    $dev_i2c = '/dev/i2c-';
1646  } elsif (-d '/dev/i2c') { # devfs
1647    $dev_i2c = '/dev/i2c/';
1648  } elsif (-c '/dev/i2c0') {
1649    $dev_i2c = '/dev/i2c';
1650  } else { # default
1651    print "No i2c device files found. Use prog/mkdev/mkdev.sh to create them.\n";
1652    exit -1;
1653  }
1654}
1655
1656###########
1657# MODULES #
1658###########
1659
1660use vars qw(@modules_list);
1661
1662sub initialize_modules_list
1663{
1664  open INPUTFILE, "/proc/modules" or die "Can't access /proc/modules!";
1665  while (<INPUTFILE>) {
1666    push @modules_list, /^(\S*)/ ;
1667  }
1668  close INPUTFILE;
1669}
1670
1671##############
1672# PCI ACCESS #
1673##############
1674
1675use vars qw(@pci_list);
1676
1677# This function returns a list of hashes. Each hash has some PCI information
1678# (more than we will ever need, probably). The most important
1679# fields are 'bus', 'slot', 'func' (they uniquely identify a PCI device in
1680# a computer) and 'vendid','devid' (they uniquely identify a type of device).
1681# /proc/bus/pci/devices is only available on late 2.1 and 2.2 kernels.
1682sub read_proc_dev_pci
1683{
1684  my ($dfn,$vend,@pci_list);
1685  open INPUTFILE, "/proc/bus/pci/devices" or return;
1686  while (<INPUTFILE>) {
1687    my $record = {};
1688    ($dfn,$vend,$record->{irq},$record->{base_addr0},$record->{base_addr1},
1689          $record->{base_addr2},$record->{base_addr3},$record->{base_addr4},
1690          $record->{base_addr5},$record->{rom_base_addr}) = 
1691          map { oct "0x$_" } (split) [0..9];
1692    $record->{bus} = $dfn >> 8;
1693    $record->{slot} = ($dfn & 0xf8) >> 3;
1694    $record->{func} = $dfn & 0x07;
1695    $record->{vendid} = $vend >> 16;
1696    $record->{devid} = $vend & 0xffff;
1697  push @pci_list,$record;
1698  }
1699  close INPUTFILE or return;
1700  return @pci_list;
1701}
1702
1703# This function returns a list of hashes. Each hash has some PCI
1704# information. The important fields here are 'bus', 'slot', 'func' (they
1705# uniquely identify a PCI device in a computer) and 'desc' (a functional
1706# description of the PCI device). If this is an 'unknown device', the
1707# vendid and devid fields are set instead.
1708sub read_proc_pci
1709{
1710  my @pci_list;
1711  open INPUTFILE, "/proc/pci" or return;
1712  while (<INPUTFILE>) {
1713    my $record = {};
1714    if (($record->{bus},$record->{slot},$record->{func}) = 
1715        /^\s*Bus\s*(\S)+\s*,\s*device\s*(\S+)\s*,\s*function\s*(\S+)\s*:\s*$/) {
1716      my $desc = <INPUTFILE>;
1717      $_ = <INPUTFILE>;
1718      if (($desc =~ /Unknown device/) and
1719              (($record->{vendid},$record->{devid}) = 
1720                         /^\s*Vendor id=(\S+)\.\s*Device id=(\S+)\.$/)) {
1721        $record->{vendid} = hex $record->{vendid};
1722        $record->{devid} = hex $record->{devid};
1723      } else {
1724        $record->{desc} = $desc;
1725      }
1726      push @pci_list,$record;
1727    }
1728  }
1729  close INPUTFILE or return;
1730  return @pci_list;
1731}
1732
1733sub initialize_proc_pci
1734{
1735  @pci_list = read_proc_dev_pci;
1736  @pci_list = read_proc_pci     if not defined @pci_list;
1737  die "Can't access either /proc/bus/pci/ or /proc/pci!" 
1738                                    if not defined @pci_list;
1739}
1740
1741#####################
1742# ADAPTER DETECTION #
1743#####################
1744
1745sub all_available_adapters
1746{
1747  my @res = ();
1748  my ($module,$adapter);
1749  MODULES:
1750  foreach $module (@modules_list) {
1751    foreach $adapter (@pci_adapters) {
1752      if (exists $adapter->{driver} and $module eq $adapter->{driver}) {
1753        push @res, $module;
1754        next MODULES;
1755      }
1756    }
1757  }
1758  return @res;
1759}
1760
1761sub adapter_pci_detection
1762{
1763  my ($device,$try,@res);
1764  print "Probing for PCI bus adapters...\n";
1765
1766  foreach $device (@pci_list) {
1767    foreach $try (@pci_adapters) {
1768      if ((defined($device->{vendid}) and 
1769           $try->{vendid} == $device->{vendid} and
1770           $try->{devid} == $device->{devid} and
1771           $try->{func} == $device->{func}) or
1772          (! defined($device->{vendid}) and
1773           $device->{desc} =~ /$try->{procid}/ and
1774           $try->{func} == $device->{func})) {
1775        printf "Use driver `%s' for device %02x:%02x.%x: %s\n",
1776               $try->{driver}?$try->{driver}:"<To Be Written>",
1777               $device->{bus},$device->{slot},$device->{func},$try->{procid};
1778        push @res,$try->{driver};
1779      }
1780    }
1781  }
1782  if (! @res) {
1783    print ("Sorry, no PCI bus adapters found.\n");
1784  } else {
1785    printf ("Probe succesfully concluded.\n");
1786  }
1787  return @res;
1788}
1789
1790# $_[0]: Adapter description as found in /proc/bus/i2c
1791# $_[1]: Algorithm description as found in /proc/bus/i2c
1792sub find_adapter_driver
1793{
1794  my $adapter;
1795  for $adapter (@pci_adapters) {
1796    return $adapter->{driver} if &{$adapter->{match}} ($_[0],$_[1]);
1797  }
1798  return "UNKNOWN";
1799}
1800
1801#############################
1802# I2C AND SMBUS /DEV ACCESS #
1803#############################
1804
1805# This should really go into a separate module/package.
1806
1807# To do: support i2c-level access (through sysread/syswrite, probably).
1808# I can't test this at all (PIIX4 does not support this), so I have not
1809# included it.
1810
1811use vars qw($IOCTL_I2C_RETRIES $IOCTL_I2C_TIMEOUT $IOCTL_I2C_UDELAY
1812            $IOCTL_I2C_MDELAY $IOCTL_I2C_SLAVE $IOCTL_I2C_TENBIT
1813            $IOCTL_I2C_SMBUS);
1814
1815# These are copied from <linux/i2c.h> and <linux/smbus.h>
1816
1817# For bit-adapters:
1818$IOCTL_I2C_RETRIES = 0x0701;
1819$IOCTL_I2C_TIMEOUT = 0x0702;
1820$IOCTL_I2C_UDELAY = 0x0705;
1821$IOCTL_I2C_MDELAY = 0x0706;
1822
1823# General ones:
1824$IOCTL_I2C_SLAVE = 0x0703;
1825$IOCTL_I2C_TENBIT = 0x0704;
1826$IOCTL_I2C_SMBUS = 0x0720;
1827
1828
1829
1830use vars qw($SMBUS_READ $SMBUS_WRITE $SMBUS_QUICK $SMBUS_BYTE $SMBUS_BYTE_DATA
1831            $SMBUS_WORD_DATA $SMBUS_PROC_CALL $SMBUS_BLOCK_DATA);
1832
1833# These are copied from <linux/smbus.h>
1834
1835$SMBUS_READ = 1;
1836$SMBUS_WRITE = 0;
1837$SMBUS_QUICK = 0;
1838$SMBUS_BYTE = 1;
1839$SMBUS_BYTE_DATA  = 2;
1840$SMBUS_WORD_DATA  = 3;
1841$SMBUS_PROC_CALL = 4;
1842$SMBUS_BLOCK_DATA = 5;
1843
1844# Select the device to communicate with through its address.
1845# $_[0]: Reference to an opened filehandle
1846# $_[1]: Address to select
1847# Returns: 0 on failure, 1 on success.
1848sub i2c_set_slave_addr
1849{
1850  my ($file,$addr) = @_;
1851  ioctl $file, $IOCTL_I2C_SLAVE, $addr or return 0;
1852  return 1;
1853}
1854
1855# i2c_smbus_access is based upon the corresponding C function (see
1856# <linux/i2c-dev.h>). You should not need to call this directly.
1857# Exact calling conventions are intricate; read i2c-dev.c if you really need
1858# to know.
1859# $_[0]: Reference to an opened filehandle
1860# $_[1]: $SMBUS_READ for reading, $SMBUS_WRITE for writing
1861# $_[2]: Command (usually register number)
1862# $_[3]: Transaction kind ($SMBUS_BYTE, $SMBUS_BYTE_DATA, etc.)
1863# $_[4]: Reference to an array used for input/output of data
1864# Returns: 0 on failure, 1 on success.
1865# Note that we need to get back to Integer boundaries through the 'x2'
1866# in the pack. This is very compiler-dependent; I wish there was some other
1867# way to do this.
1868sub i2c_smbus_access
1869{
1870  my ($file,$read_write,$command,$size,$data) = @_;
1871  my $data_array = pack "C32", @$data;
1872  my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
1873  ioctl $file, $IOCTL_I2C_SMBUS, $ioctl_data or return 0;
1874  $_[4] = [ unpack "C32",$data_array ];
1875  return 1;
1876}
1877
1878# $_[0]: Reference to an opened filehandle
1879# $_[1]: Either 0 or 1
1880# Returns: -1 on failure, the 0 on success.
1881sub i2c_smbus_write_quick
1882{
1883  my ($file,$value) = @_;
1884  my $data = [];
1885  i2c_smbus_access $file, $value, 0, $SMBUS_QUICK, $data 
1886         or return -1;
1887  return 0;
1888}
1889
1890# $_[0]: Reference to an opened filehandle
1891# Returns: -1 on failure, the read byte on success.
1892sub i2c_smbus_read_byte
1893{
1894  my ($file) = @_;
1895  my $data = [];
1896  i2c_smbus_access $file, $SMBUS_READ, 0, $SMBUS_BYTE, $data 
1897         or return -1;
1898  return $$data[0];
1899}
1900
1901# $_[0]: Reference to an opened filehandle
1902# $_[1]: Byte to write
1903# Returns: -1 on failure, 0 on success.
1904sub i2c_smbus_write_byte
1905{
1906  my ($file,$command) = @_;
1907  my $data = [$command];
1908  i2c_smbus_access $file, $SMBUS_WRITE, 0, $SMBUS_BYTE, $data 
1909         or return -1;
1910  return 0;
1911}
1912
1913# $_[0]: Reference to an opened filehandle
1914# $_[1]: Command byte (usually register number)
1915# Returns: -1 on failure, the read byte on success.
1916sub i2c_smbus_read_byte_data
1917{
1918  my ($file,$command) = @_;
1919  my $data = [];
1920  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BYTE_DATA, $data 
1921         or return -1;
1922  return $$data[0];
1923}
1924 
1925# $_[0]: Reference to an opened filehandle
1926# $_[1]: Command byte (usually register number)
1927# $_[2]: Byte to write
1928# Returns: -1 on failure, 0 on success.
1929sub i2c_smbus_write_byte_data
1930{
1931  my ($file,$command,$value) = @_;
1932  my $data = [$value];
1933  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BYTE_DATA, $data 
1934         or return -1;
1935  return 0;
1936}
1937
1938# $_[0]: Reference to an opened filehandle
1939# $_[1]: Command byte (usually register number)
1940# Returns: -1 on failure, the read word on success.
1941# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1942# this.
1943sub i2c_smbus_read_word_data
1944{
1945  my ($file,$command) = @_;
1946  my $data = [];
1947  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_WORD_DATA, $data 
1948         or return -1;
1949  return $$data[0] + 256 * $$data[1];
1950}
1951
1952# $_[0]: Reference to an opened filehandle
1953# $_[1]: Command byte (usually register number)
1954# $_[2]: Byte to write
1955# Returns: -1 on failure, 0 on success.
1956# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1957# this.
1958sub i2c_smbus_write_word_data
1959{
1960  my ($file,$command,$value) = @_;
1961  my $data = [$value & 0xff, $value >> 8];
1962  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_WORD_DATA, $data 
1963         or return -1;
1964  return 0;
1965}
1966
1967# $_[0]: Reference to an opened filehandle
1968# $_[1]: Command byte (usually register number)
1969# $_[2]: Word to write
1970# Returns: -1 on failure, read word on success.
1971# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1972# this.
1973sub i2c_smbus_process_call
1974{
1975  my ($file,$command,$value) = @_;
1976  my $data = [$value & 0xff, $value >> 8];
1977  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_PROC_CALL, $data 
1978         or return -1;
1979  return $$data[0] + 256 * $$data[1];
1980}
1981
1982# $_[0]: Reference to an opened filehandle
1983# $_[1]: Command byte (usually register number)
1984# Returns: Undefined on failure, a list of read bytes on success
1985# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1986# this.
1987sub i2c_smbus_read_block_data
1988{
1989  my ($file,$command) = @_;
1990  my $data = [];
1991  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BLOCK_DATA, $data 
1992         or return;
1993  shift @$data;
1994  return @$data;
1995}
1996
1997# $_[0]: Reference to an opened filehandle
1998# $_[1]: Command byte (usually register number)
1999# @_[2..]: List of values to write
2000# Returns: -1 on failure, 0 on success.
2001# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2002# this.
2003sub i2c_smbus_write_block_data
2004{
2005  my ($file,$command,@data) = @_;
2006  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BLOCK_DATA, \@data 
2007         or return;
2008  return 0;
2009}
2010
2011####################
2012# ADAPTER SCANNING #
2013####################
2014
2015use vars qw(@chips_detected);
2016
2017# We will build a complicated structure @chips_detected here, being:
2018# A list of
2019#  references to hashes
2020#    with field 'driver', being a string with the driver name for this chip;
2021#    with field 'detected'
2022#      being a reference to a list of
2023#        references to hashes of type 'detect_data';
2024#    with field 'misdetected'
2025#      being a reference to a list of
2026#        references to hashes of type 'detect_data'
2027
2028# Type detect_data:
2029# A hash
2030#   with field 'i2c_adap' containing an adapter string as appearing
2031#        in /proc/bus/i2c (if this is an I2C detection)
2032#  with field 'i2c_algo' containing an algorithm string as appearing
2033#       in /proc/bus/i2c (if this is an I2C detection)
2034#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
2035#       adapter (if this is an I2C detection)
2036#  with field 'i2c_driver', containing the driver name for this adapter
2037#       (if this is an I2C detection)
2038#  with field 'i2c_addr', containing the I2C address of the detection;
2039#       (if this is an I2C detection)
2040#  with field 'i2c_sub_addrs', containing a reference to a list of
2041#       other I2C addresses (if this is an I2C detection)
2042#  with field 'i2c_extra' if this is an I2C detection and the address
2043#       is not normally probed by the kernel driver
2044#  with field 'isa_addr' containing the ISA address this chip is on
2045#       (if this is an ISA detection)
2046#  with field 'isa_extra' if this is an ISA detection and the address
2047#       is not normally probed by the kernel driver
2048#  with field 'conf', containing the confidence level of this detection
2049#  with field 'chipname', containing the chip name
2050
2051# This adds a detection to the above structure. We do no alias detection
2052# here; so you should do ISA detections *after* all I2C detections.
2053# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
2054# In all normal cases, it should be all right.
2055# $_[0]: chip driver
2056# $_[1]: reference to data hash
2057# Returns: Nothing
2058sub add_i2c_to_chips_detected
2059{
2060  my ($chipdriver,$datahash) = @_;
2061  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2062      $main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs,
2063      $do_not_add);
2064
2065  # First determine where the hash has to be added.
2066  for ($i = 0; $i < @chips_detected; $i++) {
2067    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2068  }
2069  if ($i == @chips_detected) {
2070    push @chips_detected, { driver => $chipdriver,
2071                            detected => [],
2072                            misdetected => [] };
2073  }
2074  $new_detected_ref = $chips_detected[$i]->{detected};
2075  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2076
2077  # Find out whether our new entry should go into the detected or the
2078  # misdetected list. We compare all i2c addresses; if at least one matches,
2079  # but our conf value is lower, we assume this is a misdetect.
2080  @hash_addrs = ($datahash->{i2c_addr});
2081  push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
2082       if exists $datahash->{i2c_sub_addrs};
2083  $put_in_detected = 1;
2084  $do_not_add = 0;
2085  FIND_LOOP:
2086  foreach $main_entry (@chips_detected) {
2087    foreach $detected_entry (@{$main_entry->{detected}}) {
2088      @entry_addrs = ($detected_entry->{i2c_addr});
2089      push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
2090               if exists $detected_entry->{i2c_sub_addrs};
2091      if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
2092          any_list_match \@entry_addrs, \@hash_addrs) {
2093        if ($detected_entry->{conf} >= $datahash->{conf}) {
2094          $put_in_detected = 0;
2095        }
2096        if ($chipdriver eq $main_entry->{driver}) {
2097          $do_not_add = 1;
2098        }
2099        last FIND_LOOP;
2100      }
2101    }
2102  }
2103
2104  if ($put_in_detected) {
2105    # Here, we move all entries from detected to misdetected which
2106    # match at least in one main or sub address. This may not be the
2107    # best idea to do, as it may remove detections without replacing
2108    # them with second-best ones. Too bad.
2109    # (Khali 2003-09-13) If the driver is the same, the "misdetected"
2110    # entry is simply deleted; failing to do so cause the configuration
2111    # lines generated later to look very confusing (the driver will
2112    # be told to ignore valid addresses).
2113    @hash_addrs = ($datahash->{i2c_addr});
2114    push @hash_addrs, @{$datahash->{i2c_sub_addrs}} 
2115         if exists $datahash->{i2c_sub_addrs};
2116    foreach $main_entry (@chips_detected) {
2117      $detected_ref = $main_entry->{detected};
2118      $misdetected_ref = $main_entry->{misdetected};
2119      for ($i = @$detected_ref-1; $i >=0; $i--) {
2120        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
2121        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
2122             if exists $detected_ref->[$i]->{i2c_sub_addrs};
2123        if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} and
2124            any_list_match \@entry_addrs, \@hash_addrs) {
2125          push @$misdetected_ref,$detected_ref->[$i]
2126            unless $chipdriver eq $main_entry->{driver};
2127          splice @$detected_ref, $i, 1;
2128        }
2129      }
2130    }
2131
2132    # Now add the new entry to detected
2133    push @$new_detected_ref, $datahash;
2134  } else {
2135    # No hard work here
2136    push @$new_misdetected_ref, $datahash
2137      unless $do_not_add;
2138  }
2139}
2140
2141# This adds a detection to the above structure. We also do alias detection
2142# here; so you should do ISA detections *after* all I2C detections.
2143# $_[0]: alias detection function
2144# $_[1]: chip driver
2145# $_[2]: reference to data hash
2146# Returns: 0 if it is not an alias, datahash reference if it is.
2147sub add_isa_to_chips_detected
2148{
2149  my ($alias_detect,$chipdriver,$datahash) = @_;
2150  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2151      $main_entry,$isalias);
2152
2153  # First determine where the hash has to be added.
2154  $isalias=0;
2155  for ($i = 0; $i < @chips_detected; $i++) {
2156    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2157  }
2158  if ($i == @chips_detected) {
2159    push @chips_detected, { driver => $chipdriver,
2160                            detected => [],
2161                            misdetected => [] };
2162  }
2163  $new_detected_ref = $chips_detected[$i]->{detected};
2164  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2165
2166  # Now, we are looking for aliases. An alias can only be the same chiptype.
2167  # If an alias is found in the misdetected list, we add the new information
2168  # and terminate this function. If it is found in the detected list, we
2169  # still have to check whether another chip has claimed this ISA address.
2170  # So we remove the old entry from the detected list and put it in datahash.
2171
2172  # Misdetected alias detection:
2173  for ($i = 0; $i < @$new_misdetected_ref; $i++) {
2174    if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
2175        not exists $new_misdetected_ref->[$i]->{isa_addr} and
2176        defined $alias_detect and
2177        $new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2178      open FILE,"$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}" or
2179        print("Can't open $dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2180        next;
2181      binmode FILE;
2182      i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{i2c_addr} or
2183           print("Can't set I2C address for ",
2184                 "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2185           next;
2186      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2187                          $new_misdetected_ref->[$i]->{i2c_addr})) {
2188        $new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2189        $new_misdetected_ref->[$i]->{isa_extra} = $datahash->{isa_extra} 
2190               if exists $datahash->{isa_extra};
2191        close FILE;
2192        return $new_misdetected_ref->[$i]; 
2193      }
2194      close FILE;
2195    }
2196  }
2197
2198  # Detected alias detection:
2199  for ($i = 0; $i < @$new_detected_ref; $i++) {
2200    if (exists $new_detected_ref->[$i]->{i2c_addr} and
2201        not exists $new_detected_ref->[$i]->{isa_addr} and
2202        defined $alias_detect and
2203        $new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2204      open FILE,"$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}" or
2205        print("Can't open $dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2206        next;
2207      binmode FILE;
2208      i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{i2c_addr} or
2209           print("Can't set I2C address for ",
2210                 "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2211           next;
2212      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2213                          $new_detected_ref->[$i]->{i2c_addr})) {
2214        $new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2215        $new_detected_ref->[$i]->{isa_extra} = $datahash->{isa_extra} 
2216               if exists $datahash->{isa_extra};
2217        ($datahash) = splice (@$new_detected_ref, $i, 1);
2218        close FILE;
2219        $isalias=1;
2220        last;
2221      }
2222      close FILE;
2223    }
2224  }
2225
2226
2227  # Find out whether our new entry should go into the detected or the
2228  # misdetected list. We only compare main isa_addr here, of course.
2229  foreach $main_entry (@chips_detected) {
2230    $detected_ref = $main_entry->{detected};
2231    $misdetected_ref = $main_entry->{misdetected};
2232    for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
2233      if (exists $detected_ref->[$i]->{isa_addr} and
2234          $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
2235        if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
2236          push @$new_misdetected_ref, $datahash;
2237        } else {
2238          push @$misdetected_ref,$detected_ref->[$i];
2239          splice @$detected_ref, $i,1;
2240          push @$new_detected_ref, $datahash;
2241        }
2242        if ($isalias) {
2243          return $datahash;
2244        } else {
2245          return 0;
2246        }
2247      }
2248    }
2249  }
2250
2251  # Not found? OK, put it in the detected list
2252  push @$new_detected_ref, $datahash;
2253  if ($isalias) {
2254    return $datahash;
2255  } else {
2256    return 0;
2257  }
2258}
2259
2260# $_[0]: The number of the adapter to scan
2261# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
2262# $_[2]: The name of the algorithm, as appearing in /proc/bus/i2c
2263# $_[3]: The driver of the adapter
2264# @_[4..]: Addresses not to scan
2265sub scan_adapter
2266{
2267  my ( $adapter_nr,$adapter_name,$algorithm_name,$adapter_driver, 
2268       $not_to_scan) = @_;
2269  my ($chip, $addr, $conf,@chips,$new_hash,$other_addr);
2270
2271  # As we modify it, we need a copy
2272  my @not_to_scan = @$not_to_scan;
2273
2274  open FILE,"$dev_i2c$adapter_nr" or 
2275    (print "Can't open $dev_i2c$adapter_nr\n"), return;
2276  binmode FILE;
2277
2278  # Now scan each address in turn
2279  foreach $addr (0..0x7f) {
2280    # As the not_to_scan list is sorted, we can check it fast
2281    if (@not_to_scan and $not_to_scan[0] == $addr) {
2282      shift @not_to_scan;
2283      next;
2284    }
2285
2286    i2c_set_slave_addr(\*FILE,$addr) or 
2287        printf("Client at address 0x%02x can not be probed - unload all client drivers first!\n",$addr), next;
2288
2289    next unless i2c_smbus_write_quick(\*FILE,$SMBUS_WRITE) >= 0;
2290    printf "Client found at address 0x%02x\n",$addr;
2291    # Prevent 24RF08 corruption
2292    if($addr >= 0x54 and $addr <= 0x57) {
2293        i2c_smbus_write_quick(\*FILE,$SMBUS_WRITE);
2294    }
2295
2296    foreach $chip (@chip_ids) {
2297      if (exists $$chip{i2c_addrs} and contains $addr, @{$$chip{i2c_addrs}}) {
2298        print "Probing for `$$chip{name}'... ";
2299        if (($conf,@chips) = &{$$chip{i2c_detect}} (\*FILE ,$addr)) {
2300          print "Success!\n",
2301                "    (confidence $conf, driver `$$chip{driver}')";
2302          if (@chips) {
2303            print ", other addresses:";
2304            @chips = sort @chips;
2305            foreach $other_addr (sort @chips) {
2306              printf(" 0x%02x",$other_addr);
2307            }
2308          }
2309          printf "\n";
2310          $new_hash = { conf => $conf,
2311                        i2c_addr => $addr,
2312                        chipname =>  $$chip{name},
2313                        i2c_adap => $adapter_name,
2314                        i2c_algo => $algorithm_name,
2315                        i2c_driver => $adapter_driver,
2316                        i2c_devnr => $adapter_nr,
2317                      };
2318          if (@chips) {
2319            my @chips_copy = @chips;
2320            $new_hash->{i2c_sub_addrs} = \@chips_copy;
2321          }
2322          $new_hash->{i2c_extra} = 0 
2323                 if exists $chip->{i2c_driver_addrs} and
2324                    not contains( $addr , @{$chip->{i2c_driver_addrs}});
2325          add_i2c_to_chips_detected $$chip{driver}, $new_hash;
2326        } else {
2327          print "Failed!\n";
2328        }
2329      }
2330    }
2331  }
2332}
2333
2334sub scan_isa_bus
2335{
2336  my ($chip,$addr,$conf);
2337  foreach $chip (@chip_ids) {
2338    next if not exists $$chip{isa_addrs} or not exists $$chip{isa_detect};
2339    print "Probing for `$$chip{name}'\n";
2340    foreach $addr (@{$$chip{isa_addrs}}) {
2341      if ($addr) {
2342        printf "  Trying address 0x%04x... ", $addr;
2343      } else {
2344        print "  Trying general detect... ";
2345      }
2346      $conf = &{$$chip{isa_detect}} ($addr);
2347      print("Failed!\n"), next if not defined $conf;
2348      print "Success!\n";
2349      printf "    (confidence %d, driver `%s')\n", $conf, $$chip{driver};
2350      my $new_hash = { conf => $conf,
2351                       isa_addr => $addr,
2352                       chipname =>  $$chip{name}
2353                     };
2354      $new_hash->{isa_extra} = 0 
2355             if exists $chip->{isa_driver_addrs} and
2356                not contains ($addr, @{$chip->{isa_driver_addrs}});
2357      $new_hash = add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver},
2358                                            $new_hash;
2359      if ($new_hash) {
2360        printf "    Alias of the chip on I2C bus `%s', address 0x%04x\n",
2361                        $new_hash->{i2c_adap},$new_hash->{i2c_addr};
2362      }
2363    }
2364  }
2365}
2366
2367sub scan_superio
2368{
2369  my ($chip,$val,$addr,$conf);
2370  foreach $chip (@superio_ids) {
2371    print "Probing for `$$chip{name}'\n";
2372# write the password
2373    foreach $val (@{$$chip{enter}}) {
2374      outb($$chip{addrreg}, $val);
2375    }
2376# check the device ID
2377    outb($$chip{addrreg}, $$chip{devidreg});
2378    $val = inb($$chip{datareg});
2379    if($$chip{devid}>0xff) {
2380      outb($$chip{addrreg}, $$chip{devidreg} + 1);
2381      $val = ($val << 8) | inb($$chip{datareg});
2382    }
2383    if($val == $$chip{devid}) {
2384      print "  Success...";
2385# switch to the sensor logical device
2386      outb($$chip{addrreg}, $$chip{logdevreg});
2387      outb($$chip{datareg}, $$chip{logdev});
2388# check the activation register
2389      if(exists $$chip{actreg}) {
2390        outb($$chip{addrreg}, $$chip{actreg});
2391        $val = inb($$chip{datareg});
2392        if(!($val & $$chip{actmask})) {
2393          print " but not activated, module may not find\n";
2394          outb($$chip{exitreg}, $$chip{exit});
2395          next;
2396        }
2397      }
2398# Get the IO base register
2399      outb($$chip{addrreg}, $$chip{basereg});
2400      $addr = inb($$chip{datareg});
2401      outb($$chip{addrreg}, $$chip{basereg} + 1);
2402      $addr = ($addr << 8) | inb($$chip{datareg});
2403      if($addr == 0) {
2404        print " but not activated, module may not find\n";
2405        outb($$chip{addrreg}, $$chip{exit});
2406        next;
2407      }         
2408      printf " found at address 0x%04x\n", $addr;
2409      my $new_hash = { conf => 9,
2410                       isa_addr => $addr,
2411                       chipname =>  $$chip{name}
2412                     };
2413      add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver},
2414                                            $new_hash;
2415    } else {
2416      if($val == 0xff) {       
2417        print "  Failed!\n";
2418      } else {
2419        printf "  Failed! (0x%02x)\n", $val;
2420      }
2421    }
2422    while ($addr = shift(@{$$chip{exitseq}})) {
2423      outb($addr, shift(@{$$chip{exitseq}}));
2424    }
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.