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

Revision 1090, 81.0 KB (checked in by mds, 14 years ago)

Initial checkin of adm1024 driver and support in libsensors,

sensors, sensors-detect.

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