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

Revision 678, 63.8 KB (checked in by frodo, 13 years ago)

Fixed a problem when the same address was used on different adapters

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