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

Revision 859, 75.2 KB (checked in by frodo, 14 years ago)

Two small sensors-detect errors fixed:
* LM80 detect was broken, because it tried to access register $0x02

(instead of 0x02); this resulted in a runtime warning.

* At one place, another perl warning is fixed now.

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