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

Revision 714, 68.0 KB (checked in by mds, 13 years ago)

(mds) Referenced ddcmon driver. Commented out 0x51-0x57 checking for ddcmon,

not working for me. Have to ask Petr.

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