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

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

add VT8233 support to i2c-viapro.

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