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

Revision 1194, 84.0 KB (checked in by mds, 12 years ago)

add ITE 8172 detection (driver in kernel 2.4.10)

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