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

Revision 1888, 119.8 KB (checked in by khali, 11 years ago)

Add support for LM82, LM86 and LM89.

Better detection for LM83 and LM90.

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