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

Revision 937, 79.5 KB (checked in by mds, 13 years ago)

(mds) add entry for Serverworks south bridge. 0x1166 / 0x0200.

Not completely sure this is the correct PCI ID though.
No driver yet (requires NDA).

  • 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, 1999  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;
31
32#########################
33# CONSTANT DECLARATIONS #
34#########################
35
36use vars qw(@pci_adapters @chip_ids @undetectable_adapters);
37
38@undetectable_adapters = ( "i2c-elektor","i2c-elv", "i2c-philips-par",
39                           "i2c-velleman" );
40
41# This is the list of SMBus or I2C adapters we recognize by their PCI
42# signature. This is an easy and fast way to determine which SMBus or I2C
43# adapters should be present.
44# Each entry must have a vindid (Vendor ID), devid (Device ID), func (PCI
45# Function) and procid (string as appears in /proc/pci; see linux/driver/pci,
46# either pci.c or oldproc.c). If no driver is written yet, omit the
47# driver (Driver Name) field. The match (Match Description) field should
48# contain a function which returns zero if its two parameter matches
49# the text as it would appear in /proc/bus/i2c.
50@pci_adapters = ( 
51     { 
52       vendid => 0x8086,
53       devid  => 0x7113,
54       func => 3,
55       procid => "Intel 82371AB PIIX4 ACPI",
56       driver => "i2c-piix4",
57       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at [0-9,a-f]{4}/ },
58     } , 
59     { 
60       vendid => 0x8086,
61       devid  => 0x2413,
62       func => 3,
63       procid => "Intel 82801AA ICH",
64       driver => "i2c-i801",
65       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
66     } , 
67     { 
68       vendid => 0x8086,
69       devid  => 0x2423,
70       func => 3,
71       procid => "Intel 82801AB ICH0",
72       driver => "i2c-i801",
73       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
74     } , 
75     { 
76       vendid => 0x8086,
77       devid  => 0x2443,
78       func => 3,
79       procid => "Intel 82801BA ICH2",
80       driver => "i2c-i801",
81       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
82     } , 
83     { 
84       vendid => 0x1106,
85       devid  => 0x3040,
86       func => 3,
87       procid => "VIA Technologies VT 82C586B Apollo ACPI",
88       driver => "i2c-via",
89       match => sub { $_[0] =~ /^VIA i2c/ },
90     } ,
91     { 
92       vendid => 0x1106,
93       devid  => 0x3050,
94       func => 3,
95       procid => "VIA Technologies VT 82C596 Apollo ACPI",
96       driver => "i2c-viapro",
97       match => sub { $_[0] =~ /^SMBus vt82c596 adapter at [0-9,a-f]{4}/ },
98     } ,
99     { 
100       vendid => 0x1106,
101       devid  => 0x3051,
102       func => 3,
103       procid => "VIA Technologies VT 82C596B ACPI",
104       driver => "i2c-viapro",
105       match => sub { $_[0] =~ /^SMBus vt82c596 adapter at [0-9,a-f]{4}/ },
106     } ,
107     { 
108       vendid => 0x1106,
109       devid  => 0x3057,
110       func => 4,
111       procid => "VIA Technologies VT 82C686 Apollo ACPI",
112       driver => "i2c-viapro",
113       match => sub { $_[0] =~ /^SMBus vt82c596 adapter at [0-9,a-f]{4}/ },
114     } ,
115     {
116       vendid => 0x1039,
117       devid  => 0x0008,
118       func => 0,
119       procid => "Silicon Integrated Systems SIS5595",
120       driver => "i2c-sis5595",
121       match => sub {  $_[0] =~ /^SMBus SIS5595 adapter at [0-9,a-f]{4}/ },
122     } ,
123     {
124       vendid => 0x10b9,
125       devid => 0x7101,
126       funcid => 0,
127       procid => "Acer Labs M7101",
128       driver => "i2c-ali15x3",
129       match => sub { $_[0] =~ /^SMBus ALI15X3 adapter at [0-9,a-f]{4}/ },
130     },
131     { 
132       vendid => 0x106b,
133       devid  => 0x000e,
134       func => 0,
135       procid => "Apple Computer Inc. Hydra Mac I/O",
136       driver => "i2c-hydra",
137       match => sub { $_[0] =~ /^Hydra i2c/ },
138     },
139     { 
140       vendid => 0x1022,
141       devid  => 0x740b,
142       func => 3,
143       procid => "AMD-756 Athlon ACPI",
144       driver => "i2c-amd756",
145       match => sub { $_[0] =~ /^SMBus AMD756 adapter at [0-9,a-f]{4}/ },
146     },
147     {
148       vendid => 0x102b,
149       devid  => 0x0519,
150       func   => 0,
151       procid => "MGA 2064W [Millennium]",
152       driver => "i2c-matroxfb",
153       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
154     },
155     {
156       vendid => 0x102b,
157       devid  => 0x051a,
158       func   => 0,
159       procid => "MGA 1064SG [Mystique]",
160       driver => "i2c-matroxfb",
161       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
162     },
163     {
164       vendid => 0x102b,
165       devid  => 0x051b,
166       func   => 0,
167       procid => "MGA 2164W [Millennium II]",
168       driver => "i2c-matroxfb",
169       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
170     },
171     {
172       vendid => 0x102b,
173       devid  => 0x051e,
174       func   => 0,
175       procid => "MGA 1064SG [Mystique] AGP",
176       driver => "i2c-matroxfb",
177       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
178     },
179     {
180       vendid => 0x102b,
181       devid  => 0x051f,
182       func   => 0,
183       procid => "MGA 2164W [Millennium II] AGP",
184       driver => "i2c-matroxfb",
185       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
186     },
187     {
188       vendid => 0x102b,
189       devid  => 0x1000,
190       func   => 0,
191       procid => "MGA G100 [Productiva]",
192       driver => "i2c-matroxfb",
193       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
194     },
195     {
196       vendid => 0x102b,
197       devid  => 0x1001,
198       func   => 0,
199       procid => "MGA G100 [Productiva] AGP",
200       driver => "i2c-matroxfb",
201       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
202     },
203     {
204       vendid => 0x102b,
205       devid  => 0x0520,
206       func   => 0,
207       procid => "MGA G200",
208       driver => "i2c-matroxfb",
209       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
210     },
211     {
212       vendid => 0x102b,
213       devid  => 0x0521,
214       func   => 0,
215       procid => "MGA G200 AGP",
216       driver => "i2c-matroxfb",
217       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
218     },
219     {
220       vendid => 0x102b,
221       devid  => 0x0525,
222       func   => 0,
223       procid => "MGA G400 AGP",
224       driver => "i2c-matroxfb",
225       match  => sub { $_[0] =~ /^(DDC,MAVEN):fb[0-9]{1,2}/ },
226     },
227     {
228       vendid => 0x121a,
229       devid  => 0x0005,
230       func   => 0,
231       procid => "3Dfx Voodoo3",
232       driver => "i2c-voodoo3",
233       match  => sub { $_[0] =~ /Banshee adapter/ },
234     },
235     {
236       vendid => 0x121a,
237       devid  => 0x0003,
238       func   => 0,
239       procid => "3Dfx Voodoo Banshee",
240       driver => "i2c-voodoo3",
241       match  => sub { $_[0] =~ /Banshee adapter/ },
242     },
243     { 
244       vendid => 0x8086,
245       devid  => 0x7121,
246       func => 0,
247       procid => "Intel 82810 GMCH",
248       driver => "i2c-i810",
249       match => sub { $_[0] =~ /^I810/ },
250     } , 
251     { 
252       vendid => 0x8086,
253       devid  => 0x7123,
254       func => 0,
255       procid => "Intel 82810-DC100 GMCH",
256       driver => "i2c-i810",
257       match => sub { $_[0] =~ /^I810/ },
258     } , 
259     { 
260       vendid => 0x8086,
261       devid  => 0x1132,
262       func => 0,
263       procid => "Intel 82815 GMCH",
264       driver => "i2c-i810",
265       match => sub { $_[0] =~ /^I810/ },
266     } , 
267     { 
268       vendid => 0x12d2,
269       devid  => 0x0018,
270       func => 0,
271       procid => "RIVA 128",
272       driver => "i2c-riva",
273       match => sub { $_[0] =~ /^NVIDIA display/ },
274     } , 
275     { 
276       vendid => 0x10de,
277       devid  => 0x0020,
278       func => 0,
279       procid => "RIVA TNT",
280       driver => "i2c-riva",
281       match => sub { $_[0] =~ /^NVIDIA display/ },
282     } , 
283     { 
284       vendid => 0x10de,
285       devid  => 0x0028,
286       func => 0,
287       procid => "RIVA TNT2",
288       driver => "i2c-riva",
289       match => sub { $_[0] =~ /^NVIDIA display/ },
290     } , 
291     { 
292       vendid => 0x10de,
293       devid  => 0x0029,
294       func => 0,
295       procid => "RIVA UTNT2",
296       driver => "i2c-riva",
297       match => sub { $_[0] =~ /^NVIDIA display/ },
298     } , 
299     { 
300       vendid => 0x10de,
301       devid  => 0x002c,
302       func => 0,
303       procid => "RIVA VTNT2",
304       driver => "i2c-riva",
305       match => sub { $_[0] =~ /^NVIDIA display/ },
306     } , 
307     { 
308       vendid => 0x10de,
309       devid  => 0x002d,
310       func => 0,
311       procid => "RIVA UVTNT2",
312       driver => "i2c-riva",
313       match => sub { $_[0] =~ /^NVIDIA display/ },
314     } , 
315     { 
316       vendid => 0x10de,
317       devid  => 0x00a0,
318       func => 0,
319       procid => "RIVA ITNT2",
320       driver => "i2c-riva",
321       match => sub { $_[0] =~ /^NVIDIA display/ },
322     } , 
323     { 
324       vendid => 0x10de,
325       devid  => 0x0100,
326       func => 0,
327       procid => "GeForce 256",
328       driver => "i2c-riva",
329       match => sub { $_[0] =~ /^NVIDIA display/ },
330     } , 
331     { 
332       vendid => 0x10de,
333       devid  => 0x0101,
334       func => 0,
335       procid => "GeForce DDR",
336       driver => "i2c-riva",
337       match => sub { $_[0] =~ /^NVIDIA display/ },
338     } , 
339     { 
340       vendid => 0x10de,
341       devid  => 0x0102,
342       func => 0,
343       procid => "Quadro",
344       driver => "i2c-riva",
345       match => sub { $_[0] =~ /^NVIDIA display/ },
346     } , 
347     { 
348       vendid => 0x10de,
349       devid  => 0x0150,
350       func => 0,
351       procid => "GeForce GTS",
352       driver => "i2c-riva",
353       match => sub { $_[0] =~ /^NVIDIA display/ },
354     } , 
355     { 
356       vendid => 0x1166,
357       devid  => 0x0200,
358       func => 0,
359       procid => "ServerWorks South Bridge",
360       match => sub { $_[0] =~ /^ServerWorks tobewritten/ },
361     } , 
362);
363
364use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect
365            lm75_detect lm80_detect w83781d_detect w83781d_alias_detect
366            adm1025_detect w83781d_isa_detect gl518sm_detect gl520sm_detect
367            adm9240_detect adm1021_detect sis5595_isa_detect eeprom_detect
368            via686a_isa_detect adm1022_detect ltc1710_detect gl525sm_detect
369            lm87_detect ite_detect ite_isa_detect ite_alias_detect
370            ddcmonitor_detect ds1621_detect);
371
372# This is a list of all recognized chips.
373# Each entry must have the following fields:
374#  name: The full chip name
375#  driver: The driver name (without .o extension). Put in something like
376#      "Unwritten: <drivername>" if it is not yet available.
377#  i2c_addrs (optional): For I2C chips, the range of valid I2C addresses to
378#      probe. Recommend avoiding 0x69 because of clock chips.
379#  i2c_driver_addrs (optional): For I2C chips, the range of valid I2C
380#      addresses probed by the kernel driver. Strictly optional.
381#  i2c_detect (optional): For I2C chips, the function to call to detect
382#      this chip. The function should take two parameters: an open file
383#      descriptor to access the bus, and the I2C address to probe.
384#  isa_addrs (optional): For ISA chips, the range of valid port addresses to
385#      probe.
386#  isa_driver_addrs (optional): For ISA chips, the range of valid ISA
387#      addresses probed by the kernel driver. Strictly optional.
388#  isa_detect (optional): For ISA chips, the function to call to detect
389#      this chip. The function should take one parameter: the ISA address
390#      to probe.
391#  alias_detect (optional): For chips which can be both on the ISA and the
392#      I2C bus, a function which detectes whether two entries are the same.
393#      The function should take three parameters: The ISA address, the
394#      I2C bus number, and the I2C address.
395@chip_ids = (
396     {
397       name => "Myson MTP008",
398       driver => "mtp008",
399       i2c_addrs => [0x2c..0x2e], 
400       i2c_detect => sub { mtp008_detect @_},
401     } ,
402     {
403       name => "National Semiconductor LM78",
404       driver => "lm78",
405       i2c_addrs => [0x00..0x68,0x6a..0x7f], 
406       i2c_driver_addrs => [0x20..0x2f], 
407       i2c_detect => sub { lm78_detect 0, @_},
408       isa_addrs => [0x290],
409       isa_detect => sub { lm78_isa_detect 0, @_ },
410       alias_detect => sub { lm78_alias_detect 0, @_ },
411     } ,
412     {
413       name => "National Semiconductor LM78-J",
414       driver => "lm78",
415       i2c_addrs => [0x00..0x68,0x6a..0x7f], 
416       i2c_driver_addrs => [0x20..0x2f], 
417       i2c_detect => sub { lm78_detect 1, @_ },
418       isa_addrs => [0x290],
419       isa_detect => sub { lm78_isa_detect 1, @_ },
420       alias_detect => sub { lm78_alias_detect 1, @_ },
421     } ,
422     {
423       name => "National Semiconductor LM79",
424       driver => "lm78",
425       i2c_addrs => [0x00..0x68,0x6a..0x7f], 
426       i2c_driver_addrs => [0x20..0x2f], 
427       i2c_detect => sub { lm78_detect 2, @_ },
428       isa_addrs => [0x290],
429       isa_detect => sub { lm78_isa_detect 2, @_ },
430       alias_detect => sub { lm78_alias_detect 2, @_ },
431     } ,
432     {
433       name => "National Semiconductor LM75",
434       driver => "lm75",
435       i2c_addrs => [0x48..0x4f],
436       i2c_detect => sub { lm75_detect @_},
437     } ,
438     {
439       name => "National Semiconductor LM80",
440       driver => "lm80",
441       i2c_addrs => [0x28..0x2f],
442       i2c_detect => sub { lm80_detect @_} ,
443     },
444     {
445       name => "National Semiconductor LM87",
446       driver => "lm87",
447       i2c_addrs => [0x2c..0x2e],
448       i2c_detect => sub { lm87_detect @_} ,
449     },
450     {
451       name => "Winbond W83781D",
452       driver => "w83781d",
453       i2c_addrs => [0x00..0x68,0x6a..0x7f], 
454       i2c_detect => sub { w83781d_detect 0, @_},
455       i2c_driver_addrs => [0x20..0x2f], 
456       isa_addrs => [0x290],
457       isa_detect => sub { w83781d_isa_detect 0, @_ },
458       alias_detect => sub { w83781d_alias_detect 0, @_ },
459     } ,
460     {
461       name => "Winbond W83782D",
462       driver => "w83781d",
463       i2c_addrs => [0x00..0x68,0x6a..0x7f], 
464       i2c_driver_addrs => [0x20..0x2f], 
465       i2c_detect => sub { w83781d_detect 1, @_},
466       isa_addrs => [0x290],
467       isa_detect => sub { w83781d_isa_detect 1, @_ },
468       alias_detect => sub { w83781d_alias_detect 1, @_ },
469     } ,
470     {
471       name => "Winbond W83783S",
472       driver => "w83781d",
473       i2c_addrs => [0x00..0x68,0x6a..0x7f], 
474       i2c_driver_addrs => [0x20..0x2f], 
475       i2c_detect => sub { w83781d_detect 2, @_},
476     } ,
477     {
478       name => "Winbond W83627HF",
479       driver => "w83781d",
480       i2c_addrs => [0x00..0x68,0x6a..0x7f], 
481       i2c_driver_addrs => [0x20..0x2f], 
482       i2c_detect => sub { w83781d_detect 3, @_},
483       isa_addrs => [0x290],
484       isa_detect => sub { w83781d_isa_detect 3, @_ },
485       alias_detect => sub { w83781d_alias_detect 3, @_ },
486     } ,
487     {
488       name => "Asus AS99127F",
489       driver => "w83781d",
490       i2c_addrs => [0x00..0x68,0x6a..0x7f], 
491       i2c_driver_addrs => [0x20..0x2f], 
492       i2c_detect => sub { w83781d_detect 4, @_},
493     } ,
494     {
495       name => "Winbond W83697HF",
496       driver => "Unwritten (W83697HF)",
497       isa_addrs => [0x290],
498       isa_detect => sub { w83781d_isa_detect 5, @_ },
499     } ,
500     {
501       name => "Genesys Logic GL518SM Revision 0x00",
502       driver => "gl518sm",
503       i2c_addrs => [0x2c, 0x2d],
504       i2c_detect => sub { gl518sm_detect 0, @_} ,
505     },
506     {
507       name => "Genesys Logic GL518SM Revision 0x80",
508       driver => "gl518sm",
509       i2c_addrs => [0x2c, 0x2d],
510       i2c_detect => sub { gl518sm_detect 1, @_} ,
511     },
512     {
513       name => "Genesys Logic GL520SM",
514       driver => "gl520sm",
515       i2c_addrs => [0x2c, 0x2d],
516       i2c_detect => sub { gl520sm_detect @_} ,
517     },
518     {
519       name => "Genesys Logic GL525SM",
520       driver => "Unwritten (GL525SM)",
521       i2c_addrs => [0x2d],
522       i2c_detect => sub { gl525sm_detect @_} ,
523     },
524     {
525       name => "Analog Devices ADM9240",
526       driver => "adm9240",
527       i2c_addrs => [0x2c..0x2f],
528       i2c_detect => sub { adm9240_detect 0, @_ }
529     },
530     {
531       name => "Dallas Semiconductor DS1621",
532       driver => "ds1621",
533       i2c_addrs => [0x48..0x4f],
534       i2c_detect => sub { ds1621_detect @_},
535     } ,
536     {
537       name => "Dallas Semiconductor DS1780",
538       driver => "adm9240",
539       i2c_addrs => [0x2c..0x2f],
540       i2c_detect => sub { adm9240_detect 1, @_ }
541     },
542     {
543       name => "National Semiconductor LM81",
544       driver => "adm9240",
545       i2c_addrs => [0x2c..0x2f],
546       i2c_detect => sub { adm9240_detect 2, @_ }
547     },
548     {
549       name => "Analog Devices ADM1025",
550       driver => "adm1025",
551       i2c_addrs => [0x2c..0x2e],
552       i2c_detect => sub { adm1025_detect 0, @_ }
553     },
554     {
555       name => "Analog Devices ADM1021",
556       driver => "adm1021",
557       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
558       i2c_detect => sub { adm1021_detect 0, @_ },
559     },
560     {
561       name => "Maxim MAX1617",
562       driver => "adm1021",
563       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
564       i2c_detect => sub { adm1021_detect 1, @_ },
565     },
566     {
567       name => "Maxim MAX1617A",
568       driver => "adm1021",
569       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
570       i2c_detect => sub { adm1021_detect 2, @_ },
571     },
572     {
573       name => "TI THMC10",
574       driver => "adm1021",
575       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
576       i2c_detect => sub { adm1021_detect 3, @_ },
577     },
578     {
579       name => "National Semiconductor LM84",
580       driver => "adm1021",
581       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
582       i2c_detect => sub { adm1021_detect 4, @_ },
583     },
584     {
585       name => "Genesys Logic GL523SM",
586       driver => "adm1021",
587       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
588       i2c_detect => sub { adm1021_detect 5, @_ },
589     },
590     {
591       name => "Analog Devices ADM1022",
592       driver => "thmc50",
593       i2c_addrs => [0x2c..0x2f],
594       i2c_detect => sub { adm1022_detect 0, @_ },
595     },
596     {
597       name => "Texas Instruments THMC50",
598       driver => "thmc50",
599       i2c_addrs => [0x2c..0x2f],
600       i2c_detect => sub { adm1022_detect 1, @_ },
601     },
602     {
603       name => "Silicon Integrated Systems SIS5595",
604       driver => "sis5595",
605       isa_addrs => [ 0 ],
606       isa_detect => sub { sis5595_isa_detect @_ },
607     },
608     {
609       name => "VIA Technologies VT 82C686 Integrated Sensors",
610       driver => "via686a",
611       isa_addrs => [ 0 ],
612       isa_detect => sub { via686a_isa_detect @_ },
613     },
614     {
615       name => "ITE IT8705F / IT8712F",
616       driver => "Unwritten (IT87xxF)",
617       i2c_addrs => [0x00..0x68,0x6a..0x7f], 
618       i2c_driver_addrs => [0x20..0x2f], 
619       i2c_detect => sub { ite_detect 0, @_},
620       isa_addrs => [0x290],
621       isa_detect => sub { ite_isa_detect 0, @_ },
622       alias_detect => sub { ite_alias_detect 0, @_ },
623     } ,
624     {
625       name => "Serial EEPROM (PC-100 DIMM)",
626       driver => "eeprom",
627       i2c_addrs => [0x50..0x57],
628       i2c_detect => sub { eeprom_detect @_ },
629     },
630     {
631       name => "LTC1710",
632       driver => "ltc1710",
633       i2c_addrs => [0x58..0x5a],
634       i2c_detect => sub { ltc1710_detect @_ },
635     },
636     {
637       name => "DDC monitor",
638       driver => "ddcmon",
639       i2c_addrs => [0x50],
640       i2c_detect => sub { ddcmonitor_detect @_ },
641     },
642);
643
644
645#######################
646# AUXILIARY FUNCTIONS #
647#######################
648
649sub swap_bytes
650{
651  return (($_[0] & 0xff00) >> 8) + (($_[0] & 0x00ff) << 8)
652}
653
654# $_[0] is the sought value
655# @_[1..] is the list to seek in
656# Returns: 0 on failure, 1 if found.
657sub contains
658{
659  my $sought = shift;
660  foreach (@_) {
661    return 1 if $sought eq $_;
662  }
663  return 0;
664}
665
666sub parse_not_to_scan
667{
668  my ($min,$max,$to_parse) = @_;
669  my @ranges = split /\s*,\s*/, $to_parse;
670  my @res = ();
671  my $range;
672  foreach $range (@ranges) {
673    my ($start,$end) = split /\s*-s*/, $range;
674    $start = oct $start if $start =~ /^0/;
675    if (defined $end) {
676      $end = oct $end if $end =~ /^0/;
677      $start = $min if $start < $min;
678      $end = $max if $end > $max;
679      push @res, ($start+0..$end+0);
680    } else {
681      push @res, $start+0 if $start >= $min and $start <= $max;
682    }
683  }
684  return sort { $a <=> $b } @res;
685}
686
687# @_[0]: Reference to list 1
688# @_[1]: Reference to list 2
689# Result: 0 if they have no elements in common, 1 if they have
690# Elements must be numeric.
691sub any_list_match
692{
693  my ($list1,$list2) = @_;
694  my ($el1,$el2);
695  foreach $el1 (@$list1) {
696    foreach $el2 (@$list2) {
697      return 1 if $el1 == $el2;
698    }
699  }
700  return 0;
701}
702
703###################
704# I/O port access #
705###################
706
707sub initialize_ioports
708{
709  sysopen IOPORTS, "/dev/port", 2;
710}
711
712# $_[0]: port to read
713# Returns: -1 on failure, read value on success.
714sub inb
715{
716  my ($res,$nrchars);
717  sysseek IOPORTS, $_[0], 0 or return -1;
718  $nrchars = sysread IOPORTS, $res, 1;
719  return -1 if not defined $nrchars or $nrchars != 1;
720  $res = unpack "C",$res ;
721  return $res;
722}
723
724# $_[0]: port to write
725# $_[1]: value to write
726# Returns: -1 on failure, 0 on success.
727sub outb
728{
729  my $towrite = pack "C", $_[1];
730  sysseek IOPORTS, $_[0], 0 or return -1;
731  my $nrchars = syswrite IOPORTS, $towrite, 1;
732  return -1 if not defined $nrchars or $nrchars != 1;
733  return 0;
734}
735
736# $_[0]: Address register
737# $_[1]: Data register
738# $_[2]: Register to read
739# Returns: read value
740sub isa_read_byte
741{
742  outb $_[0],$_[2];
743  return inb $_[1];
744}
745
746# $_[0]: Address register
747# $_[1]: Data register
748# $_[2]: Register to write
749# $_[3}: Value to write
750# Returns: nothing
751sub isa_write_byte
752{
753  outb $_[0],$_[2];
754  outb $_[1],$_[3];
755}
756
757###########
758# MODULES #
759###########
760
761use vars qw(@modules_list);
762
763sub initialize_modules_list
764{
765  open INPUTFILE, "/proc/modules" or die "Can't access /proc/modules!";
766  while (<INPUTFILE>) {
767    push @modules_list, /^(\S*)/ ;
768  }
769  close INPUTFILE;
770}
771
772##############
773# PCI ACCESS #
774##############
775
776use vars qw(@pci_list);
777
778# This function returns a list of hashes. Each hash has some PCI information
779# (more than we will ever need, probably). The most important
780# fields are 'bus', 'slot', 'func' (they uniquely identify a PCI device in
781# a computer) and 'vendid','devid' (they uniquely identify a type of device).
782# /proc/bus/pci/devices is only available on late 2.1 and 2.2 kernels.
783sub read_proc_dev_pci
784{
785  my ($dfn,$vend,@pci_list);
786  open INPUTFILE, "/proc/bus/pci/devices" or return;
787  while (<INPUTFILE>) {
788    my $record = {};
789    ($dfn,$vend,$record->{irq},$record->{base_addr0},$record->{base_addr1},
790          $record->{base_addr2},$record->{base_addr3},$record->{base_addr4},
791          $record->{base_addr5},$record->{rom_base_addr}) = 
792          map { oct "0x$_" } split;
793    $record->{bus} = $dfn >> 8;
794    $record->{slot} = ($dfn & 0xf8) >> 3;
795    $record->{func} = $dfn & 0x07;
796    $record->{vendid} = $vend >> 16;
797    $record->{devid} = $vend & 0xffff;
798  push @pci_list,$record;
799  }
800  close INPUTFILE or return;
801  return @pci_list;
802}
803
804# This function returns a list of hashes. Each hash has some PCI
805# information. The important fields here are 'bus', 'slot', 'func' (they
806# uniquely identify a PCI device in a computer) and 'desc' (a functional
807# description of the PCI device). If this is an 'unknown device', the
808# vendid and devid fields are set instead.
809sub read_proc_pci
810{
811  my @pci_list;
812  open INPUTFILE, "/proc/pci" or return;
813  while (<INPUTFILE>) {
814    my $record = {};
815    if (($record->{bus},$record->{slot},$record->{func}) = 
816        /^\s*Bus\s*(\S)+\s*,\s*device\s*(\S+)\s*,\s*function\s*(\S+)\s*:\s*$/) {
817      my $desc = <INPUTFILE>;
818      $_ = <INPUTFILE>;
819      if (($desc =~ /Unknown device/) and
820              (($record->{vendid},$record->{devid}) = 
821                         /^\s*Vendor id=(\S+)\.\s*Device id=(\S+)\.$/)) {
822        $record->{vendid} = hex $record->{vendid};
823        $record->{devid} = hex $record->{devid};
824      } else {
825        $record->{desc} = $desc;
826      }
827      push @pci_list,$record;
828    }
829  }
830  close INPUTFILE or return;
831  return @pci_list;
832}
833
834sub initialize_proc_pci
835{
836  @pci_list = read_proc_dev_pci;
837  @pci_list = read_proc_pci     if not defined @pci_list;
838  die "Can't access either /proc/bus/pci/ or /proc/pci!" 
839                                    if not defined @pci_list;
840}
841
842#####################
843# ADAPTER DETECTION #
844#####################
845
846sub all_available_adapters
847{
848  my @res = ();
849  my ($module,$adapter);
850  MODULES:
851  foreach $module (@modules_list) {
852    foreach $adapter (@pci_adapters) {
853      if (exists $adapter->{driver} and $module eq $adapter->{driver}) {
854        push @res, $module;
855        next MODULES;
856      }
857    }
858  }
859  return @res;
860}
861
862sub adapter_pci_detection
863{
864  my ($device,$try,@res);
865  print "Probing for PCI bus adapters...\n";
866
867  foreach $device (@pci_list) {
868    foreach $try (@pci_adapters) {
869      if ((defined($device->{vendid}) and 
870           $try->{vendid} == $device->{vendid} and
871           $try->{devid} == $device->{devid} and
872           $try->{func} == $device->{func}) or
873          (! defined($device->{vendid}) and
874           $device->{desc} =~ /$try->{procid}/ and
875           $try->{func} == $device->{func})) {
876        printf "Use driver `%s' for device %02x:%02x.%x: %s\n",
877               $try->{driver}?$try->{driver}:"<To Be Written>",
878               $device->{bus},$device->{slot},$device->{func},$try->{procid};
879        push @res,$try->{driver};
880      }
881    }
882  }
883  if (! @res) {
884    print ("Sorry, no PCI bus adapters found.\n");
885  } else {
886    printf ("Probe succesfully concluded.\n");
887  }
888  return @res;
889}
890
891# $_[0]: Adapter description as found in /proc/bus/i2c
892# $_[1]: Algorithm description as found in /proc/bus/i2c
893sub find_adapter_driver
894{
895  my $adapter;
896  for $adapter (@pci_adapters) {
897    return $adapter->{driver} if &{$adapter->{match}} ($_[0],$_[1]);
898  }
899  return "UNKNOWN";
900}
901
902#############################
903# I2C AND SMBUS /DEV ACCESS #
904#############################
905
906# This should really go into a separate module/package.
907
908# To do: support i2c-level access (through sysread/syswrite, probably).
909# I can't test this at all (PIIX4 does not support this), so I have not
910# included it.
911
912use vars qw($IOCTL_I2C_RETRIES $IOCTL_I2C_TIMEOUT $IOCTL_I2C_UDELAY
913            $IOCTL_I2C_MDELAY $IOCTL_I2C_SLAVE $IOCTL_I2C_TENBIT
914            $IOCTL_I2C_SMBUS);
915
916# These are copied from <linux/i2c.h> and <linux/smbus.h>
917
918# For bit-adapters:
919$IOCTL_I2C_RETRIES = 0x0701;
920$IOCTL_I2C_TIMEOUT = 0x0702;
921$IOCTL_I2C_UDELAY = 0x0705;
922$IOCTL_I2C_MDELAY = 0x0706;
923
924# General ones:
925$IOCTL_I2C_SLAVE = 0x0703;
926$IOCTL_I2C_TENBIT = 0x0704;
927$IOCTL_I2C_SMBUS = 0x0720;
928
929
930
931use vars qw($SMBUS_READ $SMBUS_WRITE $SMBUS_QUICK $SMBUS_BYTE $SMBUS_BYTE_DATA
932            $SMBUS_WORD_DATA $SMBUS_PROC_CALL $SMBUS_BLOCK_DATA);
933
934# These are copied from <linux/smbus.h>
935
936$SMBUS_READ = 1;
937$SMBUS_WRITE = 0;
938$SMBUS_QUICK = 0;
939$SMBUS_BYTE = 1;
940$SMBUS_BYTE_DATA  = 2;
941$SMBUS_WORD_DATA  = 3;
942$SMBUS_PROC_CALL = 4;
943$SMBUS_BLOCK_DATA = 5;
944
945# Select the device to communicate with through its address.
946# $_[0]: Reference to an opened filehandle
947# $_[1]: Address to select
948# Returns: 0 on failure, 1 on success.
949sub i2c_set_slave_addr
950{
951  my ($file,$addr) = @_;
952  ioctl $file, $IOCTL_I2C_SLAVE, $addr or return 0;
953  return 1;
954}
955
956# i2c_smbus_access is based upon the corresponding C function (see
957# <linux/i2c-dev.h>). You should not need to call this directly.
958# Exact calling conventions are intricate; read i2c-dev.c if you really need
959# to know.
960# $_[0]: Reference to an opened filehandle
961# $_[1]: $SMBUS_READ for reading, $SMBUS_WRITE for writing
962# $_[2]: Command (usually register number)
963# $_[3]: Transaction kind ($SMBUS_BYTE, $SMBUS_BYTE_DATA, etc.)
964# $_[4]: Reference to an array used for input/output of data
965# Returns: 0 on failure, 1 on success.
966# Note that we need to get back to Integer boundaries through the 'x2'
967# in the pack. This is very compiler-dependent; I wish there was some other
968# way to do this.
969sub i2c_smbus_access
970{
971  my ($file,$read_write,$command,$size,$data) = @_;
972  my $data_array = pack "C32", @$data;
973  my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
974  ioctl $file, $IOCTL_I2C_SMBUS, $ioctl_data or return 0;
975  $_[4] = [ unpack "C32",$data_array ];
976  return 1;
977}
978
979# $_[0]: Reference to an opened filehandle
980# $_[1]: Either 0 or 1
981# Returns: -1 on failure, the 0 on success.
982sub i2c_smbus_write_quick
983{
984  my ($file,$value) = @_;
985  my $data = [];
986  i2c_smbus_access $file, $value, 0, $SMBUS_QUICK, $data 
987         or return -1;
988  return 0;
989}
990
991# $_[0]: Reference to an opened filehandle
992# Returns: -1 on failure, the read byte on success.
993sub i2c_smbus_read_byte
994{
995  my ($file) = @_;
996  my $data = [];
997  i2c_smbus_access $file, $SMBUS_READ, 0, $SMBUS_BYTE, $data 
998         or return -1;
999  return $$data[0];
1000}
1001
1002# $_[0]: Reference to an opened filehandle
1003# $_[1]: Byte to write
1004# Returns: -1 on failure, 0 on success.
1005sub i2c_smbus_write_byte
1006{
1007  my ($file,$command) = @_;
1008  my $data = [$command];
1009  i2c_smbus_access $file, $SMBUS_WRITE, 0, $SMBUS_BYTE, $data 
1010         or return -1;
1011  return 0;
1012}
1013
1014# $_[0]: Reference to an opened filehandle
1015# $_[1]: Command byte (usually register number)
1016# Returns: -1 on failure, the read byte on success.
1017sub i2c_smbus_read_byte_data
1018{
1019  my ($file,$command) = @_;
1020  my $data = [];
1021  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BYTE_DATA, $data 
1022         or return -1;
1023  return $$data[0];
1024}
1025 
1026# $_[0]: Reference to an opened filehandle
1027# $_[1]: Command byte (usually register number)
1028# $_[2]: Byte to write
1029# Returns: -1 on failure, 0 on success.
1030sub i2c_smbus_write_byte_data
1031{
1032  my ($file,$command,$value) = @_;
1033  my $data = [$value];
1034  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BYTE_DATA, $data 
1035         or return -1;
1036  return 0;
1037}
1038
1039# $_[0]: Reference to an opened filehandle
1040# $_[1]: Command byte (usually register number)
1041# Returns: -1 on failure, the read word on success.
1042# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1043# this.
1044sub i2c_smbus_read_word_data
1045{
1046  my ($file,$command) = @_;
1047  my $data = [];
1048  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_WORD_DATA, $data 
1049         or return -1;
1050  return $$data[0] + 256 * $$data[1];
1051}
1052
1053# $_[0]: Reference to an opened filehandle
1054# $_[1]: Command byte (usually register number)
1055# $_[2]: Byte to write
1056# Returns: -1 on failure, 0 on success.
1057# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1058# this.
1059sub i2c_smbus_write_word_data
1060{
1061  my ($file,$command,$value) = @_;
1062  my $data = [$value & 0xff, $value >> 8];
1063  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_WORD_DATA, $data 
1064         or return -1;
1065  return 0;
1066}
1067
1068# $_[0]: Reference to an opened filehandle
1069# $_[1]: Command byte (usually register number)
1070# $_[2]: Word to write
1071# Returns: -1 on failure, read word on success.
1072# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1073# this.
1074sub i2c_smbus_process_call
1075{
1076  my ($file,$command,$value) = @_;
1077  my $data = [$value & 0xff, $value >> 8];
1078  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_PROC_CALL, $data 
1079         or return -1;
1080  return $$data[0] + 256 * $$data[1];
1081}
1082
1083# $_[0]: Reference to an opened filehandle
1084# $_[1]: Command byte (usually register number)
1085# Returns: Undefined on failure, a list of read bytes on success
1086# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1087# this.
1088sub i2c_smbus_read_block_data
1089{
1090  my ($file,$command) = @_;
1091  my $data = [];
1092  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BLOCK_DATA, $data 
1093         or return;
1094  shift @$data;
1095  return @$data;
1096}
1097
1098# $_[0]: Reference to an opened filehandle
1099# $_[1]: Command byte (usually register number)
1100# @_[2..]: List of values to write
1101# Returns: -1 on failure, 0 on success.
1102# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1103# this.
1104sub i2c_smbus_write_block_data
1105{
1106  my ($file,$command,@data) = @_;
1107  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BLOCK_DATA, \@data 
1108         or return;
1109  return 0;
1110}
1111
1112####################
1113# ADAPTER SCANNING #
1114####################
1115
1116use vars qw(@chips_detected);
1117
1118# We will build a complicated structure @chips_detected here, being:
1119# A list of
1120#  references to hashes
1121#    with field 'driver', being a string with the driver name for this chip;
1122#    with field 'detected'
1123#      being a reference to a list of
1124#        references to hashes of type 'detect_data';
1125#    with field 'misdetected'
1126#      being a reference to a list of
1127#        references to hashes of type 'detect_data'
1128
1129# Type detect_data:
1130# A hash
1131#   with field 'i2c_adap' containing an adapter string as appearing
1132#        in /proc/bus/i2c (if this is an I2C detection)
1133#  with field 'i2c_algo' containing an algorithm string as appearing
1134#       in /proc/bus/i2c (if this is an I2C detection)
1135#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
1136#       adapter (if this is an I2C detection)
1137#  with field 'i2c_driver', containing the driver name for this adapter
1138#       (if this is an I2C detection)
1139#  with field 'i2c_addr', containing the I2C address of the detection;
1140#       (if this is an I2C detection)
1141#  with field 'i2c_sub_addrs', containing a reference to a list of
1142#       other I2C addresses (if this is an I2C detection)
1143#  with field 'i2c_extra' if this is an I2C detection and the address
1144#       is not normally probed by the kernel driver
1145#  with field 'isa_addr' containing the ISA address this chip is on
1146#       (if this is an ISA detection)
1147#  with field 'isa_extra' if this is an ISA detection and the address
1148#       is not normally probed by the kernel driver
1149#  with field 'conf', containing the confidence level of this detection
1150#  with field 'chipname', containing the chip name
1151
1152# This adds a detection to the above structure. We do no alias detection
1153# here; so you should do ISA detections *after* all I2C detections.
1154# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
1155# In all normal cases, it should be all right.
1156# $_[0]: chip driver
1157# $_[1]: reference to data hash
1158# Returns: Nothing
1159sub add_i2c_to_chips_detected
1160{
1161  my ($chipdriver,$datahash) = @_;
1162  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
1163      $main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs);
1164
1165  # First determine where the hash has to be added.
1166  for ($i = 0; $i < @chips_detected; $i++) {
1167    last if ($chips_detected[$i]->{driver} eq $chipdriver);
1168  }
1169  if ($i == @chips_detected) {
1170    push @chips_detected, { driver => $chipdriver,
1171                            detected => [],
1172                            misdetected => [] };
1173  }
1174  $new_detected_ref = $chips_detected[$i]->{detected};
1175  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
1176
1177  # Find out whether our new entry should go into the detected or the
1178  # misdetected list. We compare all i2c addresses; if at least one matches,
1179  # but our conf value is lower, we assume this is a misdetect.
1180  @hash_addrs = ($datahash->{i2c_addr});
1181  push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
1182       if exists $datahash->{i2c_sub_addrs};
1183  $put_in_detected = 1;
1184  FIND_LOOP:
1185  foreach $main_entry (@chips_detected) {
1186    foreach $detected_entry (@{$main_entry->{detected}}) {
1187      @entry_addrs = ($detected_entry->{i2c_addr});
1188      push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
1189               if exists $detected_entry->{i2c_sub_addrs};
1190      if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
1191          any_list_match \@entry_addrs, \@hash_addrs) {
1192        if ($detected_entry->{conf} >= $datahash->{conf}) {
1193          $put_in_detected = 0;
1194        }
1195        last FIND_LOOP;
1196      }
1197    }
1198  }
1199
1200  if ($put_in_detected) {
1201    # Here, we move all entries from detected to misdetected which
1202    # match at least in one main or sub address. This may not be the
1203    # best idea to do, as it may remove detections without replacing
1204    # them with second-best ones. Too bad.
1205    @hash_addrs = ($datahash->{i2c_addr});
1206    push @hash_addrs, @{$datahash->{i2c_sub_addrs}} 
1207         if exists $datahash->{i2c_sub_addrs};
1208    foreach $main_entry (@chips_detected) {
1209      $detected_ref = $main_entry->{detected};
1210      $misdetected_ref = $main_entry->{misdetected};
1211      for ($i = @$detected_ref-1; $i >=0; $i--) {
1212        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
1213        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
1214             if exists $detected_ref->[$i]->{i2c_sub_addrs};
1215        if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} and
1216            any_list_match \@entry_addrs, \@hash_addrs) {
1217          push @$misdetected_ref,$detected_ref->[$i];
1218          splice @$detected_ref, $i, 1;
1219        }
1220      }
1221    }
1222
1223    # Now add the new entry to detected
1224    push @$new_detected_ref, $datahash;
1225  } else {
1226    # No hard work here
1227    push @$new_misdetected_ref, $datahash;
1228  }
1229}
1230
1231# This adds a detection to the above structure. We also do alias detection
1232# here; so you should do ISA detections *after* all I2C detections.
1233# $_[0]: alias detection function
1234# $_[1]: chip driver
1235# $_[2]: reference to data hash
1236# Returns: 0 if it is not an alias, datahash reference if it is.
1237sub add_isa_to_chips_detected
1238{
1239  my ($alias_detect,$chipdriver,$datahash) = @_;
1240  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
1241      $main_entry,$isalias);
1242
1243  # First determine where the hash has to be added.
1244  $isalias=0;
1245  for ($i = 0; $i < @chips_detected; $i++) {
1246    last if ($chips_detected[$i]->{driver} eq $chipdriver);
1247  }
1248  if ($i == @chips_detected) {
1249    push @chips_detected, { driver => $chipdriver,
1250                            detected => [],
1251                            misdetected => [] };
1252  }
1253  $new_detected_ref = $chips_detected[$i]->{detected};
1254  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
1255
1256  # Now, we are looking for aliases. An alias can only be the same chiptype.
1257  # If an alias is found in the misdetected list, we add the new information
1258  # and terminate this function. If it is found in the detected list, we
1259  # still have to check whether another chip has claimed this ISA address.
1260  # So we remove the old entry from the detected list and put it in datahash.
1261
1262  # Misdetected alias detection:
1263  for ($i = 0; $i < @$new_misdetected_ref; $i++) {
1264    if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
1265        not exists $new_misdetected_ref->[$i]->{isa_addr} and
1266        defined $alias_detect and
1267        $new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
1268      open FILE,"/dev/i2c-$new_misdetected_ref->[$i]->{i2c_devnr}" or
1269        open FILE,"/dev/i2c$new_misdetected_ref->[$i]->{i2c_devnr}" or
1270           print("Can't open ",
1271                 "/dev/i2c[-]$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
1272           next;
1273      i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{i2c_addr} or
1274           print("Can't set I2C address for ",
1275                 "/dev/i2c[-]$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
1276           next;
1277      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
1278                          $new_misdetected_ref->[$i]->{i2c_addr})) {
1279        $new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
1280        $new_misdetected_ref->[$i]->{isa_extra} = $datahash->{isa_extra} 
1281               if exists $datahash->{isa_extra};
1282        close FILE;
1283        return $new_misdetected_ref->[$i]; 
1284      }
1285      close FILE;
1286    }
1287  }
1288
1289  # Detected alias detection:
1290  for ($i = 0; $i < @$new_detected_ref; $i++) {
1291    if (exists $new_detected_ref->[$i]->{i2c_addr} and
1292        not exists $new_detected_ref->[$i]->{isa_addr} and
1293        defined $alias_detect and
1294        $new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
1295      open FILE,"/dev/i2c-$new_detected_ref->[$i]->{i2c_devnr}" or
1296        open FILE,"/dev/i2c$new_detected_ref->[$i]->{i2c_devnr}" or
1297           print("Can't open ",
1298                 "/dev/i2c[-]$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
1299           next;
1300      i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{i2c_addr} or
1301           print("Can't set I2C address for ",
1302                 "/dev/i2c[-]$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
1303           next;
1304      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
1305                          $new_detected_ref->[$i]->{i2c_addr})) {
1306        $new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
1307        $new_detected_ref->[$i]->{isa_extra} = $datahash->{isa_extra} 
1308               if exists $datahash->{isa_extra};
1309        ($datahash) = splice (@$new_detected_ref, $i, 1);
1310        close FILE;
1311        $isalias=1;
1312        last;
1313      }
1314      close FILE;
1315    }
1316  }
1317
1318
1319  # Find out whether our new entry should go into the detected or the
1320  # misdetected list. We only compare main isa_addr here, of course.
1321  foreach $main_entry (@chips_detected) {
1322    $detected_ref = $main_entry->{detected};
1323    $misdetected_ref = $main_entry->{misdetected};
1324    for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
1325      if (exists $detected_ref->[$i]->{isa_addr} and
1326          $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
1327        if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
1328          push @$new_misdetected_ref, $datahash;
1329        } else {
1330          push @$misdetected_ref,$detected_ref->[$i];
1331          splice @$detected_ref, $i,1;
1332          push @$new_detected_ref, $datahash;
1333        }
1334        if ($isalias) {
1335          return $datahash;
1336        } else {
1337          return 0;
1338        }
1339      }
1340    }
1341  }
1342
1343  # Not found? OK, put it in the detected list
1344  push @$new_detected_ref, $datahash;
1345  if ($isalias) {
1346    return $datahash;
1347  } else {
1348    return 0;
1349  }
1350}
1351
1352# $_[0]: The number of the adapter to scan
1353# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
1354# $_[2]: The name of the algorithm, as appearing in /proc/bus/i2c
1355# $_[3]: The driver of the adapter
1356# @_[4..]: Addresses not to scan
1357sub scan_adapter
1358{
1359  my ( $adapter_nr,$adapter_name,$algorithm_name,$adapter_driver, 
1360       $not_to_scan) = @_;
1361  my ($chip, $addr, $conf,@chips,$new_hash,$other_addr);
1362
1363  # As we modify it, we need a copy
1364  my @not_to_scan = @$not_to_scan;
1365
1366  open FILE,"/dev/i2c-$adapter_nr" or 
1367    open FILE,"/dev/i2c$adapter_nr" or 
1368       (print "Can't open /dev/i2c[-]$adapter_nr\n"), return;
1369
1370  # Now scan each address in turn
1371  foreach $addr (0..0x7f) {
1372    # As the not_to_scan list is sorted, we can check it fast
1373    if (@not_to_scan and $not_to_scan[0] == $addr) {
1374      shift @not_to_scan;
1375      next;
1376    }
1377
1378    i2c_set_slave_addr(\*FILE,$addr) or 
1379        printf("Client at address 0x%02x can not be probed - unload all client drivers first!\n",$addr), next;
1380
1381    next unless i2c_smbus_write_quick(\*FILE,$SMBUS_WRITE) >= 0;
1382    printf "Client found at address 0x%02x\n",$addr;
1383
1384    foreach $chip (@chip_ids) {
1385      if (exists $$chip{i2c_addrs} and contains $addr, @{$$chip{i2c_addrs}}) {
1386        print "Probing for `$$chip{name}'... ";
1387        if (($conf,@chips) = &{$$chip{i2c_detect}} (\*FILE ,$addr)) {
1388          print "Success!\n",
1389                "    (confidence $conf, driver `$$chip{driver}')";
1390          if (@chips) {
1391            print ", other addresses:";
1392            @chips = sort @chips;
1393            foreach $other_addr (sort @chips) {
1394              printf(" 0x%02x",$other_addr);
1395            }
1396          }
1397          printf "\n";
1398          $new_hash = { conf => $conf,
1399                        i2c_addr => $addr,
1400                        chipname =>  $$chip{name},
1401                        i2c_adap => $adapter_name,
1402                        i2c_algo => $algorithm_name,
1403                        i2c_driver => $adapter_driver,
1404                        i2c_devnr => $adapter_nr,
1405                      };
1406          if (@chips) {
1407            my @chips_copy = @chips;
1408            $new_hash->{i2c_sub_addrs} = \@chips_copy;
1409          }
1410          $new_hash->{i2c_extra} = 0 
1411                 if exists $chip->{i2c_driver_addrs} and
1412                    not contains( $addr , @{$chip->{i2c_driver_addrs}});
1413          add_i2c_to_chips_detected $$chip{driver}, $new_hash;
1414        } else {
1415          print "Failed!\n";
1416        }
1417      }
1418    }
1419  }
1420}
1421
1422sub scan_isa_bus
1423{
1424  my ($chip,$addr,$conf);
1425  foreach $chip (@chip_ids) {
1426    next if not exists $$chip{isa_addrs} or not exists $$chip{isa_detect};
1427    print "Probing for `$$chip{name}'\n";
1428    foreach $addr (@{$$chip{isa_addrs}}) {
1429      if ($addr) {
1430        printf "  Trying address 0x%04x... ", $addr;
1431      } else {
1432        print "  Trying general detect... ";
1433      }
1434      $conf = &{$$chip{isa_detect}} ($addr);
1435      print("Failed!\n"), next if not defined $conf;
1436      print "Success!\n";
1437      printf "    (confidence %d, driver `%s')\n", $conf, $$chip{driver};
1438      my $new_hash = { conf => $conf,
1439                       isa_addr => $addr,
1440                       chipname =>  $$chip{name}
1441                     };
1442      $new_hash->{isa_extra} = 0 
1443             if exists $chip->{isa_driver_addrs} and
1444                not contains ($addr, @{$chip->{isa_driver_addrs}});
1445      $new_hash = add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver},
1446                                            $new_hash;
1447      if ($new_hash) {
1448        printf "    Alias of the chip on I2C bus `%s', address 0x%04x\n",
1449                        $new_hash->{i2c_adap},$new_hash->{i2c_addr};
1450      }
1451    }
1452  }
1453}
1454
1455
1456##################
1457# CHIP DETECTION #
1458##################
1459
1460# Each function returns a confidence value. The higher this value, the more
1461# sure we are about this chip. A Winbond W83781D, for example, will be
1462# detected as a LM78 too; but as the Winbond detection has a higher confidence
1463# factor, you should identify it as a Winbond.
1464
1465# Each function returns a list. The first element is the confidence value;
1466# Each element after it is an SMBus address. In this way, we can detect
1467# chips with several SMBus addresses. The SMBus address for which the
1468# function was called is never returned.
1469
1470# If there are devices which get confused if they are only read from, then
1471# this program will surely confuse them. But we guarantee never to write to
1472# any of these devices.
1473
1474
1475# $_[0]: A reference to the file descriptor to access this chip.
1476#        We may assume an i2c_set_slave_addr was already done.
1477# $_[1]: Address
1478# Returns: undef if not detected, (7) if detected.
1479# Registers used: 0x58
1480sub mtp008_detect
1481{
1482  my ($file,$addr) = @_;
1483  return if (i2c_smbus_read_byte_data($file,0x58)) != 0xac;
1484  return (8);
1485}
1486 
1487# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
1488# $_[1]: A reference to the file descriptor to access this chip.
1489#        We may assume an i2c_set_slave_addr was already done.
1490# $_[2]: Address
1491# Returns: undef if not detected, (7) if detected.
1492# Registers used:
1493#   0x40: Configuration
1494#   0x48: Full I2C Address
1495#   0x49: Device ID
1496# Note that this function is always called through a closure, so the
1497# arguments are shifted by one place.
1498sub lm78_detect
1499{
1500  my $reg;
1501  my ($chip,$file,$addr) = @_;
1502  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
1503  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
1504  $reg = i2c_smbus_read_byte_data($file,0x49);
1505  return unless ($chip == 0 and $reg == 0x00) or
1506                    ($chip == 1 and $reg == 0x40) or
1507                    ($chip == 2 and ($reg & 0xfe) == 0xc0);
1508  return (7);
1509}
1510
1511# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
1512# $_[1]: Address
1513# Returns: undef if not detected, 7 if detected.
1514# Note: Only address 0x290 is scanned at this moment.
1515sub lm78_isa_detect
1516{
1517  my ($chip,$addr) = @_ ;
1518  my $val = inb ($addr + 1);
1519  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
1520            inb ($addr + 7) != $val;
1521
1522  $val = inb($addr + 5) & 0x7f;
1523  outb($addr+5,~ $val);
1524  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
1525    outb($addr+5,$val);
1526    return;
1527  }
1528  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
1529  return unless (&$readproc(0x40) & 0x80) == 0x00;
1530  my $reg = &$readproc(0x49);
1531  return unless ($chip == 0 and $reg == 0x00) or
1532                ($chip == 1 and $reg == 0x40) or
1533                ($chip == 2 and ($reg & 0xfe) == 0xc0);
1534  return 7;
1535}
1536
1537
1538# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
1539# $_[1]: ISA address
1540# $_[2]: I2C file handle
1541# $_[3]: I2C address
1542sub lm78_alias_detect
1543{
1544  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
1545  my $i;
1546  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
1547  return 0 unless &$readproc(0x48) == $i2c_addr;
1548  for ($i = 0x2b; $i <= 0x3d; $i ++) {
1549    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
1550  }
1551  return 1;
1552}
1553
1554# $_[0]: A reference to the file descriptor to access this chip.
1555#        We may assume an i2c_set_slave_addr was already done.
1556# $_[1]: Address
1557# Returns: undef if not detected, (3) if detected.
1558# Registers used:
1559#   0x01: Configuration
1560#   0x02: Hysteresis
1561#   0x03: Overtemperature Shutdown
1562# Detection really sucks! It is only based on the fact that the LM75 has only
1563# four registers. Any other chip in the valid address range with only four
1564# registers will be detected too.
1565# Note that register $00 may change, so we can't use the modulo trick on it.
1566sub lm75_detect
1567{
1568  my $i;
1569  my ($file,$addr) = @_;
1570  my $cur = i2c_smbus_read_word_data($file,0x00);
1571  my $conf = i2c_smbus_read_byte_data($file,0x01);
1572  my $hyst = i2c_smbus_read_word_data($file,0x02);
1573  my $os = i2c_smbus_read_word_data($file,0x03);
1574  for ($i = 0x00; $i <= 0x1f; $i += 1) {
1575    return if i2c_smbus_read_byte_data($file,($i * 0x08) + 0x01) != $conf;
1576    return if i2c_smbus_read_word_data($file,($i * 0x08) + 0x02) != $hyst;
1577    return if i2c_smbus_read_word_data($file,($i * 0x08) + 0x03) != $os;
1578  }
1579  return (3);
1580}
1581 
1582# $_[0]: A reference to the file descriptor to access this chip.
1583#        We may assume an i2c_set_slave_addr was already done.
1584# $_[1]: Address
1585# Returns: undef if not detected, (3) if detected,
1586#   (6) or (9) if even more bits match.
1587# Registers used:
1588#   0xAC: Configuration
1589# Detection is weak. We check if Bit 3 is set and Bit 2 is clear.
1590# The DS1621 will aways have a config like 0x????10??. A even better
1591# match would be 0x0??01000.
1592sub ds1621_detect
1593{
1594  my $i;
1595  my ($file,$addr) = @_;
1596  my $conf = i2c_smbus_read_byte_data($file,0xAC);
1597  return (9) if ($conf & 0x9F) == 0x98;
1598  return (6) if ($conf & 0x0F) == 0x08;
1599  return (3) if ($conf & 0x0C) == 0x08;
1600  return ;
1601}
1602
1603# $_[0]: A reference to the file descriptor to access this chip.
1604#        We may assume an i2c_set_slave_addr was already done.
1605# $_[1]: Address
1606# Returns: undef if not detected, (3) if detected.
1607# Registers used:
1608# Registers used:
1609#   0x02: Interrupt state register
1610# How to detect this beast?
1611sub lm80_detect
1612{
1613  my $i;
1614  my ($file,$addr) = @_;
1615  return if (i2c_smbus_read_byte_data($file,0x02) & 0xc0) != 0;
1616  for ($i = 0x2a; $i <= 0x3d; $i++) {
1617    my $reg = i2c_smbus_read_byte_data($file,$i);
1618    return if i2c_smbus_read_byte_data($file,$i+0x40) != $reg;
1619    return if i2c_smbus_read_byte_data($file,$i+0x80) != $reg;
1620    return if i2c_smbus_read_byte_data($file,$i+0xc0) != $reg;
1621  }
1622  return (3);
1623}
1624 
1625# $_[0]: A reference to the file descriptor to access this chip.
1626#        We may assume an i2c_set_slave_addr was already done.
1627# $_[1]: Address
1628# Returns: undef if not detected, (7) if detected.
1629# Registers used: 0x3E, 0x3F
1630#        Assume lower 2 bits of reg 0x3F are for revisions.
1631sub lm87_detect
1632{
1633  my ($file,$addr) = @_;
1634  return if (i2c_smbus_read_byte_data($file,0x3e)) != 0x02;
1635  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xfc) != 0x04;
1636  return (7);
1637}
1638 
1639# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S,
1640#                        3 = W83627HF, 4 = AS99127F)
1641# $_[1]: A reference to the file descriptor to access this chip.
1642#        We may assume an i2c_set_slave_addr was already done.
1643# $_[2]: Address
1644# Returns: undef if not detected, (8,addr1,addr2) if detected, but only
1645#          if the LM75 chip emulation is enabled.
1646# Registers used:
1647#   0x48: Full I2C Address
1648#   0x4a: I2C addresses of emulated LM75 chips
1649#   0x4e: Vendor ID byte selection, and bank selection
1650#   0x4f: Vendor ID
1651#   0x58: Device ID (only when in bank 0); ignore LSB.
1652# Note: Fails if the W8378xD is not in bank 0!
1653# Note: Detection overrules a previous LM78 detection
1654# Note: AS99127F address register 0x48 not supported?
1655sub w83781d_detect
1656{
1657  my ($reg1,$reg2,@res);
1658  my ($chip,$file,$addr) = @_;
1659  return unless (i2c_smbus_read_byte_data($file,0x48) == $addr)
1660    or ($chip == 4);
1661  $reg1 = i2c_smbus_read_byte_data($file,0x4e);
1662  $reg2 = i2c_smbus_read_byte_data($file,0x4f);
1663  if ($chip != 4) {
1664    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
1665                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
1666  }
1667  if ($chip == 4) {
1668    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or 
1669                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x12);
1670  }
1671  return unless ($reg1 & 0x07) == 0x00;
1672  $reg1 = i2c_smbus_read_byte_data($file,0x58) & 0xfe;
1673  return if $chip == 0 and  $reg1 != 0x10;
1674  return if $chip == 1 and  $reg1 != 0x30;
1675  return if $chip == 2 and  $reg1 != 0x40;
1676  return if $chip == 3 and  $reg1 != 0x20;
1677  return if $chip == 4 and  $reg1 != 0x30;
1678  $reg1 = i2c_smbus_read_byte_data($file,0x4a);
1679  @res = (8);
1680  push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08 ;
1681  push @res, (($reg1 & 0x80) >> 4) + 0x48 unless ($reg1 & 0x80 or $chip == 2);
1682  return @res;
1683}
1684
1685# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S, 3 = W83627HF)
1686# $_[1]: ISA address
1687# $_[2]: I2C file handle
1688# $_[3]: I2C address
1689sub w83781d_alias_detect
1690{
1691  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
1692  my $i;
1693  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
1694  return 0 unless &$readproc(0x48) == $i2c_addr;
1695  for ($i = 0x2b; $i <= 0x3d; $i ++) {
1696    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
1697  }
1698  return 1;
1699}
1700
1701# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF, 5 = W83697HF)
1702#        (W83783S and AS99127F not on ISA bus)
1703# $_[1]: Address
1704# Returns: undef if not detected, (8) if detected.
1705sub w83781d_isa_detect
1706{
1707  my ($chip,$addr) = @_ ;
1708  my ($reg1,$reg2);
1709  my $val = inb ($addr + 1);
1710  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
1711            inb ($addr + 7) != $val;
1712
1713  $val = inb($addr + 5) & 0x7f;
1714  outb($addr+5,~ $val);
1715  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
1716    outb($addr+5,$val);
1717    return;
1718  }
1719
1720  my $read_proc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
1721  $reg1 = &$read_proc(0x4e);
1722  $reg2 = &$read_proc(0x4f);
1723  return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
1724                (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
1725  return unless ($reg1 & 0x07) == 0x00;
1726  $reg1 = &$read_proc(0x58) & 0xfe;
1727  return if $chip == 0 and  $reg1 != 0x10;
1728  return if $chip == 1 and  $reg1 != 0x30;
1729  return if $chip == 3 and  $reg1 != 0x20;
1730  return if $chip == 5 and  $reg1 != 0x60;
1731  return 8;
1732}
1733
1734# $_[0]: Chip to detect (0 = Revision 0x00, 1 = Revision 0x80)
1735# $_[1]: A reference to the file descriptor to access this chip.
1736#        We may assume an i2c_set_slave_addr was already done.
1737# $_[2]: Address
1738# Returns: undef if not detected, (6) if detected.
1739# Registers used:
1740#   0x00: Device ID
1741#   0x01: Revision ID
1742#   0x03: Configuration
1743# Mediocre detection
1744sub gl518sm_detect
1745{
1746  my $reg;
1747  my ($chip,$file,$addr) = @_;
1748  return unless i2c_smbus_read_byte_data($file,0x00) == 0x80;
1749  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
1750  $reg = i2c_smbus_read_byte_data($file,0x01);
1751  return unless ($chip == 0 and $reg == 0x00) or
1752                ($chip == 1 and $reg == 0x80);
1753  return (6);
1754}
1755
1756# $_[0]: A reference to the file descriptor to access this chip.
1757#        We may assume an i2c_set_slave_addr was already done.
1758# $_[1]: Address
1759# Returns: undef if not detected, (5) if detected.
1760# Registers used:
1761#   0x00: Device ID
1762#   0x01: Revision ID
1763#   0x03: Configuration
1764# Mediocre detection
1765sub gl520sm_detect
1766{
1767  my ($file,$addr) = @_;
1768  return unless i2c_smbus_read_byte_data($file,0x00) == 0x20;
1769  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
1770  # The line below must be better checked before I dare to use it.
1771  # return unless i2c_smbus_read_byte_data($file,0x01) == 0x00;
1772  return (5);
1773}
1774
1775# $_[0]: A reference to the file descriptor to access this chip.
1776#        We may assume an i2c_set_slave_addr was already done.
1777# $_[1]: Address
1778# Returns: undef if not detected, (5) if detected.
1779# Registers used:
1780#   0x00: Device ID
1781# Mediocre detection
1782sub gl525sm_detect
1783{
1784  my ($file,$addr) = @_;
1785  return unless i2c_smbus_read_byte_data($file,0x00) == 0x25;
1786  return (5);
1787}
1788
1789# $_[0]: Chip to detect (0 = ADM9240, 1 = DS1780, 2 = LM81)
1790# $_[1]: A reference to the file descriptor to access this chip.
1791#        We may assume an i2c_set_slave_addr was already done.
1792# $_[2]: Address
1793# Returns: undef if not detected, (7) if detected.
1794# Registers used:
1795#   0x3e: Company ID
1796#   0x40: Configuration
1797#   0x48: Full I2C Address
1798# Note: Detection overrules a previous LM78 detection
1799sub adm9240_detect
1800{
1801  my $reg;
1802  my ($chip, $file,$addr) = @_;
1803  $reg = i2c_smbus_read_byte_data($file,0x3e);
1804  return unless ($chip == 0 and $reg == 0x23) or
1805                ($chip == 1 and $reg == 0xda) or
1806                ($chip == 2 and $reg == 0x01);
1807  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
1808  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
1809 
1810  return (7);
1811}
1812
1813# $_[0]: Chip to detect (0 = ADM1022, 1 = THMC50)
1814# $_[1]: A reference to the file descriptor to access this chip.
1815#        We may assume an i2c_set_slave_addr was already done.
1816# $_[2]: Address
1817# Returns: undef if not detected, (8) if detected.
1818# Registers used:
1819#   0x3e: Company ID
1820#   0x3f: Revision
1821#   0x40: Configuration
1822# Note: Detection overrules a previous LM78 or ADM9240 detection
1823sub adm1022_detect
1824{
1825  my $reg;
1826  my ($chip, $file,$addr) = @_;
1827  $reg = i2c_smbus_read_byte_data($file,0x3e);
1828  return unless ($chip == 0 and $reg == 0x41) or
1829                ($chip == 1 and $reg == 0x49);
1830  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
1831  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xc0) == 0xc0;
1832  return (8);
1833}
1834
1835# $_[0]: Chip to detect (0 = ADM1025)
1836# $_[1]: A reference to the file descriptor to access this chip.
1837#        We may assume an i2c_set_slave_addr was already done.
1838# $_[2]: Address
1839# Returns: undef if not detected, (8) if detected.
1840# Registers used:
1841#   0x3e: Company ID
1842#   0x3f: Revision
1843#   0x40: Configuration
1844# Note: Detection overrules a previous LM78 or ADM9240 detection
1845sub adm1025_detect
1846{
1847  my $reg;
1848  my ($chip, $file,$addr) = @_;
1849  $reg = i2c_smbus_read_byte_data($file,0x3e);
1850  return unless ($reg == 0x41);
1851  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
1852  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xc0) == 0x20;
1853  return (8);
1854}
1855
1856# $_[0]: Chip to detect
1857#   (0 = ADM1021, 1 = MAX1617, 2 = MAX1617A, 3 = THMC10, 4 = LM84, 5 = GL523)
1858# $_[1]: A reference to the file descriptor to access this chip.
1859#        We may assume an i2c_set_slave_addr was already done.
1860# $_[2]: Address
1861# Returns: undef if not detected, (6) or (3) if detected.
1862# Registers used:
1863#   0x04: Company ID (LM84 only)
1864#   0xfe: Company ID
1865#   0xff: Revision (Maxim only)
1866#   0x02: Status
1867# Note: Especially the Maxim has very bad detection; we give it a low
1868# confidence value.
1869sub adm1021_detect
1870{
1871  my $reg;
1872  my ($chip, $file,$addr) = @_;
1873  return if $chip == 0 and i2c_smbus_read_byte_data($file,0xfe) != 0x41;
1874  return if $chip == 3 and i2c_smbus_read_byte_data($file,0xfe) != 0x49;
1875  return if $chip == 4 and i2c_smbus_read_byte_data($file,0x04) != 0x00;
1876  return if $chip == 5 and i2c_smbus_read_byte_data($file,0xfe) != 0x23;
1877  return if $chip == 2 and i2c_smbus_read_byte_data($file,0xfe) != 0x4d and
1878                           i2c_smbus_read_byte_data($file,0xff) != 0x01;
1879  # The remaining things are flaky at best. Perhaps something can be done
1880  # with the fact that some registers are unreadable?
1881  return if (i2c_smbus_read_byte_data($file,0x02) & 0x03) != 0;
1882  if ($chip == 1) {
1883    return (3);
1884  } else {
1885    return (6);
1886  }
1887}
1888
1889# $_[0]: Address
1890# Returns: undef if not detected, (9) if detected.
1891# Note: It is already 99% certain this chip exists if we find the PCI
1892# entry. The exact address is encoded in PCI space.
1893sub sis5595_isa_detect
1894{
1895  my ($addr) = @_;
1896  my ($adapter,$try,$local_try);
1897  my $found = 0;
1898  foreach $local_try (@pci_adapters) {
1899    if ($local_try->{procid} eq "Silicon Integrated Systems SIS5595") {
1900      $try = $local_try;
1901      $found = 1;
1902      last;
1903    }
1904  }
1905  return if not $found;
1906
1907  $found = 0;
1908  foreach $adapter (@pci_list) {
1909    if ((defined($adapter->{vendid}) and 
1910         $try->{vendid} == $adapter->{vendid} and
1911         $try->{devid} == $adapter->{devid} and
1912         $try->{func} == $adapter->{func}) or
1913        (! defined($adapter->{vendid}) and
1914         $adapter->{desc} =~ /$try->{procid}/ and
1915         $try->{func} == $adapter->{func})) {
1916      $found = 1;
1917      last;
1918    }
1919  }
1920  return if not $found;
1921
1922  return 9;
1923}
1924
1925# $_[0]: Address
1926# Returns: undef if not detected, (9) if detected.
1927# Note: It is already 99% certain this chip exists if we find the PCI
1928# entry. The exact address is encoded in PCI space.
1929sub via686a_isa_detect
1930{
1931  my ($addr) = @_;
1932  my ($adapter,$try,$local_try);
1933  my $found = 0;
1934  foreach $local_try (@pci_adapters) {
1935    if ($local_try->{procid} eq "VIA Technologies VT 82C686 Apollo ACPI") {
1936      $try = $local_try;
1937      $found = 1;
1938      last;
1939    }
1940  }
1941  return if not $found;
1942
1943  $found = 0;
1944  foreach $adapter (@pci_list) {
1945    if ((defined($adapter->{vendid}) and 
1946         $try->{vendid} == $adapter->{vendid} and
1947         $try->{devid} == $adapter->{devid} and
1948         $try->{func} == $adapter->{func}) or
1949        (! defined($adapter->{vendid}) and
1950         $adapter->{desc} =~ /$try->{procid}/ and
1951         $try->{func} == $adapter->{func})) {
1952      $found = 1;
1953      last;
1954    }
1955  }
1956  return if not $found;
1957
1958  return 9;
1959}
1960
1961# $_[0]: Chip to detect (0 = ..., 1 = ...)
1962# $_[1]: A reference to the file descriptor to access this chip.
1963#        We may assume an i2c_set_slave_addr was already done.
1964# $_[2]: Address
1965# Returns: undef if not detected, (7) if detected.
1966# Registers used:
1967#   0x40: Configuration
1968#   0x48: Full I2C Address
1969#   0x58: Mfr ID
1970# Note that this function is always called through a closure, so the
1971# arguments are shifted by one place.
1972sub ite_detect
1973{
1974  my $reg;
1975  my ($chip,$file,$addr) = @_;
1976  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
1977  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
1978  return unless i2c_smbus_read_byte_data($file,0x58) == 0x90;
1979  return (7);
1980}
1981
1982# $_[0]: Chip to detect (0 = ..., 1 = ...)
1983# $_[1]: Address
1984# Returns: undef if not detected, 7 if detected.
1985# Note: Only address 0x290 is scanned at this moment.
1986sub ite_isa_detect
1987{
1988  my ($chip,$addr) = @_ ;
1989  my $val = inb ($addr + 1);
1990  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
1991            inb ($addr + 7) != $val;
1992
1993  $val = inb($addr + 5) & 0x7f;
1994  outb($addr+5,~ $val);
1995  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
1996    outb($addr+5,$val);
1997    return;
1998  }
1999  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
2000  return unless (&$readproc(0x40) & 0x80) == 0x00;
2001  my $reg = &$readproc(0x58);
2002  return unless ($reg == 0x90);
2003  return 7;
2004}
2005
2006
2007# $_[0]: Chip to detect (0 = ..., 1 = ...)
2008# $_[1]: ISA address
2009# $_[2]: I2C file handle
2010# $_[3]: I2C address
2011sub ite_alias_detect
2012{
2013  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
2014  my $i;
2015  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
2016  return 0 unless &$readproc(0x48) == $i2c_addr;
2017  for ($i = 0x2b; $i <= 0x3d; $i ++) {
2018    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
2019  }
2020  return 1;
2021}
2022
2023# $_[0]: A reference to the file descriptor to access this chip.
2024#        We may assume an i2c_set_slave_addr was already done.
2025# $_[1]: Address
2026# Returns: undef if not detected, (5) if detected.
2027# Registers used:
2028#   0x00-0x63: PC-100 Data and Checksum
2029sub eeprom_detect
2030{
2031  my ($file,$addr) = @_;
2032  # Check the checksum for validity (only works for PC-100 DIMMs)
2033  my $checksum = 0;
2034  for (my $i = 0; $i <= 62; $i = $i + 1) {
2035    $checksum = $checksum + i2c_smbus_read_byte_data($file,$i);
2036  }
2037  $checksum=$checksum & 255;
2038  if (i2c_smbus_read_byte_data($file,63) == $checksum) {
2039        return (8);
2040  }
2041  # Even if checksum test fails, it still may be an eeprom
2042  return (1);
2043}
2044
2045# $_[0]: A reference to the file descriptor to access this chip.
2046#        We may assume an i2c_set_slave_addr was already done.
2047# $_[1]: Address
2048# Returns: undef if not detected, (1) if detected.
2049# Detection is impossible!
2050sub ltc1710_detect
2051{
2052  return (1);
2053}
2054
2055# $_[0]: A reference to the file descriptor to access this chip.
2056#        We may assume an i2c_set_slave_addr was already done.
2057# $_[1]: Address
2058# Returns: undef if not detected, (1) if detected.
2059# Registers used:
2060#   0x00..0x07: DDC signature
2061#   0x08..0x7E: checksumed area
2062#   0x7F:       checksum
2063### commented out additional location checks for now - don't work?
2064sub ddcmonitor_detect
2065{
2066  my ($file,$addr) = @_;
2067  my $i;
2068###  for ($i = 0; $i < 8; $i ++) {
2069###    i2c_set_slave_addr \*FILE,$addr+$i or goto FAILURE;
2070    i2c_smbus_read_byte_data($file,0x00) == 0x00 or goto FAILURE;
2071    i2c_smbus_read_byte_data($file,0x01) == 0xFF or goto FAILURE;
2072    i2c_smbus_read_byte_data($file,0x02) == 0xFF or goto FAILURE;
2073    i2c_smbus_read_byte_data($file,0x03) == 0xFF or goto FAILURE;
2074    i2c_smbus_read_byte_data($file,0x04) == 0xFF or goto FAILURE;
2075    i2c_smbus_read_byte_data($file,0x05) == 0xFF or goto FAILURE;
2076    i2c_smbus_read_byte_data($file,0x06) == 0xFF or goto FAILURE;
2077    i2c_smbus_read_byte_data($file,0x07) == 0x00 or goto FAILURE;
2078###  }
2079###  i2c_set_slave_addr \*FILE,$addr or return;
2080  # Check the checksum for validity. We should do this for all addresses,
2081  # but it would be too slow.
2082  my $checksum = 0;
2083  for ($i = 0; $i <= 127; $i = $i + 1) {
2084    $checksum = $checksum + i2c_smbus_read_byte_data($file,$i);
2085  }
2086  $checksum=$checksum & 255;
2087  if ($checksum != 0) {
2088    # I have one such monitor...
2089    return (2,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
2090  }
2091  return (8,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
2092FAILURE:
2093  i2c_set_slave_addr \*FILE,$addr;
2094  return;
2095}
2096
2097################
2098# MAIN PROGRAM #
2099################
2100
2101# $_[0]: reference to a list of chip hashes
2102sub print_chips_report 
2103{
2104  my ($listref) = @_;
2105  my $data;
2106 
2107  foreach $data (@$listref) {
2108    my $is_i2c = exists $data->{i2c_addr};
2109    my $is_isa = exists $data->{isa_addr};
2110    print "  * ";
2111    if ($is_i2c) {
2112      printf "Bus `%s' (%s)\n", $data->{i2c_adap}, $data->{i2c_algo};
2113      printf "    Busdriver `%s', I2C address 0x%02x", 
2114             $data->{i2c_driver}, $data->{i2c_addr};
2115      if (exists $data->{i2c_sub_addrs}) {
2116        print " (and";
2117        my $sub_addr;
2118        foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
2119          printf " 0x%02x",$sub_addr;
2120        }
2121        print ")"
2122      }
2123      print "\n";
2124    }
2125    if ($is_isa) {
2126      print "    " if  $is_i2c;
2127      if ($data->{isa_addr}) {
2128        printf "ISA bus address 0x%04x (Busdriver `i2c-isa')\n", 
2129               $data->{isa_addr};
2130      } else {
2131        printf "ISA bus, undetermined address (Busdriver `i2c-isa')\n"
2132      }
2133    }
2134    printf "    Chip `%s' (confidence: %d)\n",
2135           $data->{chipname},  $data->{conf};
2136  }
2137}
2138
2139# $_[0]: 1 if ISA bus is prefered, 0 for SMBus
2140# We build here an array adapters, indexed on the number the adapter has
2141# at this moment (we assume only loaded adapters are interesting at all;
2142# everything that got scanned also got loaded). Each entry is a reference
2143# to a hash containing:
2144#  driver: Name of the adapter driver
2145#  nr_now: Number of the bus now
2146#  nr_later: Number of the bus when the modprobes are done (not included if the
2147#        driver should not be loaded)
2148# A second array, called
2149sub generate_modprobes
2150{
2151  my ($prefer_isa) = @_;
2152
2153  my ($chip,$detection,$nr,$i,@optionlist,@probelist,$driver,$isa,$adap);
2154  my @adapters;
2155  my $modprobes = "";
2156  my $configfile = "";
2157
2158  # These are always needed
2159  $configfile .= "# I2C module options\n";
2160  $configfile .= "alias char-major-89 i2c-dev\n";
2161
2162  # Collect all loaded adapters
2163  open INPUTFILE,"/proc/bus/i2c" or die "Couldn't open /proc/bus/i2c?!?";
2164  while (<INPUTFILE>) {
2165    my ($dev_nr,$type,$adap,$algo) = /^i2c-(\S+)\s+(\S+)\s+(.*?)\s*\t\s*(.*?)\s+$/;
2166    next if ($type eq "dummy");
2167    $adapters[$dev_nr]->{driver} = find_adapter_driver($adap,$algo);
2168    $adapters[$dev_nr]->{adapname} = $adap;
2169    $adapters[$dev_nr]->{algoname} = $algo;
2170  }
2171  close INPUTFILE;
2172
2173  # Collect all adapters used
2174  $nr = 0;
2175  $isa = 0;
2176  $modprobes .= "# I2C adapter drivers\n";
2177  foreach $chip (@chips_detected) {
2178    foreach $detection (@{$chip->{detected}}) {
2179      # If there is more than one bus detected by a driver, they are
2180      # still all added. So we number them in the correct order
2181      if (exists $detection->{i2c_driver} and
2182          not exists $adapters[$detection->{i2c_devnr}]->{nr_later} and 
2183          not (exists $detection->{isa_addr} and $prefer_isa)) {
2184         foreach $adap (@adapters) {
2185           $adap->{nr_later} = $nr++ if $adap->{driver} eq $detection->{i2c_driver};
2186         }
2187      }
2188      if (exists $detection->{isa_addr} and
2189          not (exists $detection->{i2c_driver} and not $prefer_isa)) {
2190           $isa=1;
2191      }
2192    }
2193  }
2194
2195  for ($i = 0; $i < $nr; $i++) {
2196    foreach $adap (@adapters) {
2197      if ($adap->{driver} eq "UNKNOWN") {
2198        $modprobes .= "# modprobe unknown adapter ".$adap->{adapname}." using ". $adap->{algoname}."\n";
2199      } else {
2200        $modprobes .= "modprobe $adap->{driver}\n" if (defined($adap->{nr_later}) and $adap->{nr_later} == $i) and not $modprobes =~ /modprobe $adap->{driver}\n/;
2201      }
2202    }
2203  }
2204  $modprobes .= "modprobe i2c-isa\n" if ($isa);
2205
2206  # Now determine the chip probe lines
2207  $modprobes .= "# I2C chip drivers\n";
2208  foreach $chip (@chips_detected) {
2209    next if not @{$chip->{detected}};
2210    $modprobes .= "modprobe $chip->{driver}\n";
2211    @optionlist = ();
2212    @probelist = ();
2213
2214    # Handle detects at addresses normally not probed
2215    foreach $detection (@{$chip->{detected}}) {
2216      push @probelist, $adapters[$detection->{i2c_devnr}]->{nr_later},
2217                       $detection->{i2c_addr}
2218           if exists $detection->{i2c_addr} and
2219              exists $detection->{i2c_extra};
2220      push @probelist, -1, $detection->{isa_addr}
2221           if exists $detection->{isa_addr} and
2222              exists $detection->{isa_extra};
2223    }
2224
2225    # Handle misdetects
2226    foreach $detection (@{$chip->{misdetected}}) {
2227      push @optionlist, $adapters[$detection->{i2c_devnr}]->{nr_later},
2228                       $detection->{i2c_addr}
2229           if exists $detection->{i2c_addr} and
2230              exists $adapters[$detection->{i2c_devnr}]->{nr_later};
2231      push @optionlist, -1, $detection->{isa_addr}
2232           if exists $detection->{isa_addr} and $isa;
2233    }
2234
2235    # Handle aliases
2236    foreach $detection (@{$chip->{detected}}) {
2237      if (exists $detection->{i2c_driver} and 
2238          exists $detection->{isa_addr} and
2239          exists $adapters[$detection->{i2c_devnr}]->{nr_later} and
2240          $isa) {
2241        if ($prefer_isa) {
2242          push @optionlist,$adapters[$detection->{i2c_devnr}]->{nr_later},
2243                           $detection->{i2c_addr};
2244        } else {
2245          push @optionlist, -1, $detection->{isa_addr}
2246        }
2247      }
2248    }
2249
2250    next if not (@probelist or @optionlist);
2251    $configfile .= "options $chip->{driver}";
2252    $configfile .= sprintf " ignore=%d,0x%02x",shift @optionlist, 
2253                                               shift @optionlist
2254                  if @optionlist;
2255    $configfile .= sprintf ",%d,0x%02x",shift @optionlist, shift @optionlist
2256                  while @optionlist;
2257    $configfile .= sprintf " probe=%d,0x%02x",shift @probelist,
2258                                              shift @probelist
2259                  if @probelist;
2260    $configfile .= sprintf ",%d,0x%02x",shift @probelist, shift @probelist
2261                  while @probelist;
2262    $configfile .= "\n";
2263  }
2264
2265  return ($modprobes,$configfile);
2266 
2267}
2268
2269sub main
2270{
2271  my (@adapters,$res,$did_adapter_detection,$detect_others,$adapter);
2272
2273  initialize_proc_pci;
2274  initialize_modules_list;
2275
2276  print " This program will help you to determine which I2C/SMBus modules you ",
2277        "need to\n",
2278        " load to use lm_sensors most effectively.\n";
2279  print " You need to have done a `make install', issued a `depmod -a' and ",
2280        "made sure\n",
2281        " `/etc/conf.modules' (or `/etc/modules.conf') contains the ",
2282        "appropriate\n",
2283        " module path before you can use some functions of this utility. ",
2284        "Read\n",
2285        " doc/modules for more information.\n";
2286  print " Also, you need to be `root', or at least have access to the ",
2287        "/dev/i2c[-]* files\n",
2288        " for some things. You can use prog/mkdev/mkdev.sh to create these ",
2289        "/dev files\n",
2290        " if you do not have them already.\n";
2291  print " If you have patched your kernel and have some drivers built-in ",
2292        "you can\n",
2293        " safely answer NO if asked to load some modules. In this case, ",
2294        "things may\n",
2295        " seem a bit confusing, but they will still work.\n\n";
2296
2297  print " We can start with probing for (PCI) I2C or SMBus adapters.\n";
2298  print " You do not need any special privileges for this.\n";
2299  print " Do you want to probe now? (YES/no): ";
2300  @adapters = adapter_pci_detection
2301                        if ($did_adapter_detection = not <STDIN> =~ /\s*[Nn]/);
2302
2303  print "\n";
2304
2305  if (not $did_adapter_detection) {
2306    print " As you skipped adapter detection, we will only scan already ",
2307          "loaded adapter\n",
2308          " modules. You can still be prompted for non-detectable adapters.\n",
2309          " Do you want to? (yes/NO): ";
2310    $detect_others = <STDIN> =~ /^\s*[Yy]/;
2311  } elsif ($> != 0) {
2312    print " As you are not root, we can't load adapter modules. We will only ",
2313          "scan\n",
2314          " already loaded adapters.\n";
2315    $detect_others = 0;
2316  } else {
2317    print " We will now try to load each adapter module in turn.\n";
2318    foreach $adapter (@adapters) {
2319      if (contains $adapter, @modules_list) {
2320        print "Module `$adapter' already loaded.\n";
2321      } else {
2322        print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
2323        unless (<STDIN> =~ /^\s*[Nn]/) {
2324          if (system ("modprobe", $adapter)) {
2325            print "Loading failed ($!)... skipping.\n";
2326            if ($adapter eq "i2c-riva") {
2327              print "** Note: i2c-riva module is available at \n";
2328              print "** http://drama.obuda.kando.hu/~fero/cgi-bin/rivatv.shtml\n"; 
2329            }
2330          } else {
2331            print "Module loaded succesfully.\n";
2332          }
2333        }
2334      }
2335    }
2336    print " Do you now want to be prompted for non-detectable adapters? ",
2337          "(yes/NO): ";
2338    $detect_others = <STDIN> =~ /^\s*[Yy]/ ;
2339  }
2340
2341  if ($detect_others) {
2342    foreach $adapter (@undetectable_adapters) {
2343      print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
2344      unless (<STDIN> =~ /^\s*[Nn]/) {
2345        if (system ("modprobe", $adapter)) {
2346          print "Loading failed ($!)... skipping.\n";
2347        } else {
2348          print "Module loaded succesfully.\n";
2349        }
2350      }
2351    }
2352  }
2353
2354  print " To continue, we need module `i2c-dev' to be loaded.\n";
2355  print " If it is built-in into your kernel, you can safely skip this.\n";
2356  if (contains "i2c-dev", @modules_list) {
2357    print "i2c-dev is already loaded.\n";
2358  } else {
2359    if ($> != 0) {
2360      print " i2c-dev is not loaded. As you are not root, we will just hope ",
2361            "you edited\n",
2362            " `/etc/conf.modules' (or `/etc/modules.conf') for automatic ",
2363            "loading of\n",
2364            " this module. If not, you won't be able to open any /dev/i2c[-]* ",
2365            "file.\n";
2366    } else {
2367      print " i2c-dev is not loaded. Do you want to load it now? (YES/no): ";
2368      if (<STDIN> =~ /^\s*[Nn]/) {
2369        print " Well, you will know best. We will just hope you edited ",
2370              "`/etc/conf.modules'\n",
2371              " (or `/etc/modules.conf') for automatic loading of this ",
2372              "module. If not,\n",
2373              " you won't be able to open any /dev/i2c[-]* file (unless you",
2374              "have it built-in\n",
2375              " into your kernel)\n";
2376      } elsif (system "modprobe","i2c-dev") {
2377        print " Loading failed ($!), expect problems later on.\n";
2378      } else {
2379        print " Module loaded succesfully.\n";
2380      }
2381    }
2382  }
2383
2384  print "\n We are now going to do the adapter probings. Some adapters may ",
2385        "hang halfway\n",
2386        " through; we can't really help that. Also, some chips will be double ",
2387        "detected;\n",
2388        " we choose the one with the highest confidence value in that case.\n",
2389        " If you found that the adapter hung after probing a certain address, ",
2390        "you can\n",
2391        " specify that address to remain unprobed. If you have a PIIX4, that ",
2392        "often\n",
2393        " includes addresses 0x69 and/or 0x6a.\n";
2394
2395  my ($inp,@not_to_scan,$inp2);
2396  open INPUTFILE,"/proc/bus/i2c" or die "Couldn't open /proc/bus/i2c?!?";
2397  while (<INPUTFILE>) {
2398    my ($dev_nr,$type,$adap,$algo) = /^i2c-(\S+)\s+(\S+)\s+(.*?)\s*\t\s*(.*?)\s+$/;
2399    next if ($type eq "dummy");
2400    print "\n";
2401    print "Next adapter: $adap ($algo)\n";
2402    print "Do you want to scan it? (YES/no/selectively): ";
2403   
2404    $inp = <STDIN>;
2405    @not_to_scan=();
2406    if ($inp =~ /^\s*[Ss]/) {
2407      print "Please enter one or more addresses not to scan. Separate them ",
2408            "with comma's.\n",
2409            "You can specify a range by using dashes. Addresses may be ",
2410            "decimal (like 54)\n",
2411            "or hexadecimal (like 0x33).\n",
2412            "Addresses: ";
2413      $inp2 = <STDIN>;
2414      chop $inp2;
2415      @not_to_scan = parse_not_to_scan 0,0x7f,$inp2;
2416    }
2417    scan_adapter $dev_nr, $adap, $algo, find_adapter_driver($adap,$algo),
2418                 \@not_to_scan   unless $inp =~ /^\s*[Nn]/;
2419  }
2420
2421  print "\n Some chips are also accessible through the ISA bus. ISA probes ",
2422        "are\n",
2423        " typically a bit more dangerous, as we have to write to I/O ports ",
2424        "to do\n",
2425        " this. ";
2426  if ($> != 0) {
2427    print "As you are not root, we shall skip this step.\n";
2428  } else {
2429    print " Do you want to scan the ISA bus? (YES/no): ";
2430    if (not <STDIN> =~ /^\s*[Nn]/) {
2431      initialize_ioports or die "Sorry, can't access /dev/port ($!)?!?";
2432      scan_isa_bus;
2433    }
2434  }
2435
2436  print "\n Now follows a summary of the probes I have just done.\n";
2437  print " Just press ENTER to continue: ";
2438  <STDIN>;
2439
2440  my ($chip,$data);
2441  foreach $chip (@chips_detected) {
2442    print "\nDriver `$$chip{driver}' ";
2443    if (@{$$chip{detected}}) {
2444      if (@{$$chip{misdetected}}) {
2445        print "(should be inserted but causes problems):\n";
2446      } else {
2447        print "(should be inserted):\n";
2448      }
2449    } else {
2450      if (@{$$chip{misdetected}}) {
2451        print "(may not be inserted):\n";
2452      } else {
2453        print "(should not be inserted, but is harmless):\n";
2454      }
2455    }
2456    if (@{$$chip{detected}}) {
2457      print "  Detects correctly:\n";
2458      print_chips_report $chip->{detected};
2459    }
2460    if (@{$$chip{misdetected}}) {
2461      print "  Misdetects:\n";
2462      print_chips_report $chip->{misdetected};
2463    }
2464  }
2465
2466  print "\n\n",
2467        " I will now generate the commands needed to load the I2C modules.\n",
2468        " Sometimes, a chip is available both through the ISA bus and an ",
2469        "I2C bus.\n",
2470        " ISA bus access is faster, but you need to load an additional driver ",
2471        "module\n",
2472        " for it. If you have the choice, do you want to use the ISA bus or ",
2473        "the\n",
2474        " I2C/SMBus (ISA/smbus)? ";
2475  my $use_isa = not <STDIN> =~ /\s*[Ss]/;
2476     
2477  my ($modprobes,$configfile) = generate_modprobes $use_isa;
2478  print "\nWARNING! If you have some things built into your kernel, the \n",
2479        "below list will contain too many modules. Skip the appropriate ones!";
2480  print "\nTo load everything that is needed, add this to some /etc/rc* ",
2481        "file:\n\n";
2482  print "#----cut here----\n";
2483  print $modprobes;
2484  print "#----cut here----\n";
2485  print "\nTo make the sensors modules behave correctly, add these lines to ",
2486        "either\n",
2487        "/etc/modules.conf or /etc/conf.modules:\n\n";
2488  print "#----cut here----\n";
2489  print $configfile;
2490  print "#----cut here----\n";
2491 
2492}
2493
2494main;
Note: See TracBrowser for help on using the browser.