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

Revision 284, 50.3 KB (checked in by phil, 14 years ago)

(Phil) Altered LM75 detection slightly to find my LM75.

  • 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#    detect.pl - 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
28use strict;
29
30#########################
31# CONSTANT DECLARATIONS #
32#########################
33
34use vars qw(@pci_adapters @chip_ids @undetectable_adapters);
35
36@undetectable_adapters = ( "bit-lp", "bit-velle" );
37
38# This is the list of SMBus or I2C adapters we recognize by their PCI
39# signature. This is an easy and fast way to determine which SMBus or I2C
40# adapters should be present.
41# Each entry must have a vindid (Vendor ID), devid (Device ID), func (PCI
42# Function) and procid (string as appears in /proc/pci; see linux/driver/pci,
43# either pci.c or oldproc.c). If no driver is written yet, omit the
44# driver (Driver Name) field. The match (Match Description) field should
45# contain a function which returns zero if its two parameter matches
46# the text as it would appear in /proc/bus/i2c.
47@pci_adapters = ( 
48     { 
49       vendid => 0x8086,
50       devid  => 0x7113,
51       func => 3,
52       procid => "Intel 82371AB PIIX4 ACPI",
53       driver => "i2c-piix4",
54       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at [0-9,a-f]{4}/ },
55     } , 
56     { 
57       vendid => 0x1106,
58       devid  => 0x3040,
59       func => 3,
60       procid => "VIA Technologies VT 82C586B Apollo ACPI",
61       driver => "i2c-via",
62       match => sub { $_[0] =~ /^VIA i2c/ },
63     } ,
64     {
65       vendid => 0x1039,
66       devid  => 0x0008,
67       func => 0,
68       procid => "Silicon Integrated Systems 85C503",
69       match => sub { 0 },
70     } ,
71     {
72       vendid => 0x10b9,
73       devid => 0x7101,
74       funcid => 0,
75       procid => "Acer Labs M7101",
76       driver => "i2c-ali15x3",
77       match => sub { $_[0] =~ /^SMBus ALI15X3 adapter at [0-9,a-f]{4}/ },
78     }
79);
80
81use subs qw(lm78_detect lm78_isa_detect lm78_alias_detect lm75_detect
82            lm80_detect w83781d_detect w83781d_alias_detect
83            w83781d_isa_detect gl518sm_detect gl520sm_detect adm9240_detect
84            adm1021_detect sis5595_isa_detect eeprom_detect);
85
86# This is a list of all recognized chips.
87# Each entry must have the following fields:
88#  name: The full chip name
89#  driver (optional): The driver name (without .o extension). Omit if none is
90#      written yet.
91#  i2c_addrs (optional): For I2C chips, the range of valid I2C addresses to
92#      probe.
93#  i2c_detect (optional): For I2C chips, the function to call to detect
94#      this chip. The function should take two parameters: an open file
95#      descriptor to access the bus, and the I2C address to probe.
96#  isa_addrs (optional): For ISA chips, the range of valid port addresses to
97#      probe.
98#  isa_detect (optional): For ISA chips, the function to call to detect
99#      this chip. The function should take one parameter: the ISA address
100#      to probe.
101#  alias_detect (optional): For chips which can be both on the ISA and the
102#      I2C bus, a function which detectes whether two entries are the same.
103#      The function should take three parameters: The ISA address, the
104#      I2C bus number, and the I2C address.
105@chip_ids = (
106     {
107       name => "National Semiconductors LM78",
108       driver => "lm78",
109       i2c_addrs => [0x00..0x7f], 
110       i2c_detect => sub { lm78_detect 0, @_},
111       isa_addrs => [0x290],
112       isa_detect => sub { lm78_isa_detect 0, @_ },
113       alias_detect => sub { lm78_alias_detect 0, @_ },
114     } ,
115     {
116       name => "National Semiconductors LM78-J",
117       driver => "lm78",
118       i2c_addrs => [0x00..0x7f],
119       i2c_detect => sub { lm78_detect 1, @_ },
120       isa_addrs => [0x290],
121       isa_detect => sub { lm78_isa_detect 1, @_ },
122       alias_detect => sub { lm78_alias_detect 1, @_ },
123     } ,
124     {
125       name => "National Semiconductors LM79",
126       driver => "lm78",
127       i2c_addrs => [0x00..0x7f],
128       i2c_detect => sub { lm78_detect 2, @_ },
129       isa_addrs => [0x290],
130       isa_detect => sub { lm78_isa_detect 2, @_ },
131       alias_detect => sub { lm78_alias_detect 2, @_ },
132     } ,
133     {
134       name => "National Semiconductors LM75",
135       driver => "lm75",
136       i2c_addrs => [0x48..0x4f],
137       i2c_detect => sub { lm75_detect @_},
138     } ,
139     {
140       name => "National Semiconductors LM80",
141       driver => "lm80",
142       i2c_addrs => [0x28..0x2f],
143       i2c_detect => sub { lm80_detect @_} ,
144     },
145     {
146       name => "Winbond W83781D",
147       driver => "w83781d",
148       i2c_addrs => [0x00..0x7f], 
149       i2c_detect => sub { w83781d_detect 0, @_},
150       isa_addrs => [0x290],
151       isa_detect => sub { w83781d_isa_detect 0, @_ },
152       alias_detect => sub { w83781d_alias_detect 0, @_ },
153     } ,
154     {
155       name => "Winbond W83782D",
156       driver => "w83781d",
157       i2c_addrs => [0x00..0x7f], 
158       i2c_detect => sub { w83781d_detect 1, @_},
159       isa_addrs => [0x290],
160       isa_detect => sub { w83781d_isa_detect 1, @_ },
161       alias_detect => sub { w83781d_alias_detect 1, @_ },
162     } ,
163     {
164       name => "Winbond W83783S",
165       driver => "w83781d",
166       i2c_addrs => [0x00..0x7f], 
167       i2c_detect => sub { w83781d_detect 2, @_},
168       isa_addrs => [0x290],
169       isa_detect => sub { w83781d_isa_detect 2, @_ },
170       alias_detect => sub { w83781d_alias_detect 2, @_ },
171     } ,
172     {
173       name => "Genesys Logic GL518SM Revision 0x00",
174       driver => "gl518sm",
175       i2c_addrs => [0x4c, 0x4d],
176       i2c_detect => sub { gl518sm_detect 0, @_} ,
177     },
178     {
179       name => "Genesys Logic GL518SM Revision 0x80",
180       driver => "gl518sm",
181       i2c_addrs => [0x4c, 0x4d],
182       i2c_detect => sub { gl518sm_detect 1, @_} ,
183     },
184     {
185       name => "Genesys Logic GL520SM",
186       i2c_addrs => [0x4c, 0x4d],
187       i2c_detect => sub { gl520sm_detect @_} ,
188     },
189     {
190       name => "Analog Devices ADM9240",
191       driver => "adm9240",
192       i2c_addrs => [0x2c..0x2f],
193       i2c_detect => sub { adm9240_detect @_ }
194     },
195     {
196       name => "Analog Devices ADM1021",
197       driver => "adm1021",
198       i2c_addrs => [0x18..0x1b,0x29..0x2b,0x4c..0x4e],
199       i2c_detect => sub { adm1021_detect 0, @_ },
200     },
201     {
202       name => "Maxim MAX1617",
203       driver => "adm1021",
204       i2c_addrs => [0x18..0x1b,0x29..0x2b,0x4c..0x4e],
205       i2c_detect => sub { adm1021_detect 1, @_ },
206     },
207     {
208       name => "Silicon Integrated Systems SIS5595",
209       driver => "sis5595",
210       isa_addrs => [ 0 ],
211       isa_detect => sub { sis5595_isa_detect @_ },
212     },
213     {
214       name => "Serial EEPROM (PC-100 DIMM)",
215       driver => "eeprom",
216       i2c_addrs => [0x50..0x57],
217       i2c_detect => sub { eeprom_detect @_ },
218     }
219);
220
221
222#######################
223# AUXILIARY FUNCTIONS #
224#######################
225
226sub swap_bytes
227{
228  return (($_[0] & 0xff00) >> 8) + (($_[0] & 0x00ff) << 8)
229}
230
231# $_[0] is the sought value
232# @_[1..] is the list to seek in
233# Returns: 0 on failure, 1 if found.
234sub contains
235{
236  my $sought = shift;
237  foreach (@_) {
238    return 1 if $sought eq $_;
239  }
240  return 0;
241}
242
243sub parse_not_to_scan
244{
245  my ($min,$max,$to_parse) = @_;
246  my @ranges = split /\s*,\s*/, $to_parse;
247  my @res = ();
248  my $range;
249  foreach $range (@ranges) {
250    my ($start,$end) = split /\s*-s*/, $range;
251    $start = oct $start if $start =~ /^0/;
252    if (defined $end) {
253      $end = oct $end if $end =~ /^0/;
254      $start = $min if $start < $min;
255      $end = $max if $end > $max;
256      push @res, ($start+0..$end+0);
257    } else {
258      push @res, $start+0 if $start >= $min and $start <= $max;
259    }
260  }
261  return sort { $a <=> $b } @res;
262}
263
264# @_[0]: Reference to list 1
265# @_[1]: Reference to list 2
266# Result: 0 if they have no elements in common, 1 if they have
267# Elements must be numeric.
268sub any_list_match
269{
270  my ($list1,$list2) = @_;
271  my ($el1,$el2);
272  foreach $el1 (@$list1) {
273    foreach $el2 (@$list2) {
274      return 1 if $el1 == $el2;
275    }
276  }
277  return 0;
278}
279
280###################
281# I/O port access #
282###################
283
284sub initialize_ioports
285{
286  sysopen IOPORTS, "/dev/port", 2;
287}
288
289# $_[0]: port to read
290# Returns: -1 on failure, read value on success.
291sub inb
292{
293  my ($res,$nrchars);
294  sysseek IOPORTS, $_[0], 0 or return -1;
295  $nrchars = sysread IOPORTS, $res, 1;
296  return -1 if not defined $nrchars or $nrchars != 1;
297  $res = unpack "C",$res ;
298  return $res;
299}
300
301# $_[0]: port to write
302# $_[1]: value to write
303# Returns: -1 on failure, 0 on success.
304sub outb
305{
306  my $towrite = pack "C", $_[1];
307  sysseek IOPORTS, $_[0], 0 or return -1;
308  my $nrchars = syswrite IOPORTS, $towrite, 1;
309  return -1 if not defined $nrchars or $nrchars != 1;
310  return 0;
311}
312
313# $_[0]: Address register
314# $_[1]: Data register
315# $_[2]: Register to read
316# Returns: read value
317sub isa_read_byte
318{
319  outb $_[0],$_[2];
320  return inb $_[1];
321}
322
323# $_[0]: Address register
324# $_[1]: Data register
325# $_[2]: Register to write
326# $_[3}: Value to write
327# Returns: nothing
328sub isa_write_byte
329{
330  outb $_[0],$_[2];
331  outb $_[1],$_[3];
332}
333
334###########
335# MODULES #
336###########
337
338use vars qw(@modules_list);
339
340sub initialize_modules_list
341{
342  open INPUTFILE, "/proc/modules" or die "Can't access /proc/modules!";
343  while (<INPUTFILE>) {
344    push @modules_list, /^(\S*)/ ;
345  }
346  close INPUTFILE;
347}
348
349##############
350# PCI ACCESS #
351##############
352
353use vars qw(@pci_list);
354
355# This function returns a list of hashes. Each hash has some PCI information
356# (more than we will ever need, probably). The most important
357# fields are 'bus', 'slot', 'func' (they uniquely identify a PCI device in
358# a computer) and 'vendid','devid' (they uniquely identify a type of device).
359# /proc/bus/pci/devices is only available on late 2.1 and 2.2 kernels.
360sub read_proc_dev_pci
361{
362  my ($dfn,$vend,@pci_list);
363  open INPUTFILE, "/proc/bus/pci/devices" or return;
364  while (<INPUTFILE>) {
365    my $record = {};
366    ($dfn,$vend,$record->{irq},$record->{base_addr0},$record->{base_addr1},
367          $record->{base_addr2},$record->{base_addr3},$record->{base_addr4},
368          $record->{base_addr5},$record->{rom_base_addr}) = 
369          map { oct "0x$_" } split;
370    $record->{bus} = $dfn >> 8;
371    $record->{slot} = ($dfn & 0xf8) >> 3;
372    $record->{func} = $dfn & 0x07;
373    $record->{vendid} = $vend >> 16;
374    $record->{devid} = $vend & 0xffff;
375  push @pci_list,$record;
376  }
377  close INPUTFILE or return;
378  return @pci_list;
379}
380
381# This function returns a list of hashes. Each hash has some PCI
382# information. The important fields here are 'bus', 'slot', 'func' (they
383# uniquely identify a PCI device in a computer) and 'desc' (a functional
384# description of the PCI device). If this is an 'unknown device', the
385# vendid and devid fields are set instead.
386sub read_proc_pci
387{
388  my @pci_list;
389  open INPUTFILE, "/proc/pci" or return;
390  while (<INPUTFILE>) {
391    my $record = {};
392    if (($record->{bus},$record->{slot},$record->{func}) = 
393        /^\s*Bus\s*(\S)+\s*,\s*device\s*(\S+)\s*,\s*function\s*(\S+)\s*:\s*$/) {
394      my $desc = <INPUTFILE>;
395      unless (($desc =~ /Unknown device/) and
396              (($record->{vendid},$record->{devid}) = 
397                         /^\s*Vendor id=(\S+)\.\s*Device id=(\S+)\.$/)) {
398        $record->{desc} = $desc;
399      }
400      push @pci_list,$record;
401    }
402  }
403  close INPUTFILE or return;
404  return @pci_list;
405}
406
407sub initialize_proc_pci
408{
409  @pci_list = read_proc_dev_pci;
410  @pci_list = read_proc_pci     if not defined @pci_list;
411  die "Can't access either /proc/bus/pci/ or /proc/pci!" 
412                                    if not defined @pci_list;
413}
414
415#####################
416# ADAPTER DETECTION #
417#####################
418
419sub all_available_adapters
420{
421  my @res = ();
422  my ($module,$adapter);
423  MODULES:
424  foreach $module (@modules_list) {
425    foreach $adapter (@pci_adapters) {
426      if (exists $adapter->{driver} and $module eq $adapter->{driver}) {
427        push @res, $module;
428        next MODULES;
429      }
430    }
431  }
432  return @res;
433}
434
435sub adapter_pci_detection
436{
437  my ($device,$try,@res);
438  print "Probing for PCI bus adapters...\n";
439
440  foreach $device (@pci_list) {
441    foreach $try (@pci_adapters) {
442      if ((defined($device->{vendid}) and 
443           $try->{vendid} == $device->{vendid} and
444           $try->{devid} == $device->{devid} and
445           $try->{func} == $device->{func}) or
446          (! defined($device->{vendid}) and
447           $device->{desc} =~ /$try->{procid}/ and
448           $try->{func} == $device->{func})) {
449        printf "Use driver `%s' for device %02x:%02x.%x: %s\n",
450               $try->{driver}?$try->{driver}:"<To Be Written>",
451               $device->{bus},$device->{slot},$device->{func},$try->{procid};
452        push @res,$try->{driver};
453      }
454    }
455  }
456  if (! defined @res) {
457    print ("Sorry, no PCI bus adapters found.\n");
458  } else {
459    printf ("Probe succesfully concluded.\n");
460  }
461  return @res;
462}
463
464# $_[0]: Adapter description as found in /proc/bus/i2c
465# $_[1]: Algorithm description as found in /proc/bus/i2c
466sub find_adapter_driver
467{
468  my $adapter;
469  for $adapter (@pci_adapters) {
470    return $adapter->{driver} if &{$adapter->{match}} ($_[0],$_[1]);
471  }
472  return "?????";
473}
474
475#############################
476# I2C AND SMBUS /DEV ACCESS #
477#############################
478
479# This should really go into a separate module/package.
480
481# To do: support i2c-level access (through sysread/syswrite, probably).
482# I can't test this at all (PIIX4 does not support this), so I have not
483# included it.
484
485use vars qw($IOCTL_I2C_RETRIES $IOCTL_I2C_TIMEOUT $IOCTL_I2C_UDELAY
486            $IOCTL_I2C_MDELAY $IOCTL_I2C_SLAVE $IOCTL_I2C_TENBIT
487            $IOCTL_I2C_SMBUS);
488
489# These are copied from <linux/i2c.h> and <linux/smbus.h>
490
491# For bit-adapters:
492$IOCTL_I2C_RETRIES = 0x0701;
493$IOCTL_I2C_TIMEOUT = 0x0702;
494$IOCTL_I2C_UDELAY = 0x0705;
495$IOCTL_I2C_MDELAY = 0x0706;
496
497# General ones:
498$IOCTL_I2C_SLAVE = 0x0703;
499$IOCTL_I2C_TENBIT = 0x0704;
500$IOCTL_I2C_SMBUS = 0x0720;
501
502
503use vars qw($SMBUS_READ $SMBUS_WRITE $SMBUS_QUICK $SMBUS_BYTE $SMBUS_BYTE_DATA
504            $SMBUS_WORD_DATA $SMBUS_PROC_CALL $SMBUS_BLOCK_DATA);
505
506# These are copied from <linux/smbus.h>
507
508$SMBUS_READ = 1;
509$SMBUS_WRITE = 0;
510$SMBUS_QUICK = 0;
511$SMBUS_BYTE = 1;
512$SMBUS_BYTE_DATA  = 2;
513$SMBUS_WORD_DATA  = 3;
514$SMBUS_PROC_CALL = 4;
515$SMBUS_BLOCK_DATA = 5;
516
517# Select the device to communicate with through its address.
518# $_[0]: Reference to an opened filehandle
519# $_[1]: Address to select
520# Returns: 0 on failure, 1 on success.
521sub i2c_set_slave_addr
522{
523  my ($file,$addr) = @_;
524  ioctl $file, $IOCTL_I2C_SLAVE, $addr or return 0;
525  return 1;
526}
527
528# i2c_smbus_access is based upon the corresponding C function (see
529# <linux/i2c-dev.h>). You should not need to call this directly.
530# Exact calling conventions are intricate; read i2c-dev.c if you really need
531# to know.
532# $_[0]: Reference to an opened filehandle
533# $_[1]: $SMBUS_READ for reading, $SMBUS_WRITE for writing
534# $_[2]: Command (usually register number)
535# $_[3]: Transaction kind ($SMBUS_BYTE, $SMBUS_BYTE_DATA, etc.)
536# $_[4]: Reference to an array used for input/output of data
537# Returns: 0 on failure, 1 on success.
538# Note that we need to get back to Integer boundaries through the 'x2'
539# in the pack. This is very compiler-dependent; I wish there was some other
540# way to do this.
541sub i2c_smbus_access
542{
543  my ($file,$read_write,$command,$size,$data) = @_;
544  my $data_array = pack "C32", @$data;
545  my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
546  ioctl $file, $IOCTL_I2C_SMBUS, $ioctl_data or return 0;
547  $_[4] = [ unpack "C32",$data_array ];
548  return 1;
549}
550
551# $_[0]: Reference to an opened filehandle
552# $_[1]: Either 0 or 1
553# Returns: -1 on failure, the 0 on success.
554sub i2c_smbus_write_quick
555{
556  my ($file,$value) = @_;
557  my $data = [];
558  i2c_smbus_access $file, $value, 0, $SMBUS_QUICK, $data 
559         or return -1;
560  return 0;
561}
562
563# $_[0]: Reference to an opened filehandle
564# Returns: -1 on failure, the read byte on success.
565sub i2c_smbus_read_byte
566{
567  my ($file) = @_;
568  my $data = [];
569  i2c_smbus_access $file, $SMBUS_READ, 0, $SMBUS_BYTE, $data 
570         or return -1;
571  return $$data[0];
572}
573
574# $_[0]: Reference to an opened filehandle
575# $_[1]: Byte to write
576# Returns: -1 on failure, 0 on success.
577sub i2c_smbus_write_byte
578{
579  my ($file,$command) = @_;
580  my $data = [$command];
581  i2c_smbus_access $file, $SMBUS_WRITE, 0, $SMBUS_BYTE, $data 
582         or return -1;
583  return 0;
584}
585
586# $_[0]: Reference to an opened filehandle
587# $_[1]: Command byte (usually register number)
588# Returns: -1 on failure, the read byte on success.
589sub i2c_smbus_read_byte_data
590{
591  my ($file,$command) = @_;
592  my $data = [];
593  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BYTE_DATA, $data 
594         or return -1;
595  return $$data[0];
596}
597 
598# $_[0]: Reference to an opened filehandle
599# $_[1]: Command byte (usually register number)
600# $_[2]: Byte to write
601# Returns: -1 on failure, 0 on success.
602sub i2c_smbus_write_byte_data
603{
604  my ($file,$command,$value) = @_;
605  my $data = [$value];
606  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BYTE_DATA, $data 
607         or return -1;
608  return 0;
609}
610
611# $_[0]: Reference to an opened filehandle
612# $_[1]: Command byte (usually register number)
613# Returns: -1 on failure, the read word on success.
614# Note: some devices use the wrong endiannes; use swap_bytes to correct for
615# this.
616sub i2c_smbus_read_word_data
617{
618  my ($file,$command) = @_;
619  my $data = [];
620  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_WORD_DATA, $data 
621         or return -1;
622  return $$data[0] + 256 * $$data[1];
623}
624
625# $_[0]: Reference to an opened filehandle
626# $_[1]: Command byte (usually register number)
627# $_[2]: Byte to write
628# Returns: -1 on failure, 0 on success.
629# Note: some devices use the wrong endiannes; use swap_bytes to correct for
630# this.
631sub i2c_smbus_write_word_data
632{
633  my ($file,$command,$value) = @_;
634  my $data = [$value & 0xff, $value >> 8];
635  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_WORD_DATA, $data 
636         or return -1;
637  return 0;
638}
639
640# $_[0]: Reference to an opened filehandle
641# $_[1]: Command byte (usually register number)
642# $_[2]: Word to write
643# Returns: -1 on failure, read word on success.
644# Note: some devices use the wrong endiannes; use swap_bytes to correct for
645# this.
646sub i2c_smbus_process_call
647{
648  my ($file,$command,$value) = @_;
649  my $data = [$value & 0xff, $value >> 8];
650  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_PROC_CALL, $data 
651         or return -1;
652  return $$data[0] + 256 * $$data[1];
653}
654
655# $_[0]: Reference to an opened filehandle
656# $_[1]: Command byte (usually register number)
657# Returns: Undefined on failure, a list of read bytes on success
658# Note: some devices use the wrong endiannes; use swap_bytes to correct for
659# this.
660sub i2c_smbus_read_block_data
661{
662  my ($file,$command) = @_;
663  my $data = [];
664  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BLOCK_DATA, $data 
665         or return;
666  shift @$data;
667  return @$data;
668}
669
670# $_[0]: Reference to an opened filehandle
671# $_[1]: Command byte (usually register number)
672# @_[2..]: List of values to write
673# Returns: -1 on failure, 0 on success.
674# Note: some devices use the wrong endiannes; use swap_bytes to correct for
675# this.
676sub i2c_smbus_write_block_data
677{
678  my ($file,$command,@data) = @_;
679  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BLOCK_DATA, \@data 
680         or return;
681  return 0;
682}
683
684####################
685# ADAPTER SCANNING #
686####################
687
688use vars qw(@chips_detected);
689
690# We will build a complicated structure @chips_detected here, being:
691# A list of
692#  references to hashes
693#    with field 'driver', being a string with the driver name for this chip;
694#    with field 'detected'
695#      being a reference to a list of
696#        references to hashes of type 'detect_data';
697#    with field 'misdetected'
698#      being a reference to a list of
699#        references to hashes of type 'detect_data'
700
701# Type detect_data:
702# A hash
703#   with field 'i2c_adap' containing an adapter string as appearing
704#        in /proc/bus/i2c (if this is an I2C detection)
705#  with field 'i2c_algo' containing an algorithm string as appearing
706#       in /proc/bus/i2c (if this is an I2C detection)
707#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
708#       adapter (if this is an I2C detection)
709#  with field 'i2c_driver', containing the driver name for this adapter
710#       (if this is an I2C detection)
711#  with field 'i2c_addr', containing the I2C address of the detection;
712#       (if this is an I2C detection)
713#  with field 'i2c_sub_addrs', containing a reference to a list of
714#       other I2C addresses (if this is an I2C detection)
715#  with field 'isa_addr' containing the ISA address this chip is on
716#       (if this is an ISA detection)
717#  with field 'conf', containing the confidence level of this detection
718#  with field 'chipname', containing the chip name
719
720# This adds a detection to the above structure. We do no alias detection
721# here; so you should do ISA detections *after* all I2C detections.
722# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
723# In all normal cases, it should be all right.
724# $_[0]: chip driver
725# $_[1]: reference to data hash
726# Returns: Nothing
727sub add_i2c_to_chips_detected
728{
729  my ($chipdriver,$datahash) = @_;
730  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
731      $main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs);
732
733  # First determine where the hash has to be added.
734  for ($i = 0; $i < @chips_detected; $i++) {
735    last if ($chips_detected[$i]->{driver} eq $chipdriver);
736  }
737  if ($i == @chips_detected) {
738    push @chips_detected, { driver => $chipdriver,
739                            detected => [],
740                            misdetected => [] };
741  }
742  $new_detected_ref = $chips_detected[$i]->{detected};
743  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
744
745  # Find out whether our new entry should go into the detected or the
746  # misdetected list. We only compare main i2c_addr here; so we can have
747  # the unlikely case that we replace a subsidiary i2c_addr with a higher
748  # confidence value. Too bad.
749  $put_in_detected = 1;
750  FIND_LOOP:
751  foreach $main_entry (@chips_detected) {
752    foreach $detected_entry (@{$main_entry->{detected}}) {
753      if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
754          $detected_entry->{i2c_addr} == $datahash->{i2c_addr}) {
755        if ($detected_entry->{conf} >= $datahash->{conf}) {
756          $put_in_detected = 0;
757        }
758        last FIND_LOOP;
759      }
760    }
761  }
762
763  if ($put_in_detected) {
764    # Here, we move all entries from detected to misdetected which
765    # match at least in one main or sub address. This may not be the
766    # best idea to do, as it may remove detections without replacing
767    # them with second-best ones. Too bad.
768    @hash_addrs = ($datahash->{i2c_addr});
769    push @hash_addrs, @{$datahash->{i2c_sub_addrs}} 
770         if exists $datahash->{i2c_sub_addrs};
771    foreach $main_entry (@chips_detected) {
772      $detected_ref = $main_entry->{detected};
773      $misdetected_ref = $main_entry->{misdetected};
774      for ($i = @$detected_ref-1; $i >=0; $i--) {
775        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
776        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
777             if exists $detected_ref->[$i]->{i2c_sub_addrs};
778        if (any_list_match \@entry_addrs, \@hash_addrs) {
779          push @$misdetected_ref,$detected_ref->[$i];
780          splice @$detected_ref, $i, 1;
781        }
782      }
783    }
784
785    # Now add the new entry to detected
786    push @$new_detected_ref, $datahash;
787  } else {
788    # No hard work here
789    push @$new_misdetected_ref, $datahash;
790  }
791}
792
793# This adds a detection to the above structure. We also do alias detection
794# here; so you should do ISA detections *after* all I2C detections.
795# $_[0]: alias detection function
796# $_[1]: chip driver
797# $_[2]: reference to data hash
798# Returns: Nothing
799sub add_isa_to_chips_detected
800{
801  my ($alias_detect,$chipdriver,$datahash) = @_;
802  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
803      $main_entry);
804
805  # First determine where the hash has to be added.
806  for ($i = 0; $i < @chips_detected; $i++) {
807    last if ($chips_detected[$i]->{driver} eq $chipdriver);
808  }
809  if ($i == @chips_detected) {
810    push @chips_detected, { driver => $chipdriver,
811                            detected => [],
812                            misdetected => [] };
813  }
814  $new_detected_ref = $chips_detected[$i]->{detected};
815  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
816
817  # Now, we are looking for aliases. An alias can only be the same chiptype.
818  # If an alias is found in the misdetected list, we add the new information
819  # and terminate this function. If it is found in the detected list, we
820  # still have to check whether another chip has claimed this ISA address.
821  # So we remove the old entry from the detected list and put it in datahash.
822
823  # Misdetected alias detection:
824  for ($i = 0; $i < @$new_misdetected_ref; $i++) {
825    if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
826        not exists $new_misdetected_ref->[$i]->{isa_addr} and
827        defined $alias_detect and
828        $new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
829      open FILE,"/dev/i2c-$new_misdetected_ref->[$i]->{devnr}" or
830           print("Can't open ",
831                 "/dev/i2c-$new_misdetected_ref->[$i]->{devnr}?!?\n"),
832           next;
833      i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{address} or
834           print("Can't set I2C address for ",
835                 "/dev/i2c-$new_misdetected_ref->[$i]->{devnr}?!?\n"),
836           next;
837      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
838                          $new_misdetected_ref->[$i]->{i2c_addr})) {
839        $new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
840        close FILE;
841        return;
842      }
843      close FILE;
844    }
845  }
846
847  # Detected alias detection:
848  for ($i = 0; $i < @$new_detected_ref; $i++) {
849    if (exists $new_detected_ref->[$i]->{i2c_addr} and
850        not exists $new_detected_ref->[$i]->{isa_addr} and
851        defined $alias_detect and
852        $new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
853      open FILE,"/dev/i2c-$new_detected_ref->[$i]->{devnr}" or
854           print("Can't open ",
855                 "/dev/i2c-$new_detected_ref->[$i]->{devnr}?!?\n"),
856           next;
857      i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{address} or
858           print("Can't set I2C address for ",
859                 "/dev/i2c-$new_detected_ref->[$i]->{devnr}?!?\n"),
860           next;
861      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
862                          $new_detected_ref->[$i]->{i2c_addr})) {
863        $new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
864        ($datahash) = splice (@$new_detected_ref, $i, 1);
865        close FILE;
866        last;
867      }
868      close FILE;
869    }
870  }
871
872
873  # Find out whether our new entry should go into the detected or the
874  # misdetected list. We only compare main isa_addr here, of course.
875  foreach $main_entry (@chips_detected) {
876    $detected_ref = $main_entry->{detected};
877    $misdetected_ref = $main_entry->{misdetected};
878    for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
879      if (exists $detected_ref->[$i]->{isa_addr} and
880          $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
881        if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
882          push @$new_misdetected_ref, $datahash;
883        } else {
884          push @$misdetected_ref,$detected_ref->[$i];
885          splice @$detected_ref, $i,1;
886          push @$new_detected_ref, $datahash;
887        }
888        return;
889      }
890    }
891  }
892
893  # Nor found? OK, put it in the detected list
894  push @$new_detected_ref, $datahash;
895}
896
897# $_[0]: The number of the adapter to scan
898# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
899# $_[2]: The name of the algorithm, as appearing in /proc/bus/i2c
900# $_[3]: The driver of the adapter
901sub scan_adapter
902{
903  my ( $adapter_nr,$adapter_name,$algorithm_name,$adapter_driver, 
904       $not_to_scan) = @_;
905  my ($chip, $addr, $conf,@chips,$new_hash,$other_addr);
906
907  # As we modify it, we need a copy
908  my @not_to_scan = @$not_to_scan;
909
910  open FILE,"/dev/i2c-$adapter_nr" or 
911       (print "Can't open /dev/i2c-$adapter_nr ($!)\n"), return;
912
913  # Now scan each address in turn
914  foreach $addr (0..0x7f) {
915    # As the not_to_scan list is sorted, we can check it fast
916    if (@not_to_scan and $not_to_scan[0] == $addr) {
917      shift @not_to_scan;
918      next;
919    }
920
921    i2c_set_slave_addr(\*FILE,$addr) or print("Can't set address to $_?!?\n"), 
922                                     next;
923
924    next unless i2c_smbus_read_byte(\*FILE) >= 0;
925    printf "Client found at address 0x%02x\n",$addr;
926
927    foreach $chip (@chip_ids) {
928      if (exists $$chip{i2c_addrs} and contains $addr, @{$$chip{i2c_addrs}}) {
929        print "Probing for `$$chip{name}'... ";
930        if (($conf,@chips) = &{$$chip{i2c_detect}} (\*FILE ,$addr)) {
931          print "Success!\n",
932                "    (confidence $conf, driver `$$chip{driver}'";
933          if (@chips) {
934            print ", other addresses:";
935            @chips = sort @chips;
936            foreach $other_addr (sort @chips) {
937              printf(" %02x",$other_addr);
938            }
939          }
940          printf "\n";
941          $new_hash = { conf => $conf,
942                        i2c_addr => $addr,
943                        chipname =>  $$chip{name},
944                        i2c_adap => $adapter_name,
945                        i2c_algo => $algorithm_name,
946                        i2c_driver => $adapter_driver,
947                        i2c_devnr => $adapter_nr,
948                      };
949          $new_hash->{i2c_sub_addrs} = \@chips if (@chips);
950          add_i2c_to_chips_detected $$chip{driver}, $new_hash;
951        } else {
952          print "Failed!\n";
953        }
954      }
955    }
956  }
957}
958
959sub scan_isa_bus
960{
961  my ($chip,$addr,$conf);
962  foreach $chip (@chip_ids) {
963    next if not exists $$chip{isa_addrs} or not exists $$chip{isa_detect};
964    print "Probing for `$$chip{name}'\n";
965    foreach $addr (@{$$chip{isa_addrs}}) {
966      if ($addr) {
967        printf "  Trying address 0x%04x... ", $addr;
968      } else {
969        print "  Trying general detect... ";
970      }
971      $conf = &{$$chip{isa_detect}} ($addr);
972      print("Failed!\n"), next if not defined $conf;
973      print "Success!\n";
974      printf "    (confidence %d, driver `%s')\n", $conf, $$chip{driver};
975      add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver}, 
976                                { conf => $conf,
977                                  isa_addr => $addr,
978                                  chipname =>  $$chip{name},
979                                };
980    }
981  }
982}
983
984
985##################
986# CHIP DETECTION #
987##################
988
989# Each function returns a confidence value. The higher this value, the more
990# sure we are about this chip. A Winbond W83781D, for example, will be
991# detected as a LM78 too; but as the Winbond detection has a higher confidence
992# factor, you should identify it as a Winbond.
993
994# Each function returns a list. The first element is the confidence value;
995# Each element after it is an SMBus address. In this way, we can detect
996# chips with several SMBus addresses. The SMBus address for which the
997# function was called is never returned.
998
999# If there are devices which get confused if they are only read from, then
1000# this program will surely confuse them. But we guarantee never to write to
1001# any of these devices.
1002
1003
1004# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
1005# $_[1]: A reference to the file descriptor to access this chip.
1006#        We may assume an i2c_set_slave_addr was already done.
1007# $_[2]: Address
1008# Returns: undef if not detected, (7) if detected.
1009# Registers used:
1010#   0x40: Configuration
1011#   0x48: Full I2C Address
1012#   0x49: Device ID
1013# Note that this function is always called through a closure, so the
1014# arguments are shifted by one place.
1015sub lm78_detect
1016{
1017  my $reg;
1018  my ($chip,$file,$addr) = @_;
1019  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
1020  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
1021  $reg = i2c_smbus_read_byte_data($file,0x49);
1022  return unless ($chip == 0 and $reg == 0x00) or
1023                    ($chip == 1 and $reg == 0x40) or
1024                    ($chip == 2 and ($reg & 0xfe) == 0xc0);
1025  return (7);
1026}
1027
1028# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
1029# $_[1]: Address
1030# Returns: undef if not detected, (7) if detected.
1031# Note: Only address 0x290 is scanned at this moment.
1032sub lm78_isa_detect
1033{
1034  my ($chip,$addr) = @_ ;
1035  my $val = inb ($addr + 1);
1036  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
1037            inb ($addr + 7) != $val;
1038  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
1039  return unless (&$readproc(0x40) & 0x80) == 0x00;
1040  my $reg = &$readproc(0x49);
1041  return unless ($chip == 0 and $reg == 0x00) or
1042                ($chip == 1 and $reg == 0x40) or
1043                ($chip == 2 and ($reg & 0xfe) == 0xc0);
1044  return 7;
1045}
1046
1047
1048# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
1049# $_[1]: ISA address
1050# $_[2]: I2C file handle
1051# $_[3]: I2C address
1052sub lm78_alias_detect
1053{
1054  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
1055  my $i;
1056  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
1057  return 0 unless &$readproc(0x48) == $i2c_addr;
1058  for ($i = 0x2b; $i <= 0x3d; $i ++) {
1059    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
1060  }
1061  return 1;
1062}
1063
1064# $_[0]: A reference to the file descriptor to access this chip.
1065#        We may assume an i2c_set_slave_addr was already done.
1066# $_[1]: Address
1067# Returns: undef if not detected, (3) if detected.
1068# Registers used:
1069#   0x01: Configuration
1070#   0x02: Hysteris
1071#   0x03: Overtemperature Shutdown
1072# Detection really sucks! It is only based on the fact that the LM75 has only
1073# four registers. Any other chip in the valid address range with only four
1074# registers will be detected too.
1075# Note that register $00 may change, so we can't use the modulo trick on it.
1076sub lm75_detect
1077{
1078  my $i;
1079  my ($file,$addr) = @_;
1080  my $conf = i2c_smbus_read_byte_data($file,0x01);
1081  my $hyst = i2c_smbus_read_word_data($file,0x02);
1082  my $os = i2c_smbus_read_word_data($file,0x03);
1083  for ($i = 0x00; $i <= 0xF; $i += 1) {
1084    return if i2c_smbus_read_byte_data($file,($i * 0x10) + 0x01) != $conf;
1085    return if i2c_smbus_read_word_data($file,($i * 0x10) + 0x02) != $hyst;
1086    return if i2c_smbus_read_word_data($file,($i * 0x10) + 0x03) != $os;
1087  }
1088  return (3);
1089}
1090 
1091
1092# $_[0]: A reference to the file descriptor to access this chip.
1093#        We may assume an i2c_set_slave_addr was already done.
1094# $_[1]: Address
1095# Returns: undef if not detected, (3) if detected.
1096# Registers used:
1097# Registers used:
1098#   0x02: Interrupt state register
1099# How to detect this beast?
1100sub lm80_detect
1101{
1102  my $i;
1103  my ($file,$addr) = @_;
1104  return if (i2c_smbus_read_byte_data($file,$0x02) & 0xc0) != 0;
1105  for ($i = 0x2a; $i <= 0x3d; $i++) {
1106    my $reg = i2c_smbus_read_byte_data($file,$i);
1107    return if i2c_smbus_read_byte_data($file,$i+0x40) != $reg;
1108    return if i2c_smbus_read_byte_data($file,$i+0x80) != $reg;
1109    return if i2c_smbus_read_byte_data($file,$i+0xc0) != $reg;
1110  }
1111  return (3);
1112}
1113 
1114# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83783S)
1115# $_[1]: A reference to the file descriptor to access this chip.
1116#        We may assume an i2c_set_slave_addr was already done.
1117# $_[2]: Address
1118# Returns: undef if not detected, (8,addr1,addr2) if detected, but only
1119#          if the LM75 chip emulation is enabled.
1120# Registers used:
1121#   0x48: Full I2C Address
1122#   0x4a: I2C addresses of emulated LM75 chips
1123#   0x4e: Vendor ID byte selection, and bank selection
1124#   0x4f: Vendor ID
1125#   0x58: Device ID (only when in bank 0); both 0x10 and 0x11 is seen for
1126#         W83781D though Winbond documents 0x10 only.
1127# Note: Fails if the W8378xD is not in bank 0!
1128# Note: Detection overrules a previous LM78 detection
1129sub w83781d_detect
1130{
1131  my ($reg1,$reg2,@res);
1132  my ($chip,$file,$addr) = @_;
1133  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
1134  $reg1 = i2c_smbus_read_byte_data($file,0x4e);
1135  $reg2 = i2c_smbus_read_byte_data($file,0x4f);
1136  return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
1137                (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
1138  return unless ($reg1 & 0x07) == 0x00;
1139  $reg1 = i2c_smbus_read_byte_data($file,0x58);
1140  return if $chip == 0 and  ($reg1 & 0xfe) != 0x10;
1141  return if $chip == 1 and  $reg1 != 0x30;
1142  return if $chip == 2 and  $reg1 != 0x40;
1143  $reg1 = i2c_smbus_read_byte_data($file,0x4a);
1144  @res = (8);
1145  push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08;
1146  push @res, (($reg1 & 0x80) >> 4) + 0x48 unless $reg1 & 0x80;
1147  return @res;
1148}
1149
1150# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83783S)
1151# $_[1]: ISA address
1152# $_[2]: I2C file handle
1153# $_[3]: I2C address
1154sub w83781d_alias_detect
1155{
1156  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
1157  my $i;
1158  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
1159  return 0 unless &$readproc(0x48) == $i2c_addr;
1160  for ($i = 0x2b; $i <= 0x3d; $i ++) {
1161    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
1162  }
1163  return 1;
1164}
1165
1166# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83783S)
1167# $_[1]: Address
1168# Returns: undef if not detected, (8) if detected.
1169sub w83781d_isa_detect
1170{
1171  my ($chip,$addr) = @_ ;
1172  my ($reg1,$reg2);
1173  my $val = inb ($addr + 1);
1174  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
1175            inb ($addr + 7) != $val;
1176  my $read_proc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
1177  $reg1 = &$read_proc(0x4e);
1178  $reg2 = &$read_proc(0x4f);
1179  return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
1180                (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
1181  return unless ($reg1 & 0x07) == 0x00;
1182  $reg1 = &$read_proc(0x58);
1183  return if $chip == 0 and  ($reg1 & 0xfe) != 0x10;
1184  return if $chip == 1 and  $reg1 != 0x30;
1185  return if $chip == 2 and  $reg1 != 0x40;
1186  return 8;
1187}
1188
1189# $_[0]: Chip to detect (0 = Revision 0x00, 1 = Revision 0x80)
1190# $_[1]: A reference to the file descriptor to access this chip.
1191#        We may assume an i2c_set_slave_addr was already done.
1192# $_[2]: Address
1193# Returns: undef if not detected, (6) if detected.
1194# Registers used:
1195#   0x00: Device ID
1196#   0x01: Revision ID
1197#   0x03: Configuration
1198# Mediocre detection
1199sub gl518sm_detect
1200{
1201  my $reg;
1202  my ($chip,$file,$addr) = @_;
1203  return unless i2c_smbus_read_byte_data($file,0x00) == 0x80;
1204  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
1205  $reg = i2c_smbus_read_byte_data($file,0x01);
1206  return unless ($chip == 0 and $reg == 0x00) or
1207                ($chip == 1 and $reg == 0x80);
1208  return (6);
1209}
1210
1211# $_[0]: A reference to the file descriptor to access this chip.
1212#        We may assume an i2c_set_slave_addr was already done.
1213# $_[1]: Address
1214# Returns: undef if not detected, (5) if detected.
1215# Registers used:
1216#   0x00: Device ID
1217#   0x01: Revision ID
1218#   0x03: Configuration
1219# Mediocre detection
1220sub gl520sm_detect
1221{
1222  my ($file,$addr) = @_;
1223  return unless i2c_smbus_read_byte_data($file,0x00) == 0x20;
1224  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
1225  # The line below must be better checked before I dare to use it.
1226  # return unless i2c_smbus_read_byte_data($file,0x01) == 0x00;
1227  return (5);
1228}
1229
1230# $_[0]: A reference to the file descriptor to access this chip.
1231#        We may assume an i2c_set_slave_addr was already done.
1232# $_[1]: Address
1233# Returns: undef if not detected, (5) if detected.
1234# Registers used:
1235#   0x3e: Company ID
1236#   0x40: Configuration
1237#   0x48: Full I2C Address
1238# Note: Detection overrules a previous LM78 detection
1239sub adm9240_detect
1240{
1241  my ($file,$addr) = @_;
1242  return unless i2c_smbus_read_byte_data($file,0x3e) == 0x23;
1243  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
1244  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
1245 
1246  return (8);
1247}
1248
1249# $_[0]: Chip to detect (0 = ADM1021, 1 = MAX1617)
1250# $_[1]: A reference to the file descriptor to access this chip.
1251#        We may assume an i2c_set_slave_addr was already done.
1252# $_[2]: Address
1253# Returns: undef if not detected, (6) or (3) if detected.
1254# Registers used:
1255#   0xfe: Company ID
1256#   0x02: Status
1257# Note: Especially the Maxim has very bad detection; we give it a low
1258# confidence value.
1259sub adm1021_detect
1260{
1261  my $reg;
1262  my ($chip, $file,$addr) = @_;
1263  return if $chip == 0 and i2c_smbus_read_byte_data($file,0xfe) != 0x41;
1264  # The remaining things are flaky at best. Perhaps something can be done
1265  # with the fact that some registers are unreadable?
1266  return if (i2c_smbus_read_byte_data($file,0x02) & 0x03) != 0;
1267  if ($chip == 0) {
1268    return (6);
1269  } else {
1270    return (3);
1271  }
1272}
1273
1274# $_[0]: Address
1275# Returns: undef if not detected, (9) if detected.
1276# Note: It is already 99% certain this chip exists if we find the PCI
1277# entry. The exact address is encoded in PCI space.
1278sub sis5595_isa_detect
1279{
1280  my ($addr) = @_;
1281  my ($adapter,$try);
1282  my $found = 0;
1283  foreach $try (@pci_adapters) {
1284    if ($try->{procid} eq "Silicon Integrated Systems 85C503") {
1285      $found = 1;
1286      last;
1287    }
1288  }
1289  return if not $found;
1290
1291  $found = 0;
1292  foreach $adapter (@pci_list) {
1293    if ((defined($try->{vendid}) and 
1294         $try->{vendid} == $adapter->{vendid} and
1295         $try->{devid} == $adapter->{devid} and
1296         $try->{func} == $adapter->{func}) or
1297        (! defined($adapter->{vendid}) and
1298         $adapter->{desc} =~ /$try->{procid}/ and
1299         $try->{func} == $adapter->{func})) {
1300      $found = 1;
1301      last;
1302    }
1303  }
1304  return if not $found;
1305
1306  return (9);
1307}
1308
1309################
1310# MAIN PROGRAM #
1311################
1312
1313# $_[0]: reference to a list of chip hashes
1314sub print_chips_report 
1315{
1316  my ($listref) = @_;
1317  my $data;
1318 
1319  foreach $data (@$listref) {
1320    my $is_i2c = exists $data->{i2c_addr};
1321    my $is_isa = exists $data->{isa_addr};
1322    print "  * ";
1323    if ($is_i2c) {
1324      printf "Bus `%s' (%s)\n", $data->{i2c_adap}, $data->{i2c_algo};
1325      printf "    Busdriver `%s', I2C address 0x%02x", 
1326             $data->{i2c_driver}, $data->{i2c_addr};
1327      if (exists $data->{i2c_sub_addrs}) {
1328        print " (and";
1329        my $sub_addr;
1330        foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
1331          printf " 0x%02x",$sub_addr;
1332        }
1333        print ")"
1334      }
1335      print "\n";
1336    }
1337    if ($is_isa) {
1338      print "    " if  $is_i2c;
1339      if ($data->{isa_addr}) {
1340        printf "ISA bus address 0x%04x (Busdriver `i2c-isa')\n", 
1341               $data->{isa_addr};
1342      } else {
1343        printf "ISA bus, undetermined address (Busdriver `i2c-isa')\n"
1344      }
1345    }
1346    printf "    Chip `%s' (confidence: %d)\n",
1347           $data->{chipname},  $data->{conf};
1348  }
1349}
1350
1351# $_[0]: A reference to the file descriptor to access this chip.
1352#        We may assume an i2c_set_slave_addr was already done.
1353# $_[1]: Address
1354# Returns: undef if not detected, (5) if detected.
1355# Registers used:
1356#   0x00-0x63: PC-100 Data and Checksum
1357sub eeprom_detect
1358{
1359  my ($file,$addr) = @_;
1360  # Check the checksum for validity (only works for PC-100 DIMMs)
1361  my $checksum = 0;
1362  for (my $i = 0; $i <= 62; $i = $i + 1) {
1363    $checksum = $checksum + i2c_smbus_read_byte_data($file,$i);
1364  }
1365  $checksum=$checksum & 255;
1366  if (i2c_smbus_read_byte_data($file,63) == $checksum) {
1367        return (8);
1368  }
1369  # Even if checksum test fails, it still may be an eeprom
1370  return (1);
1371}
1372
1373################
1374# MAIN PROGRAM #
1375################
1376
1377sub main
1378{
1379  my (@adapters,$res,$did_adapter_detection,$detect_others,$adapter);
1380
1381  initialize_proc_pci;
1382  initialize_modules_list;
1383
1384  print " This program will help you to determine which I2C/SMBus modules you ",
1385        "need to\n",
1386        " load to use lm_sensors most effectively.\n";
1387  print " You need to have done a `make install', issued a `depmod -a' and ",
1388        "made sure\n",
1389        " `/etc/conf.modules' (or `/etc/modules.conf') contains the ",
1390        "appropriate\n",
1391        " module path before you can use some functions of this utility. ",
1392        "Read\n",
1393        " doc/modules for more information.\n";
1394  print " Also, you need to be `root', or at least have access to the ",
1395        "/dev/i2c-* files\n",
1396        " for some things. You can use prog/mkdev/mkdev.sh to create these ",
1397        "/dev files\n",
1398        " if you do not have them already.\n\n";
1399
1400  print " We can start with probing for (PCI) I2C or SMBus adapters.\n";
1401  print " You do not need any special privileges for this.\n";
1402  print " Do you want to probe now? (YES/no): ";
1403  @adapters = adapter_pci_detection
1404                        if ($did_adapter_detection = not <STDIN> =~ /\s*[Nn]/);
1405
1406  print "\n";
1407
1408  if (not $did_adapter_detection) {
1409    print " As you skipped adapter detection, we will only scan already ",
1410          "loaded adapter\n",
1411          " modules. You can still be prompted for non-detectable adapters.\n",
1412          " Do you want to? (yes/NO): ";
1413    $detect_others = <STDIN> =~ /^\s*[Yy]/;
1414  } elsif ($> != 0) {
1415    print " As you are not root, we can't load adapter modules. We will only ",
1416          "scan\n",
1417          " already loaded adapters.\n";
1418    $detect_others = 0;
1419  } else {
1420    print " We will now try to load each adapter module in turn.\n";
1421    foreach $adapter (@adapters) {
1422      if (contains $adapter, @modules_list) {
1423        print "Module `$adapter' already loaded.\n";
1424      } else {
1425        print "Load `$adapter'? (YES/no): ";
1426        unless (<STDIN> =~ /^\s*[Nn]/) {
1427          if (system ("modprobe", $adapter)) {
1428            print "Loading failed ($!)... skipping.\n";
1429          } else {
1430            print "Module loaded succesfully.\n";
1431          }
1432        }
1433      }
1434    }
1435    print " Do you now want to be prompted for non-detectable adapters? ",
1436          "(yes/NO): ";
1437    $detect_others = <STDIN> =~ /^\s*[Yy]/ ;
1438  }
1439
1440  if ($detect_others) {
1441    foreach $adapter (@undetectable_adapters) {
1442      print "Load `$adapter'? (YES/no): ";
1443      unless (<STDIN> =~ /^\s*[Nn]/) {
1444        if (system ("modprobe", $adapter)) {
1445          print "Loading failed ($!)... skipping.\n";
1446        } else {
1447          print "Module loaded succesfully.\n";
1448        }
1449      }
1450    }
1451  }
1452
1453  print " To continue, we need modules `i2c-proc' and `i2c-dev' to be ",
1454        "loaded.\n";
1455  if (contains "i2c-proc", @modules_list) {
1456    print "i2c-proc is already loaded.\n";
1457  } else {
1458    if ($> != 0) {
1459      print " i2c-proc is not loaded, and you are not root. I can't ",
1460            "continue.\n";
1461      exit;
1462    } else {
1463      print " i2c-proc is not loaded. May I load it now? (YES/no): ";
1464      if (<STDIN> =~ /^\s*[Nn]/) {
1465        print " Sorry, in that case I can't continue.\n";
1466        exit;
1467      } elsif (system "modprobe","i2c-proc") {
1468        print " Loading failed ($!), aborting.\n";
1469        exit;
1470      } else {
1471        print " Module loaded succesfully.\n";
1472      }
1473    }
1474  }
1475  if (contains "i2c-dev", @modules_list) {
1476    print "i2c-dev is already loaded.\n";
1477  } else {
1478    if ($> != 0) {
1479      print " i2c-dev is not loaded. As you are not root, we will just hope ",
1480            "you edited\n",
1481            " `/etc/conf.modules' (or `/etc/modules.conf') for automatic ",
1482            "loading of\n",
1483            " this module. If not, you won't be able to open any /dev/i2c-* ",
1484            "file.\n";
1485    } else {
1486      print " i2c-dev is not loaded. Do you want to load it now? (YES/no): ";
1487      if (<STDIN> =~ /^\s*[Nn]/) {
1488        print " Well, you will know best. We will just hope you edited ",
1489              "`/etc/conf.modules'\n",
1490              " (or `/etc/modules.conf') for automatic loading of this ",
1491              "module. If not,",
1492              " you won't be able to open any /dev/i2c-* file.\n";
1493      } elsif (system "modprobe","i2c-dev") {
1494        print " Loading failed ($!), aborting.\n";
1495        exit;
1496      } else {
1497        print " Module loaded succesfully.\n";
1498      }
1499    }
1500  }
1501
1502  print "\n We are now going to do the adapter probings. Some adapters may ",
1503        "hang halfway\n",
1504        " through; we can't really help that. Also, some chips will be double ",
1505        "detected;\n",
1506        " choose the one with the highest confidence value in that case.\n",
1507        " If you found that the adapter hung after probing a certain address, ",
1508        "you can\n",
1509        " specify that address to remain unprobed.\n";
1510
1511  my ($inp,@not_to_scan,$inp2);
1512  open INPUTFILE,"/proc/bus/i2c" or die "Couldn't open /proc/bus/i2c?!?";
1513  while (<INPUTFILE>) {
1514    print "\n";
1515    my ($dev_nr,$adap,$algo) = /^i2c-(\S+)\s+\S+\s+(.*?)\s*\t\s*(.*?)\s+$/;
1516    print "Next adapter: $adap ($algo)\n";
1517    print "Do you want to scan it? (YES/no/selectively): ";
1518   
1519    $inp = <STDIN>;
1520    @not_to_scan=();
1521    if ($inp =~ /^\s*[Ss]/) {
1522      print "Please enter one or more addresses not to scan. Separate them ",
1523            "with comma's.\n",
1524            "You can specify a range by using dashes. Addresses may be ",
1525            "decimal (like 54)\n",
1526            "or hexadecimal (like 0x33).\n",
1527            "Addresses: ";
1528      $inp2 = <STDIN>;
1529      chop $inp2;
1530      @not_to_scan = parse_not_to_scan 0,0x7f,$inp2;
1531    }
1532    scan_adapter $dev_nr, $adap, $algo, find_adapter_driver($adap,$algo),
1533                 \@not_to_scan   unless $inp =~ /^\s*[Nn]/;
1534  }
1535
1536  print "\n Some chips are also accessible through the ISA bus. ISA probes ",
1537        "are\n",
1538        " typically a bit more dangerous, as we have to write to I/O ports ",
1539        "to do\n",
1540        " this. ";
1541  if ($> != 0) {
1542    print "As you are not root, we shall skip this step.\n";
1543  } else {
1544    print " Do you want to scan the ISA bus? (YES/no): ";
1545    if (not <STDIN> =~ /^\s*[Nn]/) {
1546      initialize_ioports or die "Sorry, can't access /dev/port ($!)?!?";
1547      scan_isa_bus;
1548    }
1549  }
1550
1551  print "\n Now follows a summary of the probes I have just done.\n";
1552  my ($chip,$data);
1553  foreach $chip (@chips_detected) {
1554    print "\nDriver `$$chip{driver}' ";
1555    if (@{$$chip{detected}}) {
1556      if (@{$$chip{misdetected}}) {
1557        print "(should be inserted but causes problems):\n";
1558      } else {
1559        print "(should be inserted):\n";
1560      }
1561    } else {
1562      if (@{$$chip{misdetected}}) {
1563        print "(may not be inserted):\n";
1564      } else {
1565        print "(should not be inserted, but is harmless):\n";
1566      }
1567    }
1568    if (@{$$chip{detected}}) {
1569      print "  Detects correctly:\n";
1570      print_chips_report $chip->{detected};
1571    }
1572    if (@{$$chip{misdetected}}) {
1573      print "  Misdetects:\n";
1574      print_chips_report $chip->{misdetected};
1575    }
1576  }
1577}
1578
1579main;
Note: See TracBrowser for help on using the browser.