root/lm-sensors/trunk/prog/detect/detect.pl @ 265

Revision 265, 43.1 KB (checked in by frodo, 15 years ago)

ISA detection is completed for LM7x and W8378xx

No alias detection (ie. detection of chips connected to both ISA and I2C bus)
is done yet; but all hooks are in.

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