2000-07-02 18:11:31 +00:00
#!/usr/bin/perl -w
1999-02-06 01:04:57 +00:00
1999-02-17 20:55:23 +00:00
#
1999-04-14 20:05:16 +00:00
# sensors-detect - Detect PCI bus and chips
2002-04-02 02:08:56 +00:00
# Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>
1999-02-17 20:55:23 +00:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
1999-02-25 12:23:04 +00:00
# TODO: Better handling of chips with several addresses
1999-02-17 20:55:23 +00:00
# A Perl wizard really ought to look upon this; the PCI and I2C stuff should
# each be put in a separate file, using modules and packages. That is beyond
# me.
1999-03-10 01:17:15 +00:00
require 5.004;
1999-02-06 01:04:57 +00:00
use strict;
2002-11-08 09:38:29 +00:00
use Fcntl;
use POSIX;
1999-02-06 01:04:57 +00:00
2003-08-05 09:08:38 +00:00
# Just in case a root user doesn't have /sbin in his/her path for some reason
# (was seen once)
2004-01-18 07:26:37 +00:00
$ENV{PATH} = '/sbin:'.$ENV{PATH}
2003-08-05 09:08:38 +00:00
unless $ENV{PATH} =~ m,(^|:)/sbin/?(:|$),;
2004-01-18 07:26:37 +00:00
# Same for /usr/local/sbin since we need i2cdetect which is installed there
# by default (reported by Lennard Klein)
$ENV{PATH} = '/usr/local/sbin:'.$ENV{PATH}
unless $ENV{PATH} =~ m,(^|:)/usr/local/sbin/?(:|$),;
2003-08-05 09:08:38 +00:00
1999-02-17 20:55:23 +00:00
#########################
# CONSTANT DECLARATIONS #
#########################
2003-11-29 19:37:34 +00:00
use vars qw(@pci_adapters @chip_ids @superio_ids @undetectable_adapters);
2002-08-11 21:53:21 +00:00
@undetectable_adapters = ( 'i2c-elektor', 'i2c-elv', 'i2c-philips-par',
'i2c-velleman' );
1999-02-18 00:19:19 +00:00
1999-02-17 20:55:23 +00:00
# This is the list of SMBus or I2C adapters we recognize by their PCI
# signature. This is an easy and fast way to determine which SMBus or I2C
# adapters should be present.
2001-09-19 15:57:06 +00:00
# Each entry must have a vendid (Vendor ID), devid (Device ID), func (PCI
1999-02-17 20:55:23 +00:00
# Function) and procid (string as appears in /proc/pci; see linux/driver/pci,
2003-11-09 02:19:35 +00:00
# either pci.c or oldproc.c). If no driver is written yet, set the
# driver (Driver Name) field to "to-be-written".
# The match (Match Description) field should
1999-02-23 14:14:32 +00:00
# contain a function which returns zero if its two parameter matches
1999-02-19 18:11:03 +00:00
# the text as it would appear in /proc/bus/i2c.
1999-02-17 20:55:23 +00:00
@pci_adapters = (
{
vendid => 0x8086,
devid => 0x7113,
func => 3,
procid => "Intel 82371AB PIIX4 ACPI",
1999-02-19 18:11:03 +00:00
driver => "i2c-piix4",
2001-09-19 15:57:06 +00:00
match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
} ,
{
vendid => 0x8086,
devid => 0x719b,
func => 3,
procid => "Intel 82443MX Mobile",
driver => "i2c-piix4",
match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
1999-02-17 20:55:23 +00:00
} ,
1999-08-16 01:42:28 +00:00
{
vendid => 0x8086,
devid => 0x2413,
func => 3,
procid => "Intel 82801AA ICH",
driver => "i2c-i801",
2000-03-14 23:55:39 +00:00
match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
1999-08-16 01:42:28 +00:00
} ,
{
vendid => 0x8086,
devid => 0x2423,
func => 3,
procid => "Intel 82801AB ICH0",
driver => "i2c-i801",
2000-03-15 02:45:51 +00:00
match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
1999-08-16 01:42:28 +00:00
} ,
2000-07-21 23:52:28 +00:00
{
vendid => 0x8086,
devid => 0x2443,
func => 3,
procid => "Intel 82801BA ICH2",
driver => "i2c-i801",
match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
2001-10-07 02:18:25 +00:00
} ,
{
vendid => 0x8086,
devid => 0x2483,
func => 3,
procid => "Intel 82801CA/CAM ICH3",
driver => "i2c-i801",
match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
2000-07-21 23:52:28 +00:00
} ,
2002-06-07 02:56:52 +00:00
{
vendid => 0x8086,
devid => 0x24C3,
func => 3,
2002-06-12 22:49:43 +00:00
procid => "Intel 82801DB ICH4",
2002-06-07 02:56:52 +00:00
driver => "i2c-i801",
match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
} ,
2003-06-08 21:05:58 +00:00
{
vendid => 0x8086,
devid => 0x24D3,
func => 3,
procid => "Intel 82801EB ICH5",
driver => "i2c-i801",
match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
} ,
1999-02-17 20:55:23 +00:00
{
vendid => 0x1106,
devid => 0x3040,
func => 3,
2001-10-06 22:20:41 +00:00
procid => "VIA Technologies VT82C586B Apollo ACPI",
1999-02-19 18:11:03 +00:00
driver => "i2c-via",
match => sub { $_[0] =~ /^VIA i2c/ },
1999-02-17 20:55:23 +00:00
} ,
1999-07-27 16:51:00 +00:00
{
vendid => 0x1106,
devid => 0x3050,
func => 3,
2001-10-06 22:20:41 +00:00
procid => "VIA Technologies VT82C596 Apollo ACPI",
1999-07-27 16:51:00 +00:00
driver => "i2c-viapro",
2001-10-06 22:20:41 +00:00
match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
1999-07-27 16:51:00 +00:00
} ,
2000-10-12 02:57:18 +00:00
{
vendid => 0x1106,
devid => 0x3051,
func => 3,
2001-10-06 22:20:41 +00:00
procid => "VIA Technologies VT82C596B ACPI",
2000-10-12 02:57:18 +00:00
driver => "i2c-viapro",
2001-10-06 22:20:41 +00:00
match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
2000-10-12 02:57:18 +00:00
} ,
1999-07-27 16:51:00 +00:00
{
vendid => 0x1106,
devid => 0x3057,
func => 4,
2001-10-06 22:20:41 +00:00
procid => "VIA Technologies VT82C686 Apollo ACPI",
1999-07-27 16:51:00 +00:00
driver => "i2c-viapro",
2001-10-06 22:20:41 +00:00
match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
1999-07-27 16:51:00 +00:00
} ,
2001-09-15 13:25:43 +00:00
{
vendid => 0x1106,
devid => 0x3074,
func => 0,
2001-10-06 22:20:41 +00:00
procid => "VIA Technologies VT8233 VLink South Bridge",
driver => "i2c-viapro",
match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
2001-09-15 13:25:43 +00:00
} ,
2002-03-24 01:57:46 +00:00
{
vendid => 0x1106,
devid => 0x3147,
func => 0,
procid => "VIA Technologies VT8233A South Bridge",
driver => "i2c-viapro",
match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
} ,
2002-11-10 20:51:43 +00:00
{
vendid => 0x1106,
devid => 0x3177,
func => 0,
procid => "VIA Technologies VT8233A/8235 South Bridge",
driver => "i2c-viapro",
match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
} ,
2003-11-29 17:49:35 +00:00
{
vendid => 0x1106,
devid => 0x3227,
func => 0,
procid => "VIA Technologies VT8237 South Bridge",
driver => "i2c-viapro",
match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
} ,
2002-03-14 00:20:25 +00:00
{
vendid => 0x1106,
2002-05-27 20:54:46 +00:00
devid => 0x8235,
func => 4,
2002-03-14 00:20:25 +00:00
procid => "VIA Technologies VT8231 South Bridge",
2002-05-27 20:54:46 +00:00
driver => "i2c-viapro",
match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
2002-03-14 00:20:25 +00:00
} ,
1999-02-17 20:55:23 +00:00
{
vendid => 0x1039,
devid => 0x0008,
func => 0,
1999-12-02 02:05:25 +00:00
procid => "Silicon Integrated Systems SIS5595",
driver => "i2c-sis5595",
match => sub { $_[0] =~ /^SMBus SIS5595 adapter at [0-9,a-f]{4}/ },
1999-02-17 20:55:23 +00:00
} ,
2003-05-31 22:22:16 +00:00
{
vendid => 0x1039,
devid => 0x0018,
func => 0,
procid => "Silicon Integrated Systems 85C503/5513 (LPC Bridge)",
driver => "i2c-sis645",
match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
} ,
2001-07-29 23:19:39 +00:00
{
vendid => 0x1039,
devid => 0x5597,
func => 0,
procid => "Silicon Integrated Systems SIS5581/5582/5597/5598 (To be written - Do not use 5595 drivers)",
2002-09-01 15:47:21 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2001-07-29 23:19:39 +00:00
} ,
{
vendid => 0x1039,
devid => 0x5598,
func => 0,
procid => "Silicon Integrated Systems SIS5598 (To be written - Do not use 5595 drivers)",
2002-09-01 15:47:21 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2001-07-29 23:19:39 +00:00
} ,
{
vendid => 0x1039,
devid => 0x0540,
func => 0,
procid => "Silicon Integrated Systems SIS540 (To be written - Do not use 5595 drivers)",
2002-09-01 15:47:21 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2001-07-29 23:19:39 +00:00
} ,
{
vendid => 0x1039,
devid => 0x0630,
func => 0,
2002-08-28 19:15:43 +00:00
procid => "Silicon Integrated Systems SIS630",
driver => "i2c-sis630",
match => sub { $_[0] =~ /^SMBus SIS630 adapter at [0-9,a-f]{4}/ },
2001-07-29 23:19:39 +00:00
} ,
2002-09-01 20:22:51 +00:00
{
vendid => 0x1039,
devid => 0x0645,
func => 0,
procid => "Silicon Integrated Systems SIS645",
driver => "i2c-sis645",
match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
} ,
2002-09-17 06:18:40 +00:00
{
vendid => 0x1039,
devid => 0x0646,
func => 0,
procid => "Silicon Integrated Systems SIS645DX",
driver => "i2c-sis645",
match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
} ,
2003-01-20 06:07:11 +00:00
{
vendid => 0x1039,
devid => 0x0648,
func => 0,
procid => "Silicon Integrated Systems SIS648",
driver => "i2c-sis645",
match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
} ,
2002-09-26 01:45:16 +00:00
{
vendid => 0x1039,
devid => 0x0650,
func => 0,
procid => "Silicon Integrated Systems SIS650",
driver => "i2c-sis645",
match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
} ,
2003-05-31 20:23:13 +00:00
{
vendid => 0x1039,
devid => 0x0651,
func => 0,
procid => "Silicon Integrated Systems SIS651",
driver => "i2c-sis645",
match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
} ,
2002-09-17 06:18:40 +00:00
{
vendid => 0x1039,
devid => 0x0735,
func => 0,
procid => "Silicon Integrated Systems SIS735",
driver => "i2c-sis645",
match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
} ,
2003-05-31 22:22:16 +00:00
{
vendid => 0x1039,
devid => 0x0745,
func => 0,
procid => "Silicon Integrated Systems SIS745",
driver => "i2c-sis645",
match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
} ,
2003-06-17 05:30:31 +00:00
{
vendid => 0x1039,
devid => 0x0746,
func => 0,
procid => "Silicon Integrated Systems SIS746",
driver => "i2c-sis645",
match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
} ,
2001-07-29 23:19:39 +00:00
{
vendid => 0x1039,
devid => 0x0730,
func => 0,
2002-09-18 21:59:16 +00:00
procid => "Silicon Integrated Systems SIS730",
driver => "i2c-sis630",
match => sub { $_[0] =~ /^SMBus SIS630 adapter at [0-9,a-f]{4}/ },
2001-07-29 23:19:39 +00:00
} ,
2001-09-01 18:12:00 +00:00
#
# Both Ali chips below have same PCI ID. Can't be helped. Only one should load.
#
1999-02-17 20:55:23 +00:00
{
vendid => 0x10b9,
devid => 0x7101,
2001-12-31 17:32:54 +00:00
func => 0,
2001-09-01 18:12:00 +00:00
procid => "Acer Labs 1533/1543",
1999-02-19 18:11:03 +00:00
driver => "i2c-ali15x3",
2001-09-01 18:12:00 +00:00
match => sub { $_[0] =~ /^SMBus ALI15X3 adapter at/ },
},
{
vendid => 0x10b9,
devid => 0x7101,
2001-12-31 17:32:54 +00:00
func => 0,
2001-09-01 18:12:00 +00:00
procid => "Acer Labs 1535",
driver => "i2c-ali1535",
match => sub { $_[0] =~ /^SMBus ALI1535 adapter at/ },
1999-04-29 19:18:39 +00:00
},
1999-04-28 18:18:12 +00:00
{
vendid => 0x106b,
devid => 0x000e,
func => 0,
procid => "Apple Computer Inc. Hydra Mac I/O",
driver => "i2c-hydra",
match => sub { $_[0] =~ /^Hydra i2c/ },
},
1999-11-14 17:29:50 +00:00
{
vendid => 0x1022,
devid => 0x740b,
func => 3,
procid => "AMD-756 Athlon ACPI",
1999-12-01 00:33:33 +00:00
driver => "i2c-amd756",
2002-05-02 14:44:31 +00:00
match => sub { $_[0] =~ /^SMBus AMD756 adapter at [0-9,a-f]{4}/ },
2001-08-03 01:25:11 +00:00
},
{
vendid => 0x1022,
devid => 0x7413,
func => 3,
procid => "AMD-766 Athlon ACPI",
driver => "i2c-amd756",
2002-05-02 14:44:31 +00:00
match => sub { $_[0] =~ /^SMBus AMD766 adapter at [0-9,a-f]{4}/ },
1999-11-14 17:29:50 +00:00
},
2001-12-29 00:20:48 +00:00
{
vendid => 0x1022,
devid => 0x7443,
func => 3,
procid => "AMD-768 System Management",
driver => "i2c-amd756",
2002-05-02 14:44:31 +00:00
match => sub { $_[0] =~ /^SMBus AMD768 adapter at [0-9,a-f]{4}/ },
2001-12-29 00:20:48 +00:00
},
2002-11-17 19:44:46 +00:00
{
vendid => 0x1022,
devid => 0x746b,
func => 3,
procid => "AMD-8111 ACPI",
driver => "i2c-amd756",
match => sub { $_[0] =~ /^SMBus AMD8111 adapter at [0-9,a-f]{4}/ },
},
{
vendid => 0x1022,
devid => 0x746a,
func => 2,
procid => "AMD-8111 SMBus 2.0",
driver => "i2c-amd8111",
match => sub { $_[0] =~ /^SMBus2 AMD8111 adapter at [0-9,a-f]{4}/ },
},
1999-12-29 23:10:48 +00:00
{
vendid => 0x102b,
devid => 0x0519,
func => 0,
procid => "MGA 2064W [Millennium]",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
},
{
vendid => 0x102b,
devid => 0x051a,
func => 0,
procid => "MGA 1064SG [Mystique]",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
},
{
vendid => 0x102b,
devid => 0x051b,
func => 0,
procid => "MGA 2164W [Millennium II]",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
},
{
vendid => 0x102b,
devid => 0x051e,
func => 0,
procid => "MGA 1064SG [Mystique] AGP",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
},
{
vendid => 0x102b,
devid => 0x051f,
func => 0,
procid => "MGA 2164W [Millennium II] AGP",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
},
{
vendid => 0x102b,
devid => 0x1000,
func => 0,
procid => "MGA G100 [Productiva]",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
},
{
vendid => 0x102b,
devid => 0x1001,
func => 0,
procid => "MGA G100 [Productiva] AGP",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
},
{
vendid => 0x102b,
devid => 0x0520,
func => 0,
procid => "MGA G200",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
},
{
vendid => 0x102b,
devid => 0x0521,
func => 0,
procid => "MGA G200 AGP",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
},
{
vendid => 0x102b,
devid => 0x0525,
func => 0,
procid => "MGA G400 AGP",
2003-07-17 08:50:05 +00:00
driver => "i2c-matroxfb",
1999-12-29 23:10:48 +00:00
match => sub { $_[0] =~ /^(DDC,MAVEN):fb[0-9]{1,2}/ },
},
2000-01-15 18:55:55 +00:00
{
vendid => 0x121a,
devid => 0x0005,
func => 0,
procid => "3Dfx Voodoo3",
driver => "i2c-voodoo3",
2000-01-30 01:15:29 +00:00
match => sub { $_[0] =~ /Banshee adapter/ },
2000-01-15 18:55:55 +00:00
},
{
vendid => 0x121a,
devid => 0x0003,
func => 0,
procid => "3Dfx Voodoo Banshee",
driver => "i2c-voodoo3",
2000-01-30 01:15:29 +00:00
match => sub { $_[0] =~ /Banshee adapter/ },
2000-01-15 18:55:55 +00:00
},
2000-02-07 02:03:33 +00:00
{
vendid => 0x8086,
devid => 0x7121,
func => 0,
procid => "Intel 82810 GMCH",
driver => "i2c-i810",
match => sub { $_[0] =~ /^I810/ },
} ,
{
vendid => 0x8086,
devid => 0x7123,
func => 0,
procid => "Intel 82810-DC100 GMCH",
driver => "i2c-i810",
2000-09-02 19:25:29 +00:00
match => sub { $_[0] =~ /^I810/ },
} ,
2001-12-04 00:32:59 +00:00
{
vendid => 0x8086,
devid => 0x7125,
func => 0,
procid => "Intel 82810E GMCH",
driver => "i2c-i810",
match => sub { $_[0] =~ /^I810/ },
} ,
2000-09-02 19:25:29 +00:00
{
vendid => 0x8086,
devid => 0x1132,
func => 0,
procid => "Intel 82815 GMCH",
driver => "i2c-i810",
2000-02-07 02:03:33 +00:00
match => sub { $_[0] =~ /^I810/ },
} ,
2000-09-04 01:50:55 +00:00
{
vendid => 0x12d2,
devid => 0x0018,
func => 0,
procid => "RIVA 128",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0020,
func => 0,
procid => "RIVA TNT",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0028,
func => 0,
procid => "RIVA TNT2",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0029,
func => 0,
procid => "RIVA UTNT2",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x002c,
func => 0,
procid => "RIVA VTNT2",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x002d,
func => 0,
procid => "RIVA UVTNT2",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x00a0,
func => 0,
procid => "RIVA ITNT2",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0100,
func => 0,
2001-11-19 17:44:27 +00:00
procid => "GeForce SDR",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0101,
func => 0,
procid => "GeForce DDR",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0102,
func => 0,
procid => "Quadro",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0150,
func => 0,
2001-11-19 17:44:27 +00:00
procid => "GeForce2 GTS",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2001-11-19 17:44:27 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0110,
func => 0,
procid => "GeForce2 MX",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2001-11-19 17:44:27 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0111,
func => 0,
procid => "GeForce2 MX2",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2001-11-19 17:44:27 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0113,
func => 0,
procid => "Quadro2 MXR",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2001-11-19 17:44:27 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0151,
func => 0,
procid => "GeForce2 GTS2",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2001-11-19 17:44:27 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0152,
func => 0,
procid => "GeForce2 Ultra",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2001-11-19 17:44:27 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
{
vendid => 0x10de,
devid => 0x0153,
func => 0,
procid => "Quadro2 Pro",
2003-07-17 08:50:05 +00:00
driver => "rivatv",
2000-09-04 01:50:55 +00:00
match => sub { $_[0] =~ /^NVIDIA display/ },
} ,
2002-02-16 15:07:45 +00:00
{
vendid => 0x10de,
devid => 0x01b4,
func => 1,
procid => "nVidia nForce SMBus",
2002-05-01 23:28:09 +00:00
driver => "i2c-amd756",
2002-05-02 14:44:31 +00:00
match => sub { $_[0] =~ /^SMBus nVidia nForce adapter at [0-9,a-f]{4}/ },
2002-02-16 15:07:45 +00:00
} ,
2003-06-05 09:16:33 +00:00
{
vendid => 0x10de,
devid => 0x0064,
func => 1,
procid => "nVidia Corporation nForce2 SMBus (MCP)",
driver => "i2c-nforce2",
2003-06-07 08:34:25 +00:00
match => sub { $_[0] =~ /^SMBus nForce2 adapter at / },
2003-06-05 09:16:33 +00:00
} ,
2000-11-29 03:25:24 +00:00
{
vendid => 0x1166,
devid => 0x0200,
func => 0,
2001-09-19 15:57:06 +00:00
procid => "ServerWorks OSB4 South Bridge",
2000-12-27 20:08:52 +00:00
driver => "i2c-piix4",
2001-09-19 15:57:06 +00:00
match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
2000-11-29 03:25:24 +00:00
} ,
2001-02-04 23:24:03 +00:00
{
vendid => 0x1055,
devid => 0x9463,
func => 0,
procid => "SMSC Victory66 South Bridge",
driver => "i2c-piix4",
2001-09-19 15:57:06 +00:00
match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
2001-02-04 23:24:03 +00:00
} ,
2001-07-31 17:01:14 +00:00
{
vendid => 0x1166,
devid => 0x0201,
func => 0,
2001-09-19 15:57:06 +00:00
procid => "ServerWorks CSB5 South Bridge",
2001-07-31 17:01:14 +00:00
driver => "i2c-piix4",
2001-09-19 15:57:06 +00:00
match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
2001-07-31 17:01:14 +00:00
} ,
2003-10-27 03:03:47 +00:00
{
vendid => 0x1166,
devid => 0x0203,
func => 0,
procid => "ServerWorks CSB6 South Bridge",
driver => "i2c-piix4",
match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
} ,
2001-09-29 19:02:51 +00:00
{
vendid => 0x1283,
devid => 0x8172,
func => 0,
procid => "ITE 8172G MIPS/SH4 Support Chip",
driver => "i2c-adap-ite",
match => sub { $_[0] =~ /^ITE IIC adapter/ },
} ,
2002-04-02 02:08:56 +00:00
{
vendid => 0x5333,
devid => 0x8A20,
func => 0,
procid => "S3 Savage 3D",
2002-04-28 04:14:31 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2002-04-02 02:08:56 +00:00
} ,
{
vendid => 0x5333,
devid => 0x8A21,
func => 0,
procid => "S3 Savage 3D MV",
2002-04-28 04:14:31 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2002-04-02 02:08:56 +00:00
} ,
{
vendid => 0x5333,
devid => 0x8A22,
func => 0,
procid => "S3 Savage 4",
driver => "i2c-savage4",
match => sub { $_[0] =~ /Savage4 adapter/ },
} ,
{
vendid => 0x5333,
devid => 0x9102,
func => 0,
procid => "S3 Savage 2000",
driver => "i2c-savage4",
match => sub { $_[0] =~ /Savage4 adapter/ },
} ,
{
vendid => 0x5333,
devid => 0x8A25,
func => 0,
procid => "S3 ProSavage PM",
2002-04-28 04:14:31 +00:00
driver => "to-be-written",
2002-04-02 02:08:56 +00:00
match => sub { $_[0] =~ /^dontmatchthis/ },
} ,
{
vendid => 0x5333,
devid => 0x8A26,
func => 0,
procid => "S3 ProSavage KM",
2002-04-28 04:14:31 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2002-04-02 02:08:56 +00:00
} ,
{
vendid => 0x5333,
devid => 0x8C10,
func => 0,
procid => "S3 Savage MX MV",
2002-04-28 04:14:31 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2002-04-02 02:08:56 +00:00
} ,
{
vendid => 0x5333,
devid => 0x8C11,
func => 0,
procid => "S3 Savage MX",
2002-04-28 04:14:31 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2002-04-02 02:08:56 +00:00
} ,
{
vendid => 0x5333,
devid => 0x8C12,
func => 0,
procid => "S3 Savage IX MV",
2002-04-28 04:14:31 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2002-04-02 02:08:56 +00:00
} ,
{
vendid => 0x5333,
devid => 0x8C13,
func => 0,
procid => "S3 Savage IX",
2002-04-28 04:14:31 +00:00
driver => "to-be-written",
2003-07-17 08:50:05 +00:00
match => sub { 0 },
2002-04-02 02:08:56 +00:00
} ,
1999-02-17 20:55:23 +00:00
);
2000-10-18 00:34:07 +00:00
use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect
lm75_detect lm80_detect w83781d_detect w83781d_alias_detect
adm1025_detect w83781d_isa_detect gl518sm_detect gl520sm_detect
adm9240_detect adm1021_detect sis5595_isa_detect eeprom_detect
via686a_isa_detect adm1022_detect ltc1710_detect gl525sm_detect
lm87_detect ite_detect ite_isa_detect ite_alias_detect
2001-12-04 00:32:59 +00:00
ddcmonitor_detect ds1621_detect adm1024_detect fscpos_detect
2003-10-15 17:46:46 +00:00
fscscy_detect arp_detect ipmi_kcs_detect
2003-06-08 21:33:39 +00:00
ipmi_smic_detect via8231_isa_detect lm85_detect smartbatt_detect
2003-07-18 08:06:05 +00:00
adm1026_detect w83l785ts_detect lm83_detect lm90_detect
2003-09-27 08:19:20 +00:00
saa1064_detect w83l784r_detect mozart_detect max6650_detect
2003-11-08 11:13:46 +00:00
fscher_detect adm1029_detect adm1031_detect);
1999-02-17 20:55:23 +00:00
1999-02-18 00:19:19 +00:00
# This is a list of all recognized chips.
1999-02-22 20:40:16 +00:00
# Each entry must have the following fields:
# name: The full chip name
2003-11-09 02:19:35 +00:00
# driver: The driver name (without .o extension). Put in exactly
# "to-be-written" if it is not yet available.
1999-02-22 20:40:16 +00:00
# i2c_addrs (optional): For I2C chips, the range of valid I2C addresses to
1999-08-28 19:10:27 +00:00
# probe. Recommend avoiding 0x69 because of clock chips.
1999-03-23 21:48:41 +00:00
# i2c_driver_addrs (optional): For I2C chips, the range of valid I2C
# addresses probed by the kernel driver. Strictly optional.
1999-02-22 20:40:16 +00:00
# i2c_detect (optional): For I2C chips, the function to call to detect
# this chip. The function should take two parameters: an open file
# descriptor to access the bus, and the I2C address to probe.
1999-02-23 14:14:32 +00:00
# isa_addrs (optional): For ISA chips, the range of valid port addresses to
# probe.
1999-03-23 21:48:41 +00:00
# isa_driver_addrs (optional): For ISA chips, the range of valid ISA
# addresses probed by the kernel driver. Strictly optional.
1999-02-22 20:40:16 +00:00
# isa_detect (optional): For ISA chips, the function to call to detect
1999-02-23 14:14:32 +00:00
# this chip. The function should take one parameter: the ISA address
# to probe.
1999-02-23 20:28:05 +00:00
# alias_detect (optional): For chips which can be both on the ISA and the
# I2C bus, a function which detectes whether two entries are the same.
# The function should take three parameters: The ISA address, the
# I2C bus number, and the I2C address.
1999-02-18 00:19:19 +00:00
@chip_ids = (
2000-10-18 00:34:07 +00:00
{
name => "Myson MTP008",
driver => "mtp008",
i2c_addrs => [0x2c..0x2e],
i2c_detect => sub { mtp008_detect @_},
} ,
1999-02-18 00:19:19 +00:00
{
1999-08-22 17:52:38 +00:00
name => "National Semiconductor LM78",
1999-02-18 00:19:19 +00:00
driver => "lm78",
2002-09-01 02:26:26 +00:00
i2c_addrs => [0x20..0x2f],
1999-02-18 18:09:14 +00:00
i2c_detect => sub { lm78_detect 0, @_},
1999-02-23 14:14:32 +00:00
isa_addrs => [0x290],
isa_detect => sub { lm78_isa_detect 0, @_ },
1999-02-23 20:28:05 +00:00
alias_detect => sub { lm78_alias_detect 0, @_ },
1999-02-18 00:19:19 +00:00
} ,
{
1999-08-22 17:52:38 +00:00
name => "National Semiconductor LM78-J",
1999-12-30 02:07:24 +00:00
driver => "lm78",
2002-09-01 02:26:26 +00:00
i2c_addrs => [0x20..0x2f],
1999-02-18 18:09:14 +00:00
i2c_detect => sub { lm78_detect 1, @_ },
1999-02-23 14:14:32 +00:00
isa_addrs => [0x290],
isa_detect => sub { lm78_isa_detect 1, @_ },
1999-02-23 20:28:05 +00:00
alias_detect => sub { lm78_alias_detect 1, @_ },
1999-02-18 00:19:19 +00:00
} ,
{
1999-08-22 17:52:38 +00:00
name => "National Semiconductor LM79",
1999-02-18 00:19:19 +00:00
driver => "lm78",
2002-09-01 02:26:26 +00:00
i2c_addrs => [0x20..0x2f],
1999-02-18 18:09:14 +00:00
i2c_detect => sub { lm78_detect 2, @_ },
1999-02-23 14:14:32 +00:00
isa_addrs => [0x290],
isa_detect => sub { lm78_isa_detect 2, @_ },
1999-02-23 20:28:05 +00:00
alias_detect => sub { lm78_alias_detect 2, @_ },
1999-02-18 00:19:19 +00:00
} ,
{
1999-08-22 17:52:38 +00:00
name => "National Semiconductor LM75",
1999-02-18 00:19:19 +00:00
driver => "lm75",
1999-02-18 18:09:14 +00:00
i2c_addrs => [0x48..0x4f],
i2c_detect => sub { lm75_detect @_},
1999-02-18 00:19:19 +00:00
} ,
{
1999-08-22 17:52:38 +00:00
name => "National Semiconductor LM80",
1999-02-18 00:19:19 +00:00
driver => "lm80",
1999-02-18 18:09:14 +00:00
i2c_addrs => [0x28..0x2f],
i2c_detect => sub { lm80_detect @_} ,
1999-02-18 21:14:48 +00:00
},
2002-06-30 20:34:35 +00:00
{
name => "National Semiconductor LM85",
2003-03-17 02:34:10 +00:00
driver => "lm85",
2002-06-30 20:34:35 +00:00
i2c_addrs => [0x2c..0x2e],
2003-03-17 02:34:10 +00:00
i2c_detect => sub { lm85_detect 0x01, @_},
},
{
name => "Analog Devices ADM1027 or ADT7463",
driver => "lm85",
i2c_addrs => [0x2c..0x2e],
i2c_detect => sub { lm85_detect 0x41, @_},
2002-06-30 20:34:35 +00:00
},
2003-05-31 00:24:07 +00:00
{
name => "SMSC EMC6D100 and EMC6D101",
driver => "lm85",
i2c_addrs => [0x2c..0x2e],
i2c_detect => sub { lm85_detect 0x5c, @_},
},
2000-07-25 01:07:00 +00:00
{
name => "National Semiconductor LM87",
2000-09-23 01:42:32 +00:00
driver => "lm87",
2000-07-25 01:07:00 +00:00
i2c_addrs => [0x2c..0x2e],
i2c_detect => sub { lm87_detect @_} ,
},
1999-02-18 21:14:48 +00:00
{
name => "Winbond W83781D",
driver => "w83781d",
i2c_detect => sub { w83781d_detect 0, @_},
2002-09-01 02:26:26 +00:00
i2c_addrs => [0x20..0x2f],
1999-02-23 14:14:32 +00:00
isa_addrs => [0x290],
isa_detect => sub { w83781d_isa_detect 0, @_ },
1999-02-23 20:28:05 +00:00
alias_detect => sub { w83781d_alias_detect 0, @_ },
1999-02-18 21:14:48 +00:00
} ,
1999-02-22 18:20:35 +00:00
{
name => "Winbond W83782D",
driver => "w83781d",
2002-09-01 02:26:26 +00:00
i2c_addrs => [0x20..0x2f],
1999-02-22 18:20:35 +00:00
i2c_detect => sub { w83781d_detect 1, @_},
1999-08-15 20:23:31 +00:00
isa_addrs => [0x290],
isa_detect => sub { w83781d_isa_detect 1, @_ },
alias_detect => sub { w83781d_alias_detect 1, @_ },
1999-02-22 18:20:35 +00:00
} ,
{
name => "Winbond W83783S",
driver => "w83781d",
2003-07-26 09:37:12 +00:00
i2c_addrs => [0x2d],
1999-02-22 18:20:35 +00:00
i2c_detect => sub { w83781d_detect 2, @_},
1999-08-15 20:23:31 +00:00
} ,
2003-06-10 03:01:31 +00:00
{
name => "Winbond W83791D",
driver => "w83781d",
2003-07-26 09:37:12 +00:00
i2c_addrs => [0x2c..0x2f],
2003-06-10 03:01:31 +00:00
i2c_detect => sub { w83781d_detect 7, @_},
} ,
1999-08-15 20:23:31 +00:00
{
name => "Winbond W83627HF",
driver => "w83781d",
2002-09-01 02:26:26 +00:00
i2c_addrs => [0x20..0x2f],
1999-08-15 20:23:31 +00:00
i2c_detect => sub { w83781d_detect 3, @_},
1999-02-23 14:14:32 +00:00
isa_addrs => [0x290],
1999-08-15 20:23:31 +00:00
isa_detect => sub { w83781d_isa_detect 3, @_ },
alias_detect => sub { w83781d_alias_detect 3, @_ },
1999-02-22 18:20:35 +00:00
} ,
1999-10-30 21:26:21 +00:00
{
2003-07-26 09:37:12 +00:00
name => "Asus AS99127F (rev.1)",
1999-10-30 21:26:21 +00:00
driver => "w83781d",
2003-07-26 09:37:12 +00:00
i2c_addrs => [0x28..0x2f],
1999-10-30 21:26:21 +00:00
i2c_detect => sub { w83781d_detect 4, @_},
} ,
2003-07-26 09:37:12 +00:00
{
name => "Asus AS99127F (rev.2)",
driver => "w83781d",
i2c_addrs => [0x28..0x2f],
i2c_detect => sub { w83781d_detect 5, @_},
} ,
{
name => "Asus ASB100 Bach",
2003-12-09 06:17:04 +00:00
driver => "asb100",
2003-07-26 09:37:12 +00:00
i2c_addrs => [0x28..0x2f],
i2c_detect => sub { w83781d_detect 6, @_},
} ,
2003-07-27 10:37:32 +00:00
{
name => "Asus ASM58 Mozart-2",
driver => "to-be-written",
i2c_addrs => [0x77],
i2c_detect => sub { mozart_detect 0, @_},
} ,
{
name => "Asus AS2K129R Mozart-2",
driver => "to-be-written",
i2c_addrs => [0x77],
i2c_detect => sub { mozart_detect 1, @_},
} ,
{
name => "Asus Mozart-2",
driver => "to-be-written",
i2c_addrs => [0x77],
i2c_detect => sub { mozart_detect 2, @_},
} ,
2001-12-04 00:32:59 +00:00
{
name => "Winbond W83L784R/AR",
2002-08-22 00:58:57 +00:00
driver => "to-be-written",
2003-07-26 09:37:12 +00:00
i2c_addrs => [0x2d],
i2c_detect => sub { w83l784r_detect 0, @_},
2001-12-04 00:32:59 +00:00
} ,
2003-06-21 15:26:38 +00:00
{
2003-12-14 17:15:51 +00:00
name => "Winbond W83L785TS-S",
driver => "w83l785ts",
2003-06-21 15:26:38 +00:00
i2c_addrs => [0x2e],
i2c_detect => sub { w83l785ts_detect 0, @_},
} ,
2000-05-20 19:45:13 +00:00
{
name => "Winbond W83697HF",
2001-11-21 01:01:17 +00:00
driver => "w83781d",
2000-05-20 19:45:13 +00:00
isa_addrs => [0x290],
isa_detect => sub { w83781d_isa_detect 5, @_ },
} ,
1999-02-18 21:14:48 +00:00
{
name => "Genesys Logic GL518SM Revision 0x00",
driver => "gl518sm",
1999-04-07 18:37:36 +00:00
i2c_addrs => [0x2c, 0x2d],
1999-02-18 21:14:48 +00:00
i2c_detect => sub { gl518sm_detect 0, @_} ,
},
{
name => "Genesys Logic GL518SM Revision 0x80",
driver => "gl518sm",
1999-04-07 18:37:36 +00:00
i2c_addrs => [0x2c, 0x2d],
1999-02-18 21:14:48 +00:00
i2c_detect => sub { gl518sm_detect 1, @_} ,
},
{
name => "Genesys Logic GL520SM",
1999-07-27 16:51:00 +00:00
driver => "gl520sm",
1999-04-07 18:37:36 +00:00
i2c_addrs => [0x2c, 0x2d],
1999-10-30 19:51:37 +00:00
i2c_detect => sub { gl520sm_detect @_} ,
1999-10-20 02:53:38 +00:00
},
{
name => "Genesys Logic GL525SM",
2000-08-18 00:44:55 +00:00
driver => "Unwritten (GL525SM)",
1999-10-20 02:53:38 +00:00
i2c_addrs => [0x2d],
1999-10-30 19:51:37 +00:00
i2c_detect => sub { gl525sm_detect @_} ,
1999-02-18 21:14:48 +00:00
},
{
name => "Analog Devices ADM9240",
driver => "adm9240",
i2c_addrs => [0x2c..0x2f],
1999-03-29 00:58:55 +00:00
i2c_detect => sub { adm9240_detect 0, @_ }
},
2000-11-26 23:07:17 +00:00
{
name => "Dallas Semiconductor DS1621",
driver => "ds1621",
i2c_addrs => [0x48..0x4f],
i2c_detect => sub { ds1621_detect @_},
} ,
1999-03-29 00:58:55 +00:00
{
name => "Dallas Semiconductor DS1780",
driver => "adm9240",
i2c_addrs => [0x2c..0x2f],
i2c_detect => sub { adm9240_detect 1, @_ }
1999-02-18 21:14:48 +00:00
},
1999-08-22 17:52:38 +00:00
{
name => "National Semiconductor LM81",
driver => "adm9240",
i2c_addrs => [0x2c..0x2f],
i2c_detect => sub { adm9240_detect 2, @_ }
},
2003-06-08 21:33:39 +00:00
{
name => "Analog Devices ADM1026",
driver => "adm1026",
i2c_addrs => [0x2c,0x2d,0x2e],
i2c_detect => sub { adm1026_detect 0, @_ }
},
2000-03-19 22:06:54 +00:00
{
name => "Analog Devices ADM1025",
2000-05-11 01:44:14 +00:00
driver => "adm1025",
i2c_addrs => [0x2c..0x2e],
2000-03-19 22:06:54 +00:00
i2c_detect => sub { adm1025_detect 0, @_ }
},
2003-07-26 17:39:41 +00:00
{
name => "Philips NE1619",
driver => "adm1025",
i2c_addrs => [0x2c..0x2d],
i2c_detect => sub { adm1025_detect 1, @_ }
},
2001-05-15 03:18:18 +00:00
{
name => "Analog Devices ADM1024",
driver => "adm1024",
i2c_addrs => [0x2c..0x2e],
i2c_detect => sub { adm1024_detect 0, @_ }
},
1999-02-18 21:14:48 +00:00
{
name => "Analog Devices ADM1021",
1999-02-20 01:15:00 +00:00
driver => "adm1021",
1999-04-07 19:08:47 +00:00
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1999-02-18 21:14:48 +00:00
i2c_detect => sub { adm1021_detect 0, @_ },
},
{
2003-07-04 08:13:35 +00:00
name => "Analog Devices ADM1021A/ADM1023",
1999-02-20 01:15:00 +00:00
driver => "adm1021",
1999-04-07 19:08:47 +00:00
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1999-02-18 21:14:48 +00:00
i2c_detect => sub { adm1021_detect 1, @_ },
},
1999-04-10 00:05:10 +00:00
{
2003-07-04 08:13:35 +00:00
name => "Maxim MAX1617",
1999-04-10 00:05:10 +00:00
driver => "adm1021",
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
i2c_detect => sub { adm1021_detect 2, @_ },
},
1999-08-22 22:58:52 +00:00
{
2003-07-04 08:13:35 +00:00
name => "Maxim MAX1617A",
1999-08-22 22:58:52 +00:00
driver => "adm1021",
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
i2c_detect => sub { adm1021_detect 3, @_ },
},
2003-08-31 20:45:12 +00:00
{
name => "Maxim MAX6650/MAX6651",
driver => "max6650",
i2c_addrs => [0x1b,0x1f,0x48,0x4b],
i2c_detect => sub { max6650_detect 0, @_ },
},
1999-10-20 01:51:27 +00:00
{
2003-07-04 08:13:35 +00:00
name => "TI THMC10",
1999-10-20 01:51:27 +00:00
driver => "adm1021",
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
i2c_detect => sub { adm1021_detect 4, @_ },
},
1999-10-20 02:00:43 +00:00
{
2003-07-04 08:13:35 +00:00
name => "National Semiconductor LM84",
1999-10-20 02:00:43 +00:00
driver => "adm1021",
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
i2c_detect => sub { adm1021_detect 5, @_ },
},
2002-09-18 19:17:30 +00:00
{
2003-07-04 08:13:35 +00:00
name => "Genesys Logic GL523SM",
2002-09-18 19:17:30 +00:00
driver => "adm1021",
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
i2c_detect => sub { adm1021_detect 6, @_ },
},
2003-07-04 08:13:35 +00:00
{
name => "Onsemi MC1066",
driver => "adm1021",
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
i2c_detect => sub { adm1021_detect 7, @_ },
},
2003-07-19 22:09:39 +00:00
{
name => "National Semiconductor LM82",
driver => "to-be-written",
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
i2c_detect => sub { lm83_detect 1, @_ },
},
2003-07-02 09:23:51 +00:00
{
name => "National Semiconductor LM83",
2003-07-03 17:28:16 +00:00
driver => "lm83",
2003-07-02 09:23:51 +00:00
i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
2003-07-03 17:28:16 +00:00
i2c_detect => sub { lm83_detect 0, @_ },
2003-07-02 09:23:51 +00:00
},
2003-07-07 10:31:41 +00:00
{
name => "National Semiconductor LM90",
2003-08-30 20:53:29 +00:00
driver => "lm90",
2003-07-07 10:31:41 +00:00
i2c_addrs => [0x4c],
2003-07-08 07:19:12 +00:00
i2c_detect => sub { lm90_detect 0, @_ },
2003-07-07 10:31:41 +00:00
},
2003-07-19 22:09:39 +00:00
{
name => "National Semiconductor LM89",
driver => "to-be-written",
i2c_addrs => [0x4c],
i2c_detect => sub { lm90_detect 1, @_ },
},
{
name => "National Semiconductor LM86",
driver => "to-be-written",
i2c_addrs => [0x4c],
i2c_detect => sub { lm90_detect 2, @_ },
},
2003-08-30 20:53:29 +00:00
{
name => "Analog Devices ADM1032",
2003-11-02 19:37:45 +00:00
driver => "lm90",
2003-08-30 20:53:29 +00:00
i2c_addrs => [0x4c],
i2c_detect => sub { lm90_detect 3, @_ },
},
{
name => "Maxim MAX6657/MAX6658",
driver => "to-be-written",
i2c_addrs => [0x4c],
i2c_detect => sub { lm90_detect 4, @_ },
},
2003-11-08 11:13:46 +00:00
{
name => "Analog Devices ADM1029",
driver => "to-be-written",
i2c_addrs => [0x28..0x2f],
i2c_detect => sub { adm1029_detect 0, @_ },
},
{
name => "Analog Devices ADM1030",
driver => "to-be-written",
i2c_addrs => [0x2c..0x2e],
i2c_detect => sub { adm1031_detect 0, @_ },
},
{
name => "Analog Devices ADM1031",
driver => "to-be-written",
i2c_addrs => [0x2c..0x2e],
i2c_detect => sub { adm1031_detect 1, @_ },
},
1999-08-28 19:10:27 +00:00
{
name => "Analog Devices ADM1022",
1999-10-02 14:24:07 +00:00
driver => "thmc50",
1999-08-28 19:10:27 +00:00
i2c_addrs => [0x2c..0x2f],
i2c_detect => sub { adm1022_detect 0, @_ },
},
{
name => "Texas Instruments THMC50",
1999-10-02 14:24:07 +00:00
driver => "thmc50",
1999-08-28 19:10:27 +00:00
i2c_addrs => [0x2c..0x2f],
i2c_detect => sub { adm1022_detect 1, @_ },
},
1999-02-23 23:16:09 +00:00
{
name => "Silicon Integrated Systems SIS5595",
driver => "sis5595",
1999-02-24 01:12:05 +00:00
isa_addrs => [ 0 ],
1999-02-23 23:16:09 +00:00
isa_detect => sub { sis5595_isa_detect @_ },
1999-02-28 16:17:49 +00:00
},
2000-03-04 16:21:48 +00:00
{
2001-12-09 18:54:34 +00:00
name => "VIA Technologies VT82C686 Integrated Sensors",
2000-03-04 16:21:48 +00:00
driver => "via686a",
isa_addrs => [ 0 ],
isa_detect => sub { via686a_isa_detect @_ },
},
2002-05-27 21:21:29 +00:00
{
name => "VIA Technologies VT8231 Integrated Sensors",
2002-08-23 21:32:08 +00:00
driver => "vt8231",
2002-05-27 21:21:29 +00:00
isa_addrs => [ 0 ],
isa_detect => sub { via8231_isa_detect @_ },
},
2000-08-06 17:03:09 +00:00
{
2001-03-08 00:55:18 +00:00
name => "ITE IT8705F / IT8712F / SiS 950",
2001-06-03 21:58:26 +00:00
driver => "it87",
2001-10-22 01:42:53 +00:00
i2c_addrs => [0x20..0x2f],
i2c_detect => sub { ite_detect 0, @_ },
2000-08-06 17:03:09 +00:00
isa_addrs => [0x290],
isa_detect => sub { ite_isa_detect 0, @_ },
} ,
1999-02-28 16:17:49 +00:00
{
2003-08-07 08:51:08 +00:00
name => "SPD EEPROM",
1999-02-28 16:17:49 +00:00
driver => "eeprom",
i2c_addrs => [0x50..0x57],
2003-08-07 08:51:08 +00:00
i2c_detect => sub { eeprom_detect 0, @_ },
},
{
name => "Sony Vaio EEPROM",
driver => "eeprom",
i2c_addrs => [0x57],
i2c_detect => sub { eeprom_detect 1, @_ },
1999-04-08 19:33:03 +00:00
},
{
name => "LTC1710",
driver => "ltc1710",
i2c_addrs => [0x58..0x5a],
i2c_detect => sub { ltc1710_detect @_ },
},
1999-12-29 23:10:48 +00:00
{
name => "DDC monitor",
2000-01-30 01:15:29 +00:00
driver => "ddcmon",
1999-12-30 02:07:24 +00:00
i2c_addrs => [0x50],
1999-12-29 23:10:48 +00:00
i2c_detect => sub { ddcmonitor_detect @_ },
},
2001-09-18 15:20:15 +00:00
{
2003-09-27 08:19:20 +00:00
name => "FSC Poseidon",
2001-09-18 15:20:15 +00:00
driver => "fscpos",
i2c_addrs => [0x73],
i2c_detect => sub { fscpos_detect @_ },
},
2001-11-09 13:35:56 +00:00
{
2003-09-27 08:19:20 +00:00
name => "FSC Scylla",
2001-11-09 13:35:56 +00:00
driver => "fscscy",
i2c_addrs => [0x73],
i2c_detect => sub { fscscy_detect @_ },
},
2003-09-27 08:19:20 +00:00
{
name => "FSC Hermes",
2004-02-02 22:05:51 +00:00
driver => "fscher",
2003-09-27 08:19:20 +00:00
i2c_addrs => [0x73],
i2c_detect => sub { fscher_detect @_ },
},
2003-07-18 08:06:05 +00:00
{
name => "Philips Semiconductors SAA1064",
driver => "saa1064",
i2c_addrs => [0x38..0x3b],
i2c_detect => sub { saa1064_detect @_ },
2001-11-19 20:29:27 +00:00
},
2001-12-04 00:32:59 +00:00
{
2002-06-30 20:34:35 +00:00
name => "SMBus 2.0 ARP-Capable Device",
driver => "smbus-arp",
2001-12-04 00:32:59 +00:00
i2c_addrs => [0x61],
i2c_detect => sub { arp_detect @_},
},
2001-12-31 17:32:54 +00:00
{
name => "IPMI BMC KCS",
2002-11-16 03:28:33 +00:00
driver => "bmcsensors",
2001-12-31 17:32:54 +00:00
isa_addrs => [ 0x0ca0 ],
isa_detect => sub { ipmi_kcs_detect @_ },
},
{
name => "IPMI BMC SMIC",
2002-11-16 03:28:33 +00:00
driver => "bmcsensors",
2001-12-31 17:32:54 +00:00
isa_addrs => [ 0x0ca8 ],
isa_detect => sub { ipmi_smic_detect @_ },
},
2002-10-13 15:48:34 +00:00
{
2002-11-21 23:43:05 +00:00
name => "Smart Battery",
2002-10-13 15:48:34 +00:00
driver => "smartbatt",
i2c_addrs => [0x0b],
i2c_detect => sub { smartbatt_detect @_},
},
1999-02-18 00:19:19 +00:00
);
2002-12-09 03:01:23 +00:00
# This is a list of all recognized superio chips.
# Each entry must have the following fields:
# name: The full chip name
# driver: The driver name (without .o extension). Put in something like
# "Unwritten: <drivername>" if it is not yet available.
# addrreg: The address register
# datareg: The data register
# enter: The password sequence to write to the address register
# devidreg: The device ID register(s)
# devid: The device ID(s) we have to match (base device)
# logdevreg: The logical device register
# logdev: The logical device containing the sensors
# actreg (optional): The activation register within the logical device
# actmask (optional): The activation bit in the activation register
# basereg: The I/O base register within the logical device
2003-12-14 00:54:10 +00:00
# exitseq: Sequence of addr,val pairs which exits config modem
2002-12-09 03:01:23 +00:00
# alias_detect (optional): For chips which can be both on the ISA and the
# I2C bus, a function which detectes whether two entries are the same.
# The function should take three parameters: The ISA address, the
# I2C bus number, and the I2C address.
@superio_ids = (
# {
# name => "ITE 8705 Super IO Sensors",
# driver => "it87",
# addrreg => 0x2e,
# datareg => 0x2f,
2003-12-14 00:54:10 +00:00
# enter => [0x55, 0x01, 0x55, 0x55],
2002-12-09 03:01:23 +00:00
# code doesn't handle multiple devid regs yet
2003-12-14 00:54:10 +00:00
# devidreg => 0x20,
# devid => 0x8705,
2002-12-09 03:01:23 +00:00
# logdevreg => 0x07,
# logdev => 0x04,
# actreg => 0x30,
# actmask => 0x01,
# basereg => 0x60,
2003-12-14 00:54:10 +00:00
# exit is writing 0x01(?) to reg 0x02. - not compatible with other superio chips
# exitseq => [0x2e, 0xaa, 0x2e, 0x02, 0x2f, 0x01],
2002-12-15 04:41:20 +00:00
# },
2003-12-14 00:54:10 +00:00
{
name => "ITE 8712F Super IO Sensors",
driver => "it87",
addrreg => 0x2e,
datareg => 0x2f,
enter => [0x87, 0x01, 0x55, 0x55],
devidreg => 0x20,
devid => 0x8712,
logdevreg => 0x07,
logdev => 0x04,
actreg => 0x30,
actmask => 0x01,
basereg => 0x60,
# exit is writing 0x02 to reg 0x02. - not compatible with other superio chips
exitseq => [0x2e, 0xaa, 0x2e, 0x02, 0x2f, 0x02],
},
2002-12-15 04:41:20 +00:00
# Nat'l untested
# {
# name => "Nat. Semi. PC87366 Super I/O Sensors",
# driver => "xxxx",
# addrreg => 0x2e,
# datareg => 0x2f,
# enter => ?? none required?
# devidreg => 0x20,
# devid => 0xe9,
# logdevreg => 0x07,
# logdev => 0x09 # fans; temps at 0x0e
# actreg => 0x30,
# actmask => 0x01,
# basereg => 0x60,
# exit is writing 0x01 to reg 0x02. - not compatible with other superio chips
2003-12-14 00:54:10 +00:00
# exitseq => ??,
2002-12-09 03:01:23 +00:00
# },
{
2003-09-13 21:05:52 +00:00
name => "SMSC 47M10x Super IO Fan Sensors",
2002-12-09 03:01:23 +00:00
driver => "smsc47m1",
addrreg => 0x2e,
exitreg => 0x2e,
datareg => 0x2f,
enter => [0x55],
devidreg => 0x20,
devid => 0x59,
logdevreg => 0x07,
logdev => 0x0a,
actreg => 0x20,
actmask => 0x01,
basereg => 0x60,
2003-12-14 00:54:10 +00:00
exitseq => [0x2e, 0xaa],
2002-12-09 03:01:23 +00:00
},
2003-09-13 21:05:52 +00:00
{
name => "SMSC 47M14x Super IO Fan Sensors",
driver => "smsc47m1",
addrreg => 0x2e,
exitreg => 0x2e,
datareg => 0x2f,
enter => [0x55],
devidreg => 0x20,
devid => 0x5f,
logdevreg => 0x07,
logdev => 0x0a,
actreg => 0x20,
actmask => 0x01,
basereg => 0x60,
2003-12-14 00:54:10 +00:00
exitseq => [0x2e, 0xaa],
2003-09-13 21:05:52 +00:00
},
2002-12-09 03:01:23 +00:00
{
name => "VT1211 Super IO Sensors",
driver => "vt1211",
addrreg => 0x2e,
exitreg => 0x2e,
datareg => 0x2f,
enter => [0x87, 0x87],
devidreg => 0x20,
devid => 0x3c,
logdevreg => 0x07,
logdev => 0x0b,
actreg => 0x30,
actmask => 0x01,
basereg => 0x60,
2003-12-14 00:54:10 +00:00
exitseq => [0x2e, 0xaa],
2002-12-09 03:01:23 +00:00
},
{
name => "Winbond W83627HF Super IO Sensors",
2002-12-15 04:41:20 +00:00
driver => "w83627hf",
2002-12-09 03:01:23 +00:00
addrreg => 0x2e,
exitreg => 0x2e,
datareg => 0x2f,
enter => [0x87, 0x87],
devidreg => 0x20,
devid => 0x52,
logdevreg => 0x07,
logdev => 0x0b,
actreg => 0x30,
actmask => 0x01,
basereg => 0x60,
2003-12-14 00:54:10 +00:00
exitseq => [0x2e, 0xaa],
2002-12-09 03:01:23 +00:00
},
2003-06-11 23:43:25 +00:00
{
name => "Winbond W83627THF Super IO Sensors",
driver => "w83627hf",
addrreg => 0x2e,
exitreg => 0x2e,
datareg => 0x2f,
enter => [0x87, 0x87],
devidreg => 0x20,
devid => 0x82,
logdevreg => 0x07,
logdev => 0x0b,
actreg => 0x30,
actmask => 0x01,
basereg => 0x60,
exit => 0xaa,
},
2003-11-09 02:19:35 +00:00
{
name => "Winbond W83637HF Super IO Sensors",
2004-02-13 18:10:43 +00:00
driver => "w83627hf",
2003-11-09 02:19:35 +00:00
addrreg => 0x2e,
exitreg => 0x2e,
datareg => 0x2f,
enter => [0x87, 0x87],
devidreg => 0x20,
devid => 0x70,
logdevreg => 0x07,
logdev => 0x0b,
actreg => 0x30,
actmask => 0x01,
basereg => 0x60,
2003-12-14 00:54:10 +00:00
exitseq => [0x2e, 0xaa],
2003-11-09 02:19:35 +00:00
},
2002-12-09 03:01:23 +00:00
{
name => "Winbond W83697HF Super IO Sensors",
2002-12-15 04:41:20 +00:00
driver => "w83627hf",
2002-12-09 03:01:23 +00:00
addrreg => 0x2e,
exitreg => 0x2e,
datareg => 0x2f,
enter => [0x87, 0x87],
devidreg => 0x20,
devid => 0x60,
logdevreg => 0x07,
logdev => 0x0b,
actreg => 0x30,
actmask => 0x01,
basereg => 0x60,
2003-11-09 02:19:35 +00:00
exit => 0xaa,
},
{
name => "Winbond W83697UF Super IO PWM",
driver => "to-be-written",
addrreg => 0x2e,
exitreg => 0x2e,
datareg => 0x2f,
enter => [0x87, 0x87],
devidreg => 0x20,
devid => 0x68,
logdevreg => 0x07,
logdev => 0x0b,
actreg => 0x30,
actmask => 0x01,
basereg => 0x60,
2003-12-14 00:54:10 +00:00
exitseq => [0x2e, 0xaa],
2002-12-09 03:01:23 +00:00
},
);
1999-02-18 00:19:19 +00:00
#######################
# AUXILIARY FUNCTIONS #
#######################
sub swap_bytes
{
1999-02-19 02:30:17 +00:00
return (($_[0] & 0xff00) >> 8) + (($_[0] & 0x00ff) << 8)
1999-02-18 00:19:19 +00:00
}
1999-02-18 18:09:14 +00:00
# $_[0] is the sought value
# @_[1..] is the list to seek in
# Returns: 0 on failure, 1 if found.
sub contains
{
my $sought = shift;
foreach (@_) {
return 1 if $sought eq $_;
}
return 0;
}
1999-02-18 00:19:19 +00:00
1999-02-24 00:22:52 +00:00
sub parse_not_to_scan
{
my ($min,$max,$to_parse) = @_;
my @ranges = split /\s*,\s*/, $to_parse;
my @res = ();
my $range;
foreach $range (@ranges) {
my ($start,$end) = split /\s*-s*/, $range;
$start = oct $start if $start =~ /^0/;
if (defined $end) {
$end = oct $end if $end =~ /^0/;
$start = $min if $start < $min;
$end = $max if $end > $max;
push @res, ($start+0..$end+0);
} else {
push @res, $start+0 if $start >= $min and $start <= $max;
}
}
return sort { $a <=> $b } @res;
}
1999-02-19 01:52:29 +00:00
1999-02-28 17:41:46 +00:00
# @_[0]: Reference to list 1
# @_[1]: Reference to list 2
# Result: 0 if they have no elements in common, 1 if they have
# Elements must be numeric.
sub any_list_match
{
my ($list1,$list2) = @_;
my ($el1,$el2);
foreach $el1 (@$list1) {
foreach $el2 (@$list2) {
return 1 if $el1 == $el2;
}
}
return 0;
}
1999-02-22 18:20:35 +00:00
###################
# I/O port access #
###################
1999-02-23 14:14:32 +00:00
sub initialize_ioports
1999-02-22 18:20:35 +00:00
{
2003-06-28 22:05:52 +00:00
sysopen (IOPORTS, "/dev/port", O_RDWR)
2003-06-28 08:25:19 +00:00
or die "/dev/port: $!\n";
2003-07-07 10:31:41 +00:00
binmode IOPORTS;
2003-06-28 08:25:19 +00:00
}
sub close_ioports
{
close (IOPORTS)
or print "Warning: $!\n";
1999-02-22 18:20:35 +00:00
}
# $_[0]: port to read
# Returns: -1 on failure, read value on success.
sub inb
{
my ($res,$nrchars);
sysseek IOPORTS, $_[0], 0 or return -1;
$nrchars = sysread IOPORTS, $res, 1;
return -1 if not defined $nrchars or $nrchars != 1;
$res = unpack "C",$res ;
return $res;
}
# $_[0]: port to write
# $_[1]: value to write
# Returns: -1 on failure, 0 on success.
sub outb
{
2003-06-11 08:28:55 +00:00
if ($_[1] > 0xff)
{
2003-06-28 08:25:19 +00:00
my ($package, $filename, $line, $sub) = caller(1);
2003-06-11 08:28:55 +00:00
print "\n*** Called outb with value=$_[1] from line $line\n",
"*** (in $sub). PLEASE REPORT!\n",
"*** Terminating.\n";
exit(-1);
}
my $towrite = pack "C", $_[1];
1999-02-22 18:20:35 +00:00
sysseek IOPORTS, $_[0], 0 or return -1;
my $nrchars = syswrite IOPORTS, $towrite, 1;
return -1 if not defined $nrchars or $nrchars != 1;
return 0;
}
1999-02-22 20:40:16 +00:00
# $_[0]: Address register
# $_[1]: Data register
# $_[2]: Register to read
# Returns: read value
sub isa_read_byte
{
outb $_[0],$_[2];
return inb $_[1];
}
# $_[0]: Address register
# $_[1]: Data register
# $_[2]: Register to write
# $_[3}: Value to write
# Returns: nothing
sub isa_write_byte
{
outb $_[0],$_[2];
outb $_[1],$_[3];
}
2003-08-07 09:31:24 +00:00
#################
# AUTODETECTION #
#################
use vars qw($modules_conf $dev_i2c);
sub initialize_conf
{
if (-f '/etc/modules.conf') {
$modules_conf = '/etc/modules.conf';
} elsif (-f '/etc/conf.modules') {
$modules_conf = '/etc/conf.modules';
} else { # default
$modules_conf = '/etc/modules.conf';
}
if (-c '/dev/i2c-0') {
$dev_i2c = '/dev/i2c-';
2003-12-05 18:56:09 +00:00
} elsif (-d '/dev/i2c') { # devfs
2003-08-07 09:31:24 +00:00
$dev_i2c = '/dev/i2c/';
} elsif (-c '/dev/i2c0') {
$dev_i2c = '/dev/i2c';
} else { # default
print "No i2c device files found. Use prog/mkdev/mkdev.sh to create them.\n";
exit -1;
}
}
1999-02-19 01:52:29 +00:00
###########
# MODULES #
###########
use vars qw(@modules_list);
sub initialize_modules_list
{
open INPUTFILE, "/proc/modules" or die "Can't access /proc/modules!";
while (<INPUTFILE>) {
push @modules_list, /^(\S*)/ ;
}
close INPUTFILE;
}
1999-02-17 20:55:23 +00:00
##############
# PCI ACCESS #
##############
1999-02-18 00:19:19 +00:00
use vars qw(@pci_list);
1999-02-17 20:55:23 +00:00
# This function returns a list of hashes. Each hash has some PCI information
# (more than we will ever need, probably). The most important
1999-02-06 01:04:57 +00:00
# fields are 'bus', 'slot', 'func' (they uniquely identify a PCI device in
# a computer) and 'vendid','devid' (they uniquely identify a type of device).
# /proc/bus/pci/devices is only available on late 2.1 and 2.2 kernels.
sub read_proc_dev_pci
{
my ($dfn,$vend,@pci_list);
open INPUTFILE, "/proc/bus/pci/devices" or return;
while (<INPUTFILE>) {
my $record = {};
($dfn,$vend,$record->{irq},$record->{base_addr0},$record->{base_addr1},
$record->{base_addr2},$record->{base_addr3},$record->{base_addr4},
$record->{base_addr5},$record->{rom_base_addr}) =
2001-04-12 23:55:53 +00:00
map { oct "0x$_" } (split) [0..9];
1999-02-06 01:04:57 +00:00
$record->{bus} = $dfn >> 8;
$record->{slot} = ($dfn & 0xf8) >> 3;
$record->{func} = $dfn & 0x07;
$record->{vendid} = $vend >> 16;
$record->{devid} = $vend & 0xffff;
push @pci_list,$record;
}
close INPUTFILE or return;
1999-02-17 20:55:23 +00:00
return @pci_list;
1999-02-06 01:04:57 +00:00
}
1999-02-17 20:55:23 +00:00
# This function returns a list of hashes. Each hash has some PCI
# information. The important fields here are 'bus', 'slot', 'func' (they
1999-02-06 01:04:57 +00:00
# uniquely identify a PCI device in a computer) and 'desc' (a functional
1999-02-09 22:41:58 +00:00
# description of the PCI device). If this is an 'unknown device', the
# vendid and devid fields are set instead.
1999-02-06 01:04:57 +00:00
sub read_proc_pci
{
my @pci_list;
open INPUTFILE, "/proc/pci" or return;
while (<INPUTFILE>) {
my $record = {};
2000-03-15 00:26:50 +00:00
if (($record->{bus},$record->{slot},$record->{func}) =
1999-02-06 01:04:57 +00:00
/^\s*Bus\s*(\S)+\s*,\s*device\s*(\S+)\s*,\s*function\s*(\S+)\s*:\s*$/) {
1999-02-09 22:41:58 +00:00
my $desc = <INPUTFILE>;
2000-03-14 23:55:39 +00:00
$_ = <INPUTFILE>;
2000-03-15 00:26:50 +00:00
if (($desc =~ /Unknown device/) and
1999-02-09 22:41:58 +00:00
(($record->{vendid},$record->{devid}) =
/^\s*Vendor id=(\S+)\.\s*Device id=(\S+)\.$/)) {
2000-03-15 00:26:50 +00:00
$record->{vendid} = hex $record->{vendid};
$record->{devid} = hex $record->{devid};
} else {
1999-02-09 22:41:58 +00:00
$record->{desc} = $desc;
}
1999-02-06 01:04:57 +00:00
push @pci_list,$record;
}
}
close INPUTFILE or return;
1999-02-17 20:55:23 +00:00
return @pci_list;
1999-02-06 01:04:57 +00:00
}
1999-02-19 01:52:29 +00:00
sub initialize_proc_pci
1999-02-06 01:04:57 +00:00
{
1999-02-17 20:55:23 +00:00
@pci_list = read_proc_dev_pci;
@pci_list = read_proc_pci if not defined @pci_list;
die "Can't access either /proc/bus/pci/ or /proc/pci!"
if not defined @pci_list;
}
1999-02-06 01:04:57 +00:00
1999-02-17 20:55:23 +00:00
#####################
# ADAPTER DETECTION #
#####################
1999-02-19 01:52:29 +00:00
sub all_available_adapters
{
my @res = ();
my ($module,$adapter);
MODULES:
foreach $module (@modules_list) {
foreach $adapter (@pci_adapters) {
if (exists $adapter->{driver} and $module eq $adapter->{driver}) {
push @res, $module;
next MODULES;
}
}
}
return @res;
}
1999-02-17 20:55:23 +00:00
sub adapter_pci_detection
{
my ($device,$try,@res);
1999-02-06 01:04:57 +00:00
print "Probing for PCI bus adapters...\n";
1999-02-17 20:55:23 +00:00
foreach $device (@pci_list) {
1999-02-06 01:04:57 +00:00
foreach $try (@pci_adapters) {
1999-02-09 22:41:58 +00:00
if ((defined($device->{vendid}) and
$try->{vendid} == $device->{vendid} and
$try->{devid} == $device->{devid} and
$try->{func} == $device->{func}) or
(! defined($device->{vendid}) and
$device->{desc} =~ /$try->{procid}/ and
$try->{func} == $device->{func})) {
printf "Use driver `%s' for device %02x:%02x.%x: %s\n",
$try->{driver}?$try->{driver}:"<To Be Written>",
1999-02-06 01:04:57 +00:00
$device->{bus},$device->{slot},$device->{func},$try->{procid};
push @res,$try->{driver};
}
}
}
2000-08-18 00:28:00 +00:00
if (! @res) {
1999-02-06 01:04:57 +00:00
print ("Sorry, no PCI bus adapters found.\n");
} else {
printf ("Probe succesfully concluded.\n");
}
return @res;
}
1999-02-23 14:14:32 +00:00
# $_[0]: Adapter description as found in /proc/bus/i2c
# $_[1]: Algorithm description as found in /proc/bus/i2c
1999-02-19 18:11:03 +00:00
sub find_adapter_driver
{
my $adapter;
for $adapter (@pci_adapters) {
1999-02-23 14:14:32 +00:00
return $adapter->{driver} if &{$adapter->{match}} ($_[0],$_[1]);
1999-02-19 18:11:03 +00:00
}
2000-06-25 18:25:52 +00:00
return "UNKNOWN";
1999-02-19 18:11:03 +00:00
}
1999-02-17 20:55:23 +00:00
#############################
# I2C AND SMBUS /DEV ACCESS #
#############################
1999-02-18 00:19:19 +00:00
# This should really go into a separate module/package.
# To do: support i2c-level access (through sysread/syswrite, probably).
# I can't test this at all (PIIX4 does not support this), so I have not
# included it.
1999-02-17 20:55:23 +00:00
use vars qw($IOCTL_I2C_RETRIES $IOCTL_I2C_TIMEOUT $IOCTL_I2C_UDELAY
$IOCTL_I2C_MDELAY $IOCTL_I2C_SLAVE $IOCTL_I2C_TENBIT
$IOCTL_I2C_SMBUS);
# These are copied from <linux/i2c.h> and <linux/smbus.h>
# For bit-adapters:
$IOCTL_I2C_RETRIES = 0x0701;
$IOCTL_I2C_TIMEOUT = 0x0702;
$IOCTL_I2C_UDELAY = 0x0705;
$IOCTL_I2C_MDELAY = 0x0706;
1999-02-17 23:24:24 +00:00
# General ones:
1999-02-17 20:55:23 +00:00
$IOCTL_I2C_SLAVE = 0x0703;
$IOCTL_I2C_TENBIT = 0x0704;
$IOCTL_I2C_SMBUS = 0x0720;
1999-02-17 23:24:24 +00:00
1999-11-13 22:57:17 +00:00
1999-02-17 20:55:23 +00:00
use vars qw($SMBUS_READ $SMBUS_WRITE $SMBUS_QUICK $SMBUS_BYTE $SMBUS_BYTE_DATA
$SMBUS_WORD_DATA $SMBUS_PROC_CALL $SMBUS_BLOCK_DATA);
1999-02-17 23:24:24 +00:00
1999-02-17 20:55:23 +00:00
# These are copied from <linux/smbus.h>
1999-02-17 23:24:24 +00:00
1999-02-17 20:55:23 +00:00
$SMBUS_READ = 1;
$SMBUS_WRITE = 0;
$SMBUS_QUICK = 0;
$SMBUS_BYTE = 1;
$SMBUS_BYTE_DATA = 2;
$SMBUS_WORD_DATA = 3;
$SMBUS_PROC_CALL = 4;
$SMBUS_BLOCK_DATA = 5;
1999-02-17 23:24:24 +00:00
# Select the device to communicate with through its address.
# $_[0]: Reference to an opened filehandle
# $_[1]: Address to select
# Returns: 0 on failure, 1 on success.
1999-02-17 20:55:23 +00:00
sub i2c_set_slave_addr
{
my ($file,$addr) = @_;
ioctl $file, $IOCTL_I2C_SLAVE, $addr or return 0;
return 1;
}
# i2c_smbus_access is based upon the corresponding C function (see
1999-02-17 23:24:24 +00:00
# <linux/i2c-dev.h>). You should not need to call this directly.
# Exact calling conventions are intricate; read i2c-dev.c if you really need
# to know.
# $_[0]: Reference to an opened filehandle
# $_[1]: $SMBUS_READ for reading, $SMBUS_WRITE for writing
# $_[2]: Command (usually register number)
# $_[3]: Transaction kind ($SMBUS_BYTE, $SMBUS_BYTE_DATA, etc.)
# $_[4]: Reference to an array used for input/output of data
# Returns: 0 on failure, 1 on success.
1999-02-18 00:19:19 +00:00
# Note that we need to get back to Integer boundaries through the 'x2'
# in the pack. This is very compiler-dependent; I wish there was some other
# way to do this.
1999-02-17 20:55:23 +00:00
sub i2c_smbus_access
{
my ($file,$read_write,$command,$size,$data) = @_;
my $data_array = pack "C32", @$data;
1999-02-18 00:19:19 +00:00
my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
1999-02-17 20:55:23 +00:00
ioctl $file, $IOCTL_I2C_SMBUS, $ioctl_data or return 0;
$_[4] = [ unpack "C32",$data_array ];
return 1;
}
1999-02-17 23:24:24 +00:00
# $_[0]: Reference to an opened filehandle
# $_[1]: Either 0 or 1
# Returns: -1 on failure, the 0 on success.
sub i2c_smbus_write_quick
{
my ($file,$value) = @_;
my $data = [];
i2c_smbus_access $file, $value, 0, $SMBUS_QUICK, $data
or return -1;
return 0;
}
# $_[0]: Reference to an opened filehandle
# Returns: -1 on failure, the read byte on success.
sub i2c_smbus_read_byte
{
my ($file) = @_;
my $data = [];
i2c_smbus_access $file, $SMBUS_READ, 0, $SMBUS_BYTE, $data
or return -1;
return $$data[0];
}
# $_[0]: Reference to an opened filehandle
# $_[1]: Byte to write
# Returns: -1 on failure, 0 on success.
sub i2c_smbus_write_byte
1999-02-17 20:55:23 +00:00
{
my ($file,$command) = @_;
1999-02-17 23:24:24 +00:00
my $data = [$command];
i2c_smbus_access $file, $SMBUS_WRITE, 0, $SMBUS_BYTE, $data
1999-02-17 20:55:23 +00:00
or return -1;
1999-02-17 23:24:24 +00:00
return 0;
}
# $_[0]: Reference to an opened filehandle
# $_[1]: Command byte (usually register number)
# Returns: -1 on failure, the read byte on success.
sub i2c_smbus_read_byte_data
{
my ($file,$command) = @_;
my $data = [];
i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BYTE_DATA, $data
or return -1;
return $$data[0];
1999-02-17 20:55:23 +00:00
}
1999-02-17 23:24:24 +00:00
# $_[0]: Reference to an opened filehandle
# $_[1]: Command byte (usually register number)
# $_[2]: Byte to write
# Returns: -1 on failure, 0 on success.
sub i2c_smbus_write_byte_data
{
my ($file,$command,$value) = @_;
my $data = [$value];
i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BYTE_DATA, $data
or return -1;
return 0;
}
# $_[0]: Reference to an opened filehandle
# $_[1]: Command byte (usually register number)
1999-02-18 00:19:19 +00:00
# Returns: -1 on failure, the read word on success.
1999-02-17 23:24:24 +00:00
# Note: some devices use the wrong endiannes; use swap_bytes to correct for
# this.
1999-02-18 00:19:19 +00:00
sub i2c_smbus_read_word_data
1999-02-17 23:24:24 +00:00
{
1999-02-18 00:19:19 +00:00
my ($file,$command) = @_;
my $data = [];
i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_WORD_DATA, $data
1999-02-17 23:24:24 +00:00
or return -1;
1999-02-18 00:19:19 +00:00
return $$data[0] + 256 * $$data[1];
1999-02-17 23:24:24 +00:00
}
# $_[0]: Reference to an opened filehandle
# $_[1]: Command byte (usually register number)
1999-02-18 00:19:19 +00:00
# $_[2]: Byte to write
# Returns: -1 on failure, 0 on success.
1999-02-17 23:24:24 +00:00
# Note: some devices use the wrong endiannes; use swap_bytes to correct for
# this.
1999-02-18 00:19:19 +00:00
sub i2c_smbus_write_word_data
1999-02-17 20:55:23 +00:00
{
1999-02-18 00:19:19 +00:00
my ($file,$command,$value) = @_;
my $data = [$value & 0xff, $value >> 8];
i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_WORD_DATA, $data
1999-02-17 20:55:23 +00:00
or return -1;
1999-02-18 00:19:19 +00:00
return 0;
1999-02-17 20:55:23 +00:00
}
1999-02-17 23:24:24 +00:00
# $_[0]: Reference to an opened filehandle
# $_[1]: Command byte (usually register number)
# $_[2]: Word to write
# Returns: -1 on failure, read word on success.
# Note: some devices use the wrong endiannes; use swap_bytes to correct for
# this.
sub i2c_smbus_process_call
{
my ($file,$command,$value) = @_;
my $data = [$value & 0xff, $value >> 8];
i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_PROC_CALL, $data
or return -1;
return $$data[0] + 256 * $$data[1];
}
# $_[0]: Reference to an opened filehandle
# $_[1]: Command byte (usually register number)
# Returns: Undefined on failure, a list of read bytes on success
# Note: some devices use the wrong endiannes; use swap_bytes to correct for
# this.
sub i2c_smbus_read_block_data
{
my ($file,$command) = @_;
my $data = [];
i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BLOCK_DATA, $data
or return;
shift @$data;
return @$data;
}
# $_[0]: Reference to an opened filehandle
# $_[1]: Command byte (usually register number)
# @_[2..]: List of values to write
# Returns: -1 on failure, 0 on success.
# Note: some devices use the wrong endiannes; use swap_bytes to correct for
# this.
1999-02-18 00:19:19 +00:00
sub i2c_smbus_write_block_data
1999-02-17 23:24:24 +00:00
{
my ($file,$command,@data) = @_;
i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BLOCK_DATA, \@data
or return;
return 0;
}
1999-02-18 00:19:19 +00:00
####################
# ADAPTER SCANNING #
####################
1999-02-17 23:24:24 +00:00
1999-02-19 18:11:03 +00:00
use vars qw(@chips_detected);
# We will build a complicated structure @chips_detected here, being:
# A list of
# references to hashes
# with field 'driver', being a string with the driver name for this chip;
# with field 'detected'
# being a reference to a list of
1999-02-28 17:41:46 +00:00
# references to hashes of type 'detect_data';
1999-02-19 18:11:03 +00:00
# with field 'misdetected'
# being a reference to a list of
1999-02-28 17:41:46 +00:00
# references to hashes of type 'detect_data'
# Type detect_data:
# A hash
# with field 'i2c_adap' containing an adapter string as appearing
# in /proc/bus/i2c (if this is an I2C detection)
# with field 'i2c_algo' containing an algorithm string as appearing
# in /proc/bus/i2c (if this is an I2C detection)
# with field 'i2c_devnr', contianing the /dev/i2c-* number of this
# adapter (if this is an I2C detection)
# with field 'i2c_driver', containing the driver name for this adapter
# (if this is an I2C detection)
# with field 'i2c_addr', containing the I2C address of the detection;
# (if this is an I2C detection)
# with field 'i2c_sub_addrs', containing a reference to a list of
# other I2C addresses (if this is an I2C detection)
1999-03-23 21:48:41 +00:00
# with field 'i2c_extra' if this is an I2C detection and the address
# is not normally probed by the kernel driver
1999-02-28 17:41:46 +00:00
# with field 'isa_addr' containing the ISA address this chip is on
# (if this is an ISA detection)
1999-03-23 21:48:41 +00:00
# with field 'isa_extra' if this is an ISA detection and the address
# is not normally probed by the kernel driver
1999-02-28 17:41:46 +00:00
# with field 'conf', containing the confidence level of this detection
# with field 'chipname', containing the chip name
# This adds a detection to the above structure. We do no alias detection
# here; so you should do ISA detections *after* all I2C detections.
# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
# In all normal cases, it should be all right.
1999-02-19 18:11:03 +00:00
# $_[0]: chip driver
# $_[1]: reference to data hash
1999-02-28 17:41:46 +00:00
# Returns: Nothing
sub add_i2c_to_chips_detected
1999-02-19 18:11:03 +00:00
{
1999-02-23 14:14:32 +00:00
my ($chipdriver,$datahash) = @_;
1999-02-28 17:41:46 +00:00
my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2003-09-26 21:07:16 +00:00
$main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs,
$do_not_add);
1999-02-28 17:41:46 +00:00
# First determine where the hash has to be added.
1999-02-19 18:11:03 +00:00
for ($i = 0; $i < @chips_detected; $i++) {
last if ($chips_detected[$i]->{driver} eq $chipdriver);
}
if ($i == @chips_detected) {
push @chips_detected, { driver => $chipdriver,
detected => [],
misdetected => [] };
}
$new_detected_ref = $chips_detected[$i]->{detected};
$new_misdetected_ref = $chips_detected[$i]->{misdetected};
1999-02-28 17:41:46 +00:00
# Find out whether our new entry should go into the detected or the
1999-03-02 08:08:29 +00:00
# misdetected list. We compare all i2c addresses; if at least one matches,
# but our conf value is lower, we assume this is a misdetect.
@hash_addrs = ($datahash->{i2c_addr});
push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
if exists $datahash->{i2c_sub_addrs};
1999-02-28 17:41:46 +00:00
$put_in_detected = 1;
2003-09-26 21:07:16 +00:00
$do_not_add = 0;
1999-02-28 17:41:46 +00:00
FIND_LOOP:
foreach $main_entry (@chips_detected) {
foreach $detected_entry (@{$main_entry->{detected}}) {
1999-03-02 10:04:21 +00:00
@entry_addrs = ($detected_entry->{i2c_addr});
push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
1999-03-02 11:13:46 +00:00
if exists $detected_entry->{i2c_sub_addrs};
1999-02-28 17:41:46 +00:00
if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
1999-03-02 08:08:29 +00:00
any_list_match \@entry_addrs, \@hash_addrs) {
1999-02-28 17:41:46 +00:00
if ($detected_entry->{conf} >= $datahash->{conf}) {
$put_in_detected = 0;
}
2003-09-26 21:07:16 +00:00
if ($chipdriver eq $main_entry->{driver}) {
$do_not_add = 1;
}
1999-02-28 17:41:46 +00:00
last FIND_LOOP;
}
}
}
if ($put_in_detected) {
# Here, we move all entries from detected to misdetected which
# match at least in one main or sub address. This may not be the
# best idea to do, as it may remove detections without replacing
# them with second-best ones. Too bad.
2003-09-26 21:07:16 +00:00
# (Khali 2003-09-13) If the driver is the same, the "misdetected"
# entry is simply deleted; failing to do so cause the configuration
# lines generated later to look very confusing (the driver will
# be told to ignore valid addresses).
1999-02-28 17:41:46 +00:00
@hash_addrs = ($datahash->{i2c_addr});
push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
if exists $datahash->{i2c_sub_addrs};
foreach $main_entry (@chips_detected) {
$detected_ref = $main_entry->{detected};
$misdetected_ref = $main_entry->{misdetected};
for ($i = @$detected_ref-1; $i >=0; $i--) {
@entry_addrs = ($detected_ref->[$i]->{i2c_addr});
push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
if exists $detected_ref->[$i]->{i2c_sub_addrs};
1999-12-29 20:13:25 +00:00
if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} and
any_list_match \@entry_addrs, \@hash_addrs) {
2003-09-26 21:07:16 +00:00
push @$misdetected_ref,$detected_ref->[$i]
unless $chipdriver eq $main_entry->{driver};
1999-02-28 17:41:46 +00:00
splice @$detected_ref, $i, 1;
1999-02-19 18:11:03 +00:00
}
}
}
1999-02-28 17:41:46 +00:00
# Now add the new entry to detected
push @$new_detected_ref, $datahash;
} else {
# No hard work here
2003-09-26 21:07:16 +00:00
push @$new_misdetected_ref, $datahash
unless $do_not_add;
1999-02-19 18:11:03 +00:00
}
}
1999-02-28 17:41:46 +00:00
# This adds a detection to the above structure. We also do alias detection
# here; so you should do ISA detections *after* all I2C detections.
# $_[0]: alias detection function
# $_[1]: chip driver
# $_[2]: reference to data hash
1999-12-05 20:15:43 +00:00
# Returns: 0 if it is not an alias, datahash reference if it is.
1999-02-23 14:14:32 +00:00
sub add_isa_to_chips_detected
{
1999-02-23 20:28:05 +00:00
my ($alias_detect,$chipdriver,$datahash) = @_;
1999-02-28 17:41:46 +00:00
my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
1999-12-05 20:15:43 +00:00
$main_entry,$isalias);
1999-02-23 14:14:32 +00:00
1999-02-28 17:41:46 +00:00
# First determine where the hash has to be added.
1999-12-05 20:15:43 +00:00
$isalias=0;
1999-02-23 14:14:32 +00:00
for ($i = 0; $i < @chips_detected; $i++) {
last if ($chips_detected[$i]->{driver} eq $chipdriver);
}
if ($i == @chips_detected) {
push @chips_detected, { driver => $chipdriver,
detected => [],
1999-02-28 17:41:46 +00:00
misdetected => [] };
1999-02-23 14:14:32 +00:00
}
$new_detected_ref = $chips_detected[$i]->{detected};
$new_misdetected_ref = $chips_detected[$i]->{misdetected};
1999-02-28 17:41:46 +00:00
1999-02-23 20:28:05 +00:00
# Now, we are looking for aliases. An alias can only be the same chiptype.
1999-02-28 17:41:46 +00:00
# If an alias is found in the misdetected list, we add the new information
# and terminate this function. If it is found in the detected list, we
# still have to check whether another chip has claimed this ISA address.
# So we remove the old entry from the detected list and put it in datahash.
# Misdetected alias detection:
for ($i = 0; $i < @$new_misdetected_ref; $i++) {
if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
not exists $new_misdetected_ref->[$i]->{isa_addr} and
1999-02-23 20:28:05 +00:00
defined $alias_detect and
1999-02-28 17:41:46 +00:00
$new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2003-08-07 09:31:24 +00:00
open FILE,"$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}" or
print("Can't open $dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
next;
2003-07-07 10:31:41 +00:00
binmode FILE;
1999-03-02 10:04:21 +00:00
i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{i2c_addr} or
1999-02-25 08:37:29 +00:00
print("Can't set I2C address for ",
2003-08-07 09:31:24 +00:00
"$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
1999-02-25 08:37:29 +00:00
next;
1999-02-24 01:12:05 +00:00
if (&$alias_detect ($datahash->{isa_addr},\*FILE,
1999-02-28 17:41:46 +00:00
$new_misdetected_ref->[$i]->{i2c_addr})) {
$new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
1999-03-23 21:48:41 +00:00
$new_misdetected_ref->[$i]->{isa_extra} = $datahash->{isa_extra}
if exists $datahash->{isa_extra};
1999-02-25 12:23:04 +00:00
close FILE;
1999-12-05 20:15:43 +00:00
return $new_misdetected_ref->[$i];
1999-02-23 20:28:05 +00:00
}
1999-02-24 01:12:05 +00:00
close FILE;
1999-02-23 20:28:05 +00:00
}
}
1999-02-28 17:41:46 +00:00
# Detected alias detection:
for ($i = 0; $i < @$new_detected_ref; $i++) {
if (exists $new_detected_ref->[$i]->{i2c_addr} and
not exists $new_detected_ref->[$i]->{isa_addr} and
defined $alias_detect and
$new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2003-08-07 09:31:24 +00:00
open FILE,"$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}" or
print("Can't open $dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
next;
2003-07-07 10:31:41 +00:00
binmode FILE;
1999-03-03 14:18:01 +00:00
i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{i2c_addr} or
1999-02-25 08:37:29 +00:00
print("Can't set I2C address for ",
2003-08-07 09:31:24 +00:00
"$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
1999-02-25 08:37:29 +00:00
next;
1999-02-24 01:12:05 +00:00
if (&$alias_detect ($datahash->{isa_addr},\*FILE,
1999-02-28 17:41:46 +00:00
$new_detected_ref->[$i]->{i2c_addr})) {
$new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
1999-03-23 21:48:41 +00:00
$new_detected_ref->[$i]->{isa_extra} = $datahash->{isa_extra}
if exists $datahash->{isa_extra};
1999-02-28 17:41:46 +00:00
($datahash) = splice (@$new_detected_ref, $i, 1);
1999-02-25 12:23:04 +00:00
close FILE;
1999-12-05 20:15:43 +00:00
$isalias=1;
1999-02-23 20:28:05 +00:00
last;
}
1999-02-24 01:33:18 +00:00
close FILE;
1999-02-23 20:28:05 +00:00
}
}
1999-02-28 17:41:46 +00:00
# Find out whether our new entry should go into the detected or the
# misdetected list. We only compare main isa_addr here, of course.
foreach $main_entry (@chips_detected) {
$detected_ref = $main_entry->{detected};
$misdetected_ref = $main_entry->{misdetected};
for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
if (exists $detected_ref->[$i]->{isa_addr} and
$detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
1999-02-23 14:14:32 +00:00
push @$new_misdetected_ref, $datahash;
1999-02-28 17:41:46 +00:00
} else {
push @$misdetected_ref,$detected_ref->[$i];
splice @$detected_ref, $i,1;
push @$new_detected_ref, $datahash;
1999-02-23 14:14:32 +00:00
}
1999-12-05 20:15:43 +00:00
if ($isalias) {
return $datahash;
} else {
return 0;
}
1999-02-23 14:14:32 +00:00
}
}
}
1999-02-28 17:41:46 +00:00
1999-03-02 08:08:29 +00:00
# Not found? OK, put it in the detected list
1999-02-28 17:41:46 +00:00
push @$new_detected_ref, $datahash;
1999-12-05 20:15:43 +00:00
if ($isalias) {
return $datahash;
} else {
return 0;
}
1999-02-23 14:14:32 +00:00
}
1999-02-18 00:19:19 +00:00
# $_[0]: The number of the adapter to scan
1999-02-19 18:11:03 +00:00
# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
1999-02-23 14:14:32 +00:00
# $_[2]: The name of the algorithm, as appearing in /proc/bus/i2c
# $_[3]: The driver of the adapter
1999-03-02 08:08:29 +00:00
# @_[4..]: Addresses not to scan
1999-02-18 00:19:19 +00:00
sub scan_adapter
1999-02-17 23:24:24 +00:00
{
1999-02-24 00:22:52 +00:00
my ( $adapter_nr,$adapter_name,$algorithm_name,$adapter_driver,
$not_to_scan) = @_;
1999-02-28 17:41:46 +00:00
my ($chip, $addr, $conf,@chips,$new_hash,$other_addr);
# As we modify it, we need a copy
1999-02-24 00:22:52 +00:00
my @not_to_scan = @$not_to_scan;
1999-02-28 17:41:46 +00:00
2003-08-07 09:31:24 +00:00
open FILE,"$dev_i2c$adapter_nr" or
(print "Can't open $dev_i2c$adapter_nr\n"), return;
2003-07-07 10:31:41 +00:00
binmode FILE;
1999-02-28 17:41:46 +00:00
# Now scan each address in turn
1999-02-18 18:09:14 +00:00
foreach $addr (0..0x7f) {
1999-02-28 17:41:46 +00:00
# As the not_to_scan list is sorted, we can check it fast
1999-02-24 00:22:52 +00:00
if (@not_to_scan and $not_to_scan[0] == $addr) {
shift @not_to_scan;
next;
}
1999-02-28 17:41:46 +00:00
1999-12-08 20:37:09 +00:00
i2c_set_slave_addr(\*FILE,$addr) or
printf("Client at address 0x%02x can not be probed - unload all client drivers first!\n",$addr), next;
1999-02-28 17:41:46 +00:00
2002-09-01 15:47:21 +00:00
next unless i2c_smbus_write_quick(\*FILE,$SMBUS_WRITE) >= 0;
1999-02-18 18:09:14 +00:00
printf "Client found at address 0x%02x\n",$addr;
2002-09-01 15:47:21 +00:00
# Prevent 24RF08 corruption
if($addr >= 0x54 and $addr <= 0x57) {
i2c_smbus_write_quick(\*FILE,$SMBUS_WRITE);
}
1999-02-28 17:41:46 +00:00
1999-02-18 18:09:14 +00:00
foreach $chip (@chip_ids) {
1999-02-23 20:28:05 +00:00
if (exists $$chip{i2c_addrs} and contains $addr, @{$$chip{i2c_addrs}}) {
1999-02-23 23:16:09 +00:00
print "Probing for `$$chip{name}'... ";
1999-02-19 01:52:29 +00:00
if (($conf,@chips) = &{$$chip{i2c_detect}} (\*FILE ,$addr)) {
1999-02-19 02:30:17 +00:00
print "Success!\n",
1999-12-29 23:10:48 +00:00
" (confidence $conf, driver `$$chip{driver}')";
1999-02-19 01:52:29 +00:00
if (@chips) {
1999-02-25 08:30:04 +00:00
print ", other addresses:";
1999-02-28 17:41:46 +00:00
@chips = sort @chips;
1999-02-25 08:30:04 +00:00
foreach $other_addr (sort @chips) {
1999-03-02 08:08:29 +00:00
printf(" 0x%02x",$other_addr);
1999-02-25 08:30:04 +00:00
}
1999-02-20 00:54:55 +00:00
}
1999-02-28 17:41:46 +00:00
printf "\n";
$new_hash = { conf => $conf,
i2c_addr => $addr,
chipname => $$chip{name},
i2c_adap => $adapter_name,
i2c_algo => $algorithm_name,
i2c_driver => $adapter_driver,
i2c_devnr => $adapter_nr,
};
1999-03-01 13:49:06 +00:00
if (@chips) {
my @chips_copy = @chips;
$new_hash->{i2c_sub_addrs} = \@chips_copy;
}
1999-03-23 21:48:41 +00:00
$new_hash->{i2c_extra} = 0
if exists $chip->{i2c_driver_addrs} and
not contains( $addr , @{$chip->{i2c_driver_addrs}});
1999-02-28 17:41:46 +00:00
add_i2c_to_chips_detected $$chip{driver}, $new_hash;
1999-02-18 18:09:14 +00:00
} else {
1999-02-19 18:11:03 +00:00
print "Failed!\n";
1999-02-18 18:09:14 +00:00
}
}
}
1999-02-18 00:19:19 +00:00
}
1999-02-17 23:24:24 +00:00
}
1999-02-23 14:14:32 +00:00
sub scan_isa_bus
{
my ($chip,$addr,$conf);
foreach $chip (@chip_ids) {
next if not exists $$chip{isa_addrs} or not exists $$chip{isa_detect};
1999-02-23 23:16:09 +00:00
print "Probing for `$$chip{name}'\n";
1999-02-23 14:14:32 +00:00
foreach $addr (@{$$chip{isa_addrs}}) {
1999-02-24 01:12:05 +00:00
if ($addr) {
printf " Trying address 0x%04x... ", $addr;
} else {
1999-02-28 17:41:46 +00:00
print " Trying general detect... ";
1999-02-24 01:12:05 +00:00
}
1999-02-23 14:14:32 +00:00
$conf = &{$$chip{isa_detect}} ($addr);
print("Failed!\n"), next if not defined $conf;
print "Success!\n";
printf " (confidence %d, driver `%s')\n", $conf, $$chip{driver};
1999-03-23 21:48:41 +00:00
my $new_hash = { conf => $conf,
isa_addr => $addr,
chipname => $$chip{name}
};
$new_hash->{isa_extra} = 0
if exists $chip->{isa_driver_addrs} and
not contains ($addr, @{$chip->{isa_driver_addrs}});
1999-12-05 20:15:43 +00:00
$new_hash = add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver},
$new_hash;
if ($new_hash) {
1999-12-10 19:44:00 +00:00
printf " Alias of the chip on I2C bus `%s', address 0x%04x\n",
1999-12-05 23:54:23 +00:00
$new_hash->{i2c_adap},$new_hash->{i2c_addr};
1999-12-05 20:15:43 +00:00
}
1999-02-23 14:14:32 +00:00
}
}
}
2002-12-09 03:01:23 +00:00
sub scan_superio
{
my ($chip,$val,$addr,$conf);
foreach $chip (@superio_ids) {
print "Probing for `$$chip{name}'\n";
# write the password
foreach $val (@{$$chip{enter}}) {
outb($$chip{addrreg}, $val);
}
# check the device ID
outb($$chip{addrreg}, $$chip{devidreg});
$val = inb($$chip{datareg});
2003-12-14 00:54:10 +00:00
if($$chip{devid}>0xff) {
outb($$chip{addrreg}, $$chip{devidreg} + 1);
$val = ($val << 8) | inb($$chip{datareg});
}
2002-12-09 03:01:23 +00:00
if($val == $$chip{devid}) {
print " Success...";
# switch to the sensor logical device
outb($$chip{addrreg}, $$chip{logdevreg});
outb($$chip{datareg}, $$chip{logdev});
# check the activation register
if(exists $$chip{actreg}) {
outb($$chip{addrreg}, $$chip{actreg});
$val = inb($$chip{datareg});
if(!($val & $$chip{actmask})) {
print " but not activated, module may not find\n";
outb($$chip{exitreg}, $$chip{exit});
next;
}
}
# Get the IO base register
outb($$chip{addrreg}, $$chip{basereg});
$addr = inb($$chip{datareg});
outb($$chip{addrreg}, $$chip{basereg} + 1);
$addr = ($addr << 8) | inb($$chip{datareg});
if($addr == 0) {
print " but not activated, module may not find\n";
outb($$chip{addrreg}, $$chip{exit});
next;
}
printf " found at address 0x%04x\n", $addr;
2003-10-22 18:42:44 +00:00
my $new_hash = { conf => 9,
2002-12-09 03:01:23 +00:00
isa_addr => $addr,
chipname => $$chip{name}
};
add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver},
$new_hash;
} else {
2003-06-10 02:32:57 +00:00
if($val == 0xff) {
print " Failed!\n";
} else {
printf " Failed! (0x%02x)\n", $val;
}
2002-12-09 03:01:23 +00:00
}
2003-12-14 00:54:10 +00:00
while ($addr = shift(@{$$chip{exitseq}})) {
outb($addr, shift(@{$$chip{exitseq}}));
}
2002-12-09 03:01:23 +00:00
}
}
1999-02-18 18:09:14 +00:00
1999-02-18 00:19:19 +00:00
##################
# CHIP DETECTION #
##################
1999-02-18 18:09:14 +00:00
# Each function returns a confidence value. The higher this value, the more
1999-02-18 21:14:48 +00:00
# sure we are about this chip. A Winbond W83781D, for example, will be
# detected as a LM78 too; but as the Winbond detection has a higher confidence
# factor, you should identify it as a Winbond.
# Each function returns a list. The first element is the confidence value;
# Each element after it is an SMBus address. In this way, we can detect
# chips with several SMBus addresses. The SMBus address for which the
# function was called is never returned.
1999-02-18 18:09:14 +00:00
# If there are devices which get confused if they are only read from, then
# this program will surely confuse them. But we guarantee never to write to
# any of these devices.
2000-10-18 00:34:07 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, (7) if detected.
# Registers used: 0x58
sub mtp008_detect
{
my ($file,$addr) = @_;
return if (i2c_smbus_read_byte_data($file,0x58)) != 0xac;
return (8);
}
1999-02-18 18:09:14 +00:00
# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
1999-02-18 21:14:48 +00:00
# Returns: undef if not detected, (7) if detected.
1999-02-18 18:09:14 +00:00
# Registers used:
1999-02-18 21:14:48 +00:00
# 0x40: Configuration
1999-02-18 18:09:14 +00:00
# 0x48: Full I2C Address
# 0x49: Device ID
1999-02-18 21:14:48 +00:00
# Note that this function is always called through a closure, so the
# arguments are shifted by one place.
1999-02-18 18:09:14 +00:00
sub lm78_detect
{
my $reg;
my ($chip,$file,$addr) = @_;
1999-02-18 21:14:48 +00:00
return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
1999-02-19 02:30:17 +00:00
return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
1999-02-18 18:09:14 +00:00
$reg = i2c_smbus_read_byte_data($file,0x49);
2001-01-19 02:39:26 +00:00
return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
1999-02-18 21:14:48 +00:00
($chip == 1 and $reg == 0x40) or
1999-02-19 02:30:17 +00:00
($chip == 2 and ($reg & 0xfe) == 0xc0);
1999-02-18 21:14:48 +00:00
return (7);
1999-02-18 18:09:14 +00:00
}
1999-02-22 20:40:16 +00:00
# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
1999-02-23 14:14:32 +00:00
# $_[1]: Address
1999-03-09 16:19:30 +00:00
# Returns: undef if not detected, 7 if detected.
1999-02-22 20:40:16 +00:00
# Note: Only address 0x290 is scanned at this moment.
sub lm78_isa_detect
{
1999-02-23 14:14:32 +00:00
my ($chip,$addr) = @_ ;
my $val = inb ($addr + 1);
return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
1999-02-22 20:40:16 +00:00
inb ($addr + 7) != $val;
LM78 insmod parameters and better detection
Supported insmod parameters:
ignore, ignore_range
probe, probe_range
force, force_lm78, force_lm78j, force_lm79
force* overrules ignore* overrules probe*
The *_range parameters need three elements for each specification:
bus,start_addr,end_addr
The address ranges are inclusive.
The other parameters need two elements for each specification:
bus,addr
In each case, '-1' stands for 'any I2C bus', and 9191 stands for
'the ISA bus' (Bonus question: who can figure out why I choose 9191?)
In each case, just append if you want several specification, for example:
insmod lm78 probe=9191,0x2a0,1,0x56
force_* does no detection, not even chip detection; it blindly assumes
you know what you are doing. plain force does the chip detection, but
nothing else; but it can still fail if the register read-out does not
match a chip type.
Detection is done in exactly the same way as sensors-detect, except that
only the range 0x20-0x2f is examined by default. This needs to be
synchronized somehow with the detect script. I would rather scan the whole
I2C address range, but with those clueless PIIX4 hangs when clock chips
are read, that would simply give too much trouble.
The detect script has slightly better ISA detection now, too.
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@325 7894878c-1315-0410-8ee3-d5d059ff63e0
1999-03-19 06:25:02 +00:00
$val = inb($addr + 5) & 0x7f;
2003-06-11 08:28:55 +00:00
outb($addr + 5, ~$val & 0xff);
LM78 insmod parameters and better detection
Supported insmod parameters:
ignore, ignore_range
probe, probe_range
force, force_lm78, force_lm78j, force_lm79
force* overrules ignore* overrules probe*
The *_range parameters need three elements for each specification:
bus,start_addr,end_addr
The address ranges are inclusive.
The other parameters need two elements for each specification:
bus,addr
In each case, '-1' stands for 'any I2C bus', and 9191 stands for
'the ISA bus' (Bonus question: who can figure out why I choose 9191?)
In each case, just append if you want several specification, for example:
insmod lm78 probe=9191,0x2a0,1,0x56
force_* does no detection, not even chip detection; it blindly assumes
you know what you are doing. plain force does the chip detection, but
nothing else; but it can still fail if the register read-out does not
match a chip type.
Detection is done in exactly the same way as sensors-detect, except that
only the range 0x20-0x2f is examined by default. This needs to be
synchronized somehow with the detect script. I would rather scan the whole
I2C address range, but with those clueless PIIX4 hangs when clock chips
are read, that would simply give too much trouble.
The detect script has slightly better ISA detection now, too.
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@325 7894878c-1315-0410-8ee3-d5d059ff63e0
1999-03-19 06:25:02 +00:00
if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
outb($addr+5,$val);
return;
}
1999-02-23 14:14:32 +00:00
my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
return unless (&$readproc(0x40) & 0x80) == 0x00;
my $reg = &$readproc(0x49);
2001-01-19 02:39:26 +00:00
return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
1999-02-23 14:14:32 +00:00
($chip == 1 and $reg == 0x40) or
($chip == 2 and ($reg & 0xfe) == 0xc0);
return 7;
1999-02-22 20:40:16 +00:00
}
1999-02-23 20:28:05 +00:00
# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
# $_[1]: ISA address
# $_[2]: I2C file handle
# $_[3]: I2C address
sub lm78_alias_detect
{
my ($chip,$isa_addr,$file,$i2c_addr) = @_;
my $i;
my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
return 0 unless &$readproc(0x48) == $i2c_addr;
for ($i = 0x2b; $i <= 0x3d; $i ++) {
1999-02-24 01:33:18 +00:00
return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
1999-02-23 20:28:05 +00:00
}
return 1;
}
1999-02-18 18:09:14 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
1999-02-18 00:19:19 +00:00
# $_[1]: Address
2003-07-02 09:06:51 +00:00
# Returns: undef if not detected, 2 to 6 if detected;
# 6 means that the LM75 was found in its default power up state;
# 5 means that the LM75 was found in another known default state;
# 4 means that the LM75 was found in a probable state (temperatures
# make sense);
# 3 means that the configuration register passes the test;
1999-02-18 18:09:14 +00:00
# Registers used:
2003-07-02 09:06:51 +00:00
# 0x01: Temperature
1999-02-18 18:09:14 +00:00
# 0x01: Configuration
1999-08-28 19:10:27 +00:00
# 0x02: Hysteresis
1999-02-18 18:09:14 +00:00
# 0x03: Overtemperature Shutdown
2003-07-02 09:06:51 +00:00
# The first detection step is only based on the fact that the LM75 has only
1999-02-18 18:09:14 +00:00
# four registers. Any other chip in the valid address range with only four
# registers will be detected too.
# Note that register $00 may change, so we can't use the modulo trick on it.
sub lm75_detect
{
my $i;
my ($file,$addr) = @_;
1999-03-01 13:49:06 +00:00
my $cur = i2c_smbus_read_word_data($file,0x00);
2003-10-13 20:09:52 +00:00
my $cur_varies = 0;
1999-02-18 18:09:14 +00:00
my $conf = i2c_smbus_read_byte_data($file,0x01);
my $hyst = i2c_smbus_read_word_data($file,0x02);
my $os = i2c_smbus_read_word_data($file,0x03);
1999-03-01 13:49:06 +00:00
for ($i = 0x00; $i <= 0x1f; $i += 1) {
return if i2c_smbus_read_byte_data($file,($i * 0x08) + 0x01) != $conf;
return if i2c_smbus_read_word_data($file,($i * 0x08) + 0x02) != $hyst;
return if i2c_smbus_read_word_data($file,($i * 0x08) + 0x03) != $os;
2003-10-13 20:09:52 +00:00
$cur_varies = 1
if (! $cur_varies) and
i2c_smbus_read_word_data($file,($i * 0x08)) != $cur;
1999-02-18 18:09:14 +00:00
}
2003-07-02 09:06:51 +00:00
# Default power up state (from specs)
return 6
if $conf == 0 and ($hyst&0x80ff) == 0x004b and ($os&0x80ff) == 0x0050;
# Default state as seen on the Asus TX97-E
return 5
if $conf == 0 and ($hyst&0x80ff) == 0x002d and ($os&0x80ff) == 0x0034;
2003-10-13 20:09:52 +00:00
# All registers hold the same value, obviously a misdetection
2003-10-11 13:35:01 +00:00
return
2003-10-13 20:09:52 +00:00
if (! $cur_varies) and $conf == ($cur&0xff) and $cur == $hyst
and $cur == $os;
2003-10-11 13:35:01 +00:00
# Unused bits in conf register
return
if ($conf&0xe0) != 0;
2003-07-02 09:06:51 +00:00
# Most probable value ranges
return 4
2003-10-11 13:35:01 +00:00
if (($cur&0x00ff) <= 125 || ($cur&0x00ff) >= 201)
2003-07-02 09:06:51 +00:00
and ($hyst&0x00ff) <= 125 and ($os&0x00ff) <= 125 and $hyst<$os;
2003-10-11 13:35:01 +00:00
return 3;
1999-02-18 18:09:14 +00:00
}
2000-11-26 23:07:17 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, (3) if detected,
2003-12-02 20:57:02 +00:00
# (5) or (7) if even more bits match.
2000-11-26 23:07:17 +00:00
# Registers used:
2003-12-02 20:57:02 +00:00
# 0xAA: Temperature
# 0xA1: High limit
# 0xA2: Low limit
2000-11-26 23:07:17 +00:00
# 0xAC: Configuration
# Detection is weak. We check if Bit 3 is set and Bit 2 is clear.
# The DS1621 will aways have a config like 0x????10??. A even better
# match would be 0x0??01000.
2003-12-02 20:57:02 +00:00
# Temperature checkings will hopefully prevent LM75 chips from being
# detected as a DS1621.
2000-11-26 23:07:17 +00:00
sub ds1621_detect
{
my $i;
my ($file,$addr) = @_;
2003-12-02 20:57:02 +00:00
my $temp = i2c_smbus_read_word_data($file,0xAA);
return if ($temp & 0x007F);
$temp = i2c_smbus_read_word_data($file,0xA1);
return if ($temp & 0x007F);
$temp = i2c_smbus_read_word_data($file,0xA2);
return if ($temp & 0x007F);
2000-11-26 23:07:17 +00:00
my $conf = i2c_smbus_read_byte_data($file,0xAC);
2003-12-02 20:57:02 +00:00
return (7) if ($conf & 0x9F) == 0x98;
return (5) if ($conf & 0x0F) == 0x08;
2000-11-26 23:07:17 +00:00
return (3) if ($conf & 0x0C) == 0x08;
return ;
}
1999-02-18 18:09:14 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
2004-02-11 22:07:02 +00:00
# Returns: undef if not detected, 1 to 3 if detected.
1999-02-18 18:09:14 +00:00
# Registers used:
2004-02-11 22:07:02 +00:00
# 0x00: Configuration register
1999-02-18 18:09:14 +00:00
# 0x02: Interrupt state register
2004-02-11 22:07:02 +00:00
# 0x2a-0x3d: Limits registers
# This one is easily misdetected since it doesn't provide identification
# registers. So we have to use some tricks:
# - 6-bit addressing, so limits readings modulo 0x40 should be unchanged
# - positive temperature limits
# - limits order correctness
# Hopefully this should limit the rate of false positives, without increasing
# the rate of false negatives.
# Thanks to Lennard Klein for testing on a non-LM80 chip, which was
# previously misdetected, and isn't anymore. For reference, it scored
# a final confidence of 0, and changing from strict limit comparisons
# to loose comparisons did not change the score.
1999-02-18 18:09:14 +00:00
sub lm80_detect
{
2003-11-21 23:12:04 +00:00
my ($i,$reg);
1999-02-18 18:09:14 +00:00
my ($file,$addr) = @_;
2004-02-11 22:07:02 +00:00
return if (i2c_smbus_read_byte_data($file,0x00) & 0x80) != 0;
2000-08-18 00:28:00 +00:00
return if (i2c_smbus_read_byte_data($file,0x02) & 0xc0) != 0;
2004-02-11 22:07:02 +00:00
1999-02-18 18:09:14 +00:00
for ($i = 0x2a; $i <= 0x3d; $i++) {
2003-11-21 23:12:04 +00:00
$reg = i2c_smbus_read_byte_data($file,$i);
1999-02-18 21:14:48 +00:00
return if i2c_smbus_read_byte_data($file,$i+0x40) != $reg;
return if i2c_smbus_read_byte_data($file,$i+0x80) != $reg;
return if i2c_smbus_read_byte_data($file,$i+0xc0) != $reg;
1999-02-18 18:09:14 +00:00
}
2003-11-21 23:12:04 +00:00
2004-02-11 22:07:02 +00:00
# Refine a bit by checking wether limits are in the correct order
# (min<max for voltages, hyst<max for temperature). Since it is still
# possible that the chip is an LM80 with limits not properly set,
# a few "errors" are tolerated.
my $confidence = 0;
for ($i = 0x2a; $i <= 0x3a; $i++) {
$confidence++
if i2c_smbus_read_byte_data($file,$i) < i2c_smbus_read_byte_data($file,$i+1);
2003-11-21 23:12:04 +00:00
}
2004-02-11 22:07:02 +00:00
# hot temp<OS temp
$confidence++
if i2c_smbus_read_byte_data($file,0x38) < i2c_smbus_read_byte_data($file,0x3a);
# Negative temperature limits are unlikely.
for ($i = 0x3a; $i <= 0x3d; $i++) {
$confidence++ if (i2c_smbus_read_byte_data($file,$i) & 0x80) == 0;
}
# $confidence is between 0 and 14
$confidence = ($confidence >> 1) - 4;
# $confidence is now between -4 and 3
return unless $confidence > 0;
return $confidence;
1999-02-18 18:09:14 +00:00
}
2002-06-30 20:34:35 +00:00
2003-07-03 17:28:16 +00:00
# $_[0]: Chip to detect
2003-07-19 22:09:39 +00:00
# (0 = LM83, 1 = LM82)
2003-07-03 17:28:16 +00:00
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
2003-07-19 22:09:39 +00:00
# Returns: undef if not detected, 5 to 8 if detected.
2003-07-03 17:28:16 +00:00
# Registers used:
2003-08-07 13:03:25 +00:00
# 0x02: Status 1
2003-07-19 22:09:39 +00:00
# 0x03: Configuration
2003-07-03 17:28:16 +00:00
# 0x04: Company ID of LM84
2003-08-07 13:03:25 +00:00
# 0x35: Status 2
2003-07-03 17:28:16 +00:00
# 0xfe: Manufacturer ID
2003-07-19 22:09:39 +00:00
# 0xff: Chip ID / die revision
# We can use the LM84 Company ID register because the LM83 and the LM82 are
# compatible with the LM84.
2003-08-07 13:03:25 +00:00
# The LM83 chip ID is missing from the datasheet and was contributed by
# Magnus Forsstrom.
2003-07-03 17:28:16 +00:00
sub lm83_detect
{
2003-07-19 22:09:39 +00:00
my ($chip, $file) = @_;
2003-08-07 13:03:25 +00:00
return if i2c_smbus_read_byte_data($file,0xfe) != 0x01;
return if $chip == 0 and i2c_smbus_read_byte_data($file,0xff) != 0x03;
return if $chip == 1 and i2c_smbus_read_byte_data($file,0xff) != 0x01;
my $confidence = 4;
$confidence++
if (i2c_smbus_read_byte_data($file,0x02) & 0xa8) == 0x00;
$confidence++
if (i2c_smbus_read_byte_data($file,0x03) & 0x41) == 0x00;
$confidence++
if i2c_smbus_read_byte_data($file,0x04) == 0x00;
$confidence++
if $chip == 0
&& (i2c_smbus_read_byte_data($file,0x35) & 0x48) == 0x00;
return $confidence;
2003-07-03 17:28:16 +00:00
}
2003-07-07 10:31:41 +00:00
# $_[0]: Chip to detect
2003-08-30 20:53:29 +00:00
# (0 = LM90, 1=LM89, 2=LM86, 3=ADM1032, 4=MAX6657/MAX6658)
2003-07-07 10:31:41 +00:00
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
2003-08-30 20:53:29 +00:00
# Returns: undef if not detected, 3, 7 or 8 if detected.
2003-09-08 17:38:23 +00:00
# The Maxim chips have a low confidence value (3)
2003-08-30 20:53:29 +00:00
# because the die revision codes are not known.
2003-07-07 10:31:41 +00:00
# Registers used:
# 0x03: Configuration
# 0xfe: Manufacturer ID
# 0xff: Chip ID / die revision
sub lm90_detect
{
2003-08-30 20:53:29 +00:00
my ($chip, $file, $addr) = @_;
my $mid = i2c_smbus_read_byte_data($file, 0xfe);
my $cid = i2c_smbus_read_byte_data($file, 0xff);
my $conf = i2c_smbus_read_byte_data($file, 0x03);
2003-07-19 22:09:39 +00:00
if ($chip == 0) {
2003-08-30 20:53:29 +00:00
return if ($conf & 0x2a) != 0;
return if $mid != 0x01; # National Semicondutor
return 8 if $cid == 0x21; # LM90
return 7 if $cid > 0x21 and $cid < 0x30;
2003-07-19 22:09:39 +00:00
}
if ($chip == 1) {
2003-08-30 20:53:29 +00:00
return if ($conf & 0x2a) != 0;
return if $mid != 0x01; # National Semicondutor
return 8 if $cid == 0x31; # LM89
return 7 if $cid > 0x31 and $cid < 0x40;
2003-07-19 22:09:39 +00:00
}
if ($chip == 2) {
2003-08-30 20:53:29 +00:00
return if ($conf & 0x2a) != 0;
return if $mid != 0x01; # National Semicondutor
return 8 if $cid == 0x11; # LM86
return 7 if $cid > 0x11 and $cid < 0x20;
}
if ($chip == 3) {
return if ($conf & 0x3f) != 0;
return if $mid != 0x41; # Analog Devices
2003-09-08 17:38:23 +00:00
return 8 if ($cid & 0xf0) == 0x40; # ADM1032
2003-08-30 20:53:29 +00:00
}
if ($chip == 4) {
return if ($conf & 0x1f) != 0;
return if $mid != 0x4d; # Maxim
return 3;
2003-07-19 22:09:39 +00:00
}
return;
2003-07-07 10:31:41 +00:00
}
2003-11-08 11:13:46 +00:00
# $_[0]: Chip to detect
# (0 = ADM1029)
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
# Returns: undef if not detected, 3 to 9 if detected.
# Registers used:
# 0x02, 0x03: Fan support
# 0x05: GPIO config
# 0x07, 0x08, 0x09: Fan config
# 0x0d: Manufacturer ID
# 0x0e: Chip ID / die revision
sub adm1029_detect
{
my ($chip, $file, $addr) = @_;
my $mid = i2c_smbus_read_byte_data($file, 0x0d);
my $cid = i2c_smbus_read_byte_data($file, 0x0e);
my $fansc = i2c_smbus_read_byte_data($file, 0x02);
my $fanss = i2c_smbus_read_byte_data($file, 0x03);
my $gpio = i2c_smbus_read_byte_data($file, 0x05);
my $fanas = i2c_smbus_read_byte_data($file, 0x07);
my $fanhps = i2c_smbus_read_byte_data($file, 0x08);
my $fanfs = i2c_smbus_read_byte_data($file, 0x09);
my $confidence = 3;
if ($chip == 0) {
return if $mid != 0x41; # Analog Devices
$confidence++ if ($cid & 0xF0) == 0x00; # ADM1029
$confidence+=2 if ($fansc & 0xFC) == 0x00
&& ($fanss & 0xFC) == 0x00;
$confidence+=2 if ($fanas & 0xFC) == 0x00
&& ($fanhps & 0xFC) == 0x00
&& ($fanfs & 0xFC) == 0x00;
$confidence++ if ($gpio & 0x80) == 0x00;
return $confidence;
}
return;
}
# $_[0]: Chip to detect
# (0 = ADM1030, 1=ADM1031)
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
# Returns: undef if not detected, 3 to 7 (ADM1031) or 9 (ADM1030)
# if detected.
# Registers used:
# 0x01: Config 2
# 0x03: Status 2
# 0x0d, 0x0e, 0x0f: Temperature offsets
# 0x22: Fan speed config
# 0x3d: Chip ID
# 0x3e: Manufacturer ID
# 0x3f: Die revision
sub adm1031_detect
{
my ($chip, $file, $addr) = @_;
my $mid = i2c_smbus_read_byte_data($file, 0x3e);
my $cid = i2c_smbus_read_byte_data($file, 0x3d);
my $drev = i2c_smbus_read_byte_data($file, 0x3f);
my $conf2 = i2c_smbus_read_byte_data($file, 0x01);
my $stat2 = i2c_smbus_read_byte_data($file, 0x03);
my $fsc = i2c_smbus_read_byte_data($file, 0x22);
my $lto = i2c_smbus_read_byte_data($file, 0x0d);
my $r1to = i2c_smbus_read_byte_data($file, 0x0e);
my $r2to = i2c_smbus_read_byte_data($file, 0x0f);
my $confidence = 3;
if ($chip == 0) {
return if $mid != 0x41; # Analog Devices
return if $cid != 0x30; # ADM1030
$confidence++ if ($drev & 0x70) == 0x00;
$confidence++ if ($conf2 & 0x4A) == 0x00;
$confidence++ if ($stat2 & 0x3F) == 0x00;
$confidence++ if ($fsc & 0xF0) == 0x00;
$confidence++ if ($lto & 0x70) == 0x00;
$confidence++ if ($r1to & 0x70) == 0x00;
return $confidence;
}
if ($chip == 1) {
return if $mid != 0x41; # Analog Devices
return if $cid != 0x31; # ADM1031
$confidence++ if ($drev & 0x70) == 0x00;
$confidence++ if ($lto & 0x70) == 0x00;
$confidence++ if ($r1to & 0x70) == 0x00;
$confidence++ if ($r2to & 0x70) == 0x00;
return $confidence;
}
return;
}
2003-03-17 02:34:10 +00:00
# $_[0]: Vendor to check for
# (0x01 = National Semi, 0x41 = Analog Dev)
# $_[1]: A reference to the file descriptor to access this chip.
# #_[2]: Base address.
2002-06-30 20:34:35 +00:00
# Returns: undef if not detected, (7) if detected.
# Registers used: 0x3e == Vendor register.
# 0x3f == Version/Stepping register.
# Constants used: 0x01 == National Semiconductor Vendor Id.
2003-03-17 02:34:10 +00:00
# 0x41 == Analog Devices Vendor Id.
2003-05-31 00:24:07 +00:00
# 0x5c == SMSC Vendor Id.
2002-06-30 20:34:35 +00:00
# 0x60 == Version number. The lower 4 stepping
# bits are masked and ignored.
sub lm85_detect
{
2003-03-17 02:34:10 +00:00
my ($vendor,$file,$addr) = @_;
return if (i2c_smbus_read_byte_data($file,0x3e)) != $vendor ;
2002-06-30 20:34:35 +00:00
return if (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) != 0x60;
return (7);
}
2000-07-25 01:07:00 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, (7) if detected.
# Registers used: 0x3E, 0x3F
# Assume lower 2 bits of reg 0x3F are for revisions.
sub lm87_detect
{
my ($file,$addr) = @_;
return if (i2c_smbus_read_byte_data($file,0x3e)) != 0x02;
return if (i2c_smbus_read_byte_data($file,0x3f) & 0xfc) != 0x04;
return (7);
}
1999-10-30 21:26:21 +00:00
# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S,
2003-07-26 09:37:12 +00:00
# 3 = W83627HF, 4 = AS99127F (rev.1),
# 5 = AS99127F (rev.2), 6 = ASB100, 7 = W83791D
1999-02-22 18:20:35 +00:00
# $_[1]: A reference to the file descriptor to access this chip.
1999-02-18 21:14:48 +00:00
# We may assume an i2c_set_slave_addr was already done.
1999-02-22 18:20:35 +00:00
# $_[2]: Address
1999-02-18 21:14:48 +00:00
# Returns: undef if not detected, (8,addr1,addr2) if detected, but only
# if the LM75 chip emulation is enabled.
# Registers used:
# 0x48: Full I2C Address
# 0x4a: I2C addresses of emulated LM75 chips
# 0x4e: Vendor ID byte selection, and bank selection
# 0x4f: Vendor ID
2003-07-27 10:37:32 +00:00
# 0x58: Device ID (only when in bank 0)
1999-02-22 18:20:35 +00:00
# Note: Fails if the W8378xD is not in bank 0!
1999-02-18 21:14:48 +00:00
# Note: Detection overrules a previous LM78 detection
2003-07-26 09:37:12 +00:00
# Note: Asus chips do not have their I2C address at register 0x48?
2003-07-31 07:24:29 +00:00
# AS99127F rev.1 and ASB100 have 0x00, confirmation wanted for
# AS99127F rev.2.
1999-02-18 21:14:48 +00:00
sub w83781d_detect
{
my ($reg1,$reg2,@res);
my ($chip,$file,$addr) = @_;
2003-07-26 09:37:12 +00:00
1999-11-12 03:13:22 +00:00
return unless (i2c_smbus_read_byte_data($file,0x48) == $addr)
2003-07-26 09:37:12 +00:00
or ($chip >= 4 && $chip <= 6);
1999-02-18 21:14:48 +00:00
$reg1 = i2c_smbus_read_byte_data($file,0x4e);
$reg2 = i2c_smbus_read_byte_data($file,0x4f);
2003-07-26 09:37:12 +00:00
if ($chip == 4) { # Asus AS99127F (rev.1)
return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or
(($reg1 & 0x80) == 0x80 and $reg2 == 0x12);
} elsif ($chip == 6) { # Asus ASB100
return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0x94) or
(($reg1 & 0x80) == 0x80 and $reg2 == 0x06);
} else { # Winbond and Asus AS99127F (rev.2)
1999-10-30 21:26:21 +00:00
return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or
(($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
}
2003-07-26 09:37:12 +00:00
1999-02-22 20:40:16 +00:00
return unless ($reg1 & 0x07) == 0x00;
2003-07-26 09:37:12 +00:00
$reg1 = i2c_smbus_read_byte_data($file,0x58);
return if $chip == 0 and ($reg1 != 0x10 && $reg1 != 0x11);
1999-02-22 18:20:35 +00:00
return if $chip == 1 and $reg1 != 0x30;
return if $chip == 2 and $reg1 != 0x40;
2003-10-25 18:53:48 +00:00
return if $chip == 3 and $reg1 != 0x21;
2003-07-26 09:37:12 +00:00
return if $chip == 4 and $reg1 != 0x31;
return if $chip == 5 and $reg1 != 0x31;
return if $chip == 6 and $reg1 != 0x31;
2003-10-28 19:17:04 +00:00
return if $chip == 7 and $reg1 != 0x71;
1999-02-18 21:14:48 +00:00
$reg1 = i2c_smbus_read_byte_data($file,0x4a);
@res = (8);
2003-07-31 07:32:09 +00:00
@res = (7) # Asus chips were always seen at 0x2d
2003-08-01 09:17:17 +00:00
if ($chip >= 4 && $chip <= 6 && $addr != 0x2d);
push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08;
2003-07-26 09:37:12 +00:00
push @res, (($reg1 & 0x70) >> 4) + 0x48 unless ($reg1 & 0x80 or $chip == 2);
1999-02-18 21:14:48 +00:00
return @res;
}
2003-07-27 10:37:32 +00:00
# $_[0]: Chip to detect (0 = ASM58, 1 = AS2K129R, 2 = ???)
# $_[1]: A reference to the file descriptor to access this chip
# $_[2]: Address (unused)
# Returns: undef if not detected, 5 if detected
# Registers used:
# 0x4e: Vendor ID high byte
# 0x4f: Vendor ID low byte
# 0x58: Device ID
# Note: The values were given by Alex van Kaam, we don't have datasheets
# to confirm.
sub mozart_detect
{
my ($vid,$dev);
my ($chip,$file,$addr) = @_;
$vid = (i2c_smbus_read_byte_data($file,0x4e) << 8)
+ i2c_smbus_read_byte_data($file,0x4f);
$dev = i2c_smbus_read_byte_data($file,0x58);
return if ($chip == 0) and ($dev != 0x56 || $vid != 0x9436);
return if ($chip == 1) and ($dev != 0x56 || $vid != 0x9406);
return if ($chip == 2) and ($dev != 0x10 || $vid != 0x5ca3);
return 5;
}
1999-08-15 20:23:31 +00:00
# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S, 3 = W83627HF)
1999-02-23 20:28:05 +00:00
# $_[1]: ISA address
# $_[2]: I2C file handle
# $_[3]: I2C address
sub w83781d_alias_detect
{
my ($chip,$isa_addr,$file,$i2c_addr) = @_;
my $i;
my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
return 0 unless &$readproc(0x48) == $i2c_addr;
for ($i = 0x2b; $i <= 0x3d; $i ++) {
1999-02-24 01:33:18 +00:00
return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
1999-02-23 20:28:05 +00:00
}
return 1;
}
2000-05-20 19:45:13 +00:00
# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF, 5 = W83697HF)
# (W83783S and AS99127F not on ISA bus)
1999-02-23 14:14:32 +00:00
# $_[1]: Address
1999-02-22 20:40:16 +00:00
# Returns: undef if not detected, (8) if detected.
sub w83781d_isa_detect
{
1999-02-23 14:14:32 +00:00
my ($chip,$addr) = @_ ;
1999-04-02 22:38:47 +00:00
my ($reg1,$reg2);
1999-02-23 14:14:32 +00:00
my $val = inb ($addr + 1);
1999-03-24 21:28:22 +00:00
return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
1999-02-22 20:40:16 +00:00
inb ($addr + 7) != $val;
LM78 insmod parameters and better detection
Supported insmod parameters:
ignore, ignore_range
probe, probe_range
force, force_lm78, force_lm78j, force_lm79
force* overrules ignore* overrules probe*
The *_range parameters need three elements for each specification:
bus,start_addr,end_addr
The address ranges are inclusive.
The other parameters need two elements for each specification:
bus,addr
In each case, '-1' stands for 'any I2C bus', and 9191 stands for
'the ISA bus' (Bonus question: who can figure out why I choose 9191?)
In each case, just append if you want several specification, for example:
insmod lm78 probe=9191,0x2a0,1,0x56
force_* does no detection, not even chip detection; it blindly assumes
you know what you are doing. plain force does the chip detection, but
nothing else; but it can still fail if the register read-out does not
match a chip type.
Detection is done in exactly the same way as sensors-detect, except that
only the range 0x20-0x2f is examined by default. This needs to be
synchronized somehow with the detect script. I would rather scan the whole
I2C address range, but with those clueless PIIX4 hangs when clock chips
are read, that would simply give too much trouble.
The detect script has slightly better ISA detection now, too.
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@325 7894878c-1315-0410-8ee3-d5d059ff63e0
1999-03-19 06:25:02 +00:00
$val = inb($addr + 5) & 0x7f;
2003-06-11 08:28:55 +00:00
outb($addr+5, ~$val & 0xff);
LM78 insmod parameters and better detection
Supported insmod parameters:
ignore, ignore_range
probe, probe_range
force, force_lm78, force_lm78j, force_lm79
force* overrules ignore* overrules probe*
The *_range parameters need three elements for each specification:
bus,start_addr,end_addr
The address ranges are inclusive.
The other parameters need two elements for each specification:
bus,addr
In each case, '-1' stands for 'any I2C bus', and 9191 stands for
'the ISA bus' (Bonus question: who can figure out why I choose 9191?)
In each case, just append if you want several specification, for example:
insmod lm78 probe=9191,0x2a0,1,0x56
force_* does no detection, not even chip detection; it blindly assumes
you know what you are doing. plain force does the chip detection, but
nothing else; but it can still fail if the register read-out does not
match a chip type.
Detection is done in exactly the same way as sensors-detect, except that
only the range 0x20-0x2f is examined by default. This needs to be
synchronized somehow with the detect script. I would rather scan the whole
I2C address range, but with those clueless PIIX4 hangs when clock chips
are read, that would simply give too much trouble.
The detect script has slightly better ISA detection now, too.
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@325 7894878c-1315-0410-8ee3-d5d059ff63e0
1999-03-19 06:25:02 +00:00
if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
outb($addr+5,$val);
return;
}
1999-02-23 14:14:32 +00:00
my $read_proc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
$reg1 = &$read_proc(0x4e);
$reg2 = &$read_proc(0x4f);
return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or
(($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
return unless ($reg1 & 0x07) == 0x00;
1999-03-24 21:28:22 +00:00
$reg1 = &$read_proc(0x58) & 0xfe;
return if $chip == 0 and $reg1 != 0x10;
1999-02-23 14:14:32 +00:00
return if $chip == 1 and $reg1 != 0x30;
1999-08-15 20:23:31 +00:00
return if $chip == 3 and $reg1 != 0x20;
2000-05-20 19:45:13 +00:00
return if $chip == 5 and $reg1 != 0x60;
1999-02-24 01:16:40 +00:00
return 8;
1999-02-22 20:40:16 +00:00
}
1999-02-18 21:14:48 +00:00
# $_[0]: Chip to detect (0 = Revision 0x00, 1 = Revision 0x80)
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
# Returns: undef if not detected, (6) if detected.
# Registers used:
# 0x00: Device ID
# 0x01: Revision ID
# 0x03: Configuration
# Mediocre detection
sub gl518sm_detect
{
my $reg;
my ($chip,$file,$addr) = @_;
return unless i2c_smbus_read_byte_data($file,0x00) == 0x80;
1999-02-19 02:30:17 +00:00
return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
1999-02-18 21:14:48 +00:00
$reg = i2c_smbus_read_byte_data($file,0x01);
return unless ($chip == 0 and $reg == 0x00) or
($chip == 1 and $reg == 0x80);
return (6);
}
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, (5) if detected.
# Registers used:
# 0x00: Device ID
# 0x01: Revision ID
# 0x03: Configuration
# Mediocre detection
sub gl520sm_detect
{
my ($file,$addr) = @_;
return unless i2c_smbus_read_byte_data($file,0x00) == 0x20;
1999-02-19 02:30:17 +00:00
return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
1999-02-18 21:14:48 +00:00
# The line below must be better checked before I dare to use it.
# return unless i2c_smbus_read_byte_data($file,0x01) == 0x00;
return (5);
}
1999-10-20 02:53:38 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, (5) if detected.
# Registers used:
# 0x00: Device ID
# Mediocre detection
sub gl525sm_detect
{
my ($file,$addr) = @_;
return unless i2c_smbus_read_byte_data($file,0x00) == 0x25;
return (5);
}
1999-08-22 17:52:38 +00:00
# $_[0]: Chip to detect (0 = ADM9240, 1 = DS1780, 2 = LM81)
1999-03-29 00:58:55 +00:00
# $_[1]: A reference to the file descriptor to access this chip.
1999-02-18 21:14:48 +00:00
# We may assume an i2c_set_slave_addr was already done.
1999-03-29 00:58:55 +00:00
# $_[2]: Address
1999-08-28 19:10:27 +00:00
# Returns: undef if not detected, (7) if detected.
1999-02-18 21:14:48 +00:00
# Registers used:
# 0x3e: Company ID
# 0x40: Configuration
# 0x48: Full I2C Address
# Note: Detection overrules a previous LM78 detection
sub adm9240_detect
{
1999-03-29 00:58:55 +00:00
my $reg;
my ($chip, $file,$addr) = @_;
$reg = i2c_smbus_read_byte_data($file,0x3e);
return unless ($chip == 0 and $reg == 0x23) or
1999-08-22 17:52:38 +00:00
($chip == 1 and $reg == 0xda) or
($chip == 2 and $reg == 0x01);
1999-02-19 02:30:17 +00:00
return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
1999-02-18 21:14:48 +00:00
return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
1999-08-28 19:10:27 +00:00
return (7);
}
# $_[0]: Chip to detect (0 = ADM1022, 1 = THMC50)
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
# Returns: undef if not detected, (8) if detected.
# Registers used:
# 0x3e: Company ID
# 0x3f: Revision
# 0x40: Configuration
# Note: Detection overrules a previous LM78 or ADM9240 detection
sub adm1022_detect
{
my $reg;
my ($chip, $file,$addr) = @_;
$reg = i2c_smbus_read_byte_data($file,0x3e);
return unless ($chip == 0 and $reg == 0x41) or
($chip == 1 and $reg == 0x49);
return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xc0) == 0xc0;
1999-02-18 21:14:48 +00:00
return (8);
}
2003-07-26 17:39:41 +00:00
# $_[0]: Chip to detect (0 = ADM1025, 1 = NE1619)
2000-03-19 22:06:54 +00:00
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
# Returns: undef if not detected, (8) if detected.
# Registers used:
# 0x3e: Company ID
# 0x3f: Revision
# 0x40: Configuration
# Note: Detection overrules a previous LM78 or ADM9240 detection
sub adm1025_detect
{
my $reg;
my ($chip, $file,$addr) = @_;
2003-07-26 17:39:41 +00:00
2000-03-19 22:06:54 +00:00
$reg = i2c_smbus_read_byte_data($file,0x3e);
2003-07-26 17:39:41 +00:00
return if ($chip == 0) and ($reg != 0x41);
return if ($chip == 1) and ($reg != 0xA1);
2000-03-19 22:06:54 +00:00
return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
2001-06-22 01:06:04 +00:00
return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x20;
2003-07-26 17:39:41 +00:00
2000-03-19 22:06:54 +00:00
return (8);
}
2003-06-08 21:33:39 +00:00
# $_[0]: Chip to detect (0 = ADM1026)
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
# Returns: undef if not detected, (8) if detected.
# Registers used:
# 0x16: Company ID
# 0x17: Revision
sub adm1026_detect
{
my $reg;
my ($chip, $file,$addr) = @_;
$reg = i2c_smbus_read_byte_data($file,0x16);
return unless ($reg == 0x41);
return unless (i2c_smbus_read_byte_data($file,0x17) & 0xf0) == 0x40;
return (8);
}
2001-05-15 03:18:18 +00:00
# $_[0]: Chip to detect (0 = ADM1024)
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
# Returns: undef if not detected, (8) if detected.
# Registers used:
# 0x3e: Company ID
# 0x3f: Revision
# 0x40: Configuration
sub adm1024_detect
{
my $reg;
my ($chip, $file,$addr) = @_;
$reg = i2c_smbus_read_byte_data($file,0x3e);
return unless ($reg == 0x41);
return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
2001-06-22 01:06:04 +00:00
return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x10;
2001-05-15 03:18:18 +00:00
return (8);
}
1999-10-20 01:51:27 +00:00
# $_[0]: Chip to detect
2003-07-04 08:13:35 +00:00
# (0 = ADM1021, 1 = ADM1021A/ADM1023, 2 = MAX1617, 3 = MAX1617A, 4 = THMC10,
# 5 = LM84, 6 = GL523, 7 = MC1066)
1999-02-18 21:14:48 +00:00
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
2003-10-11 13:35:01 +00:00
# Returns: undef if not detected, 3 if simply detected, 5 if detected and
2003-07-04 08:13:35 +00:00
# manufacturer ID matches, 7 if detected and manufacturer ID and
# revision match
1999-02-18 21:14:48 +00:00
# Registers used:
1999-10-20 02:13:51 +00:00
# 0x04: Company ID (LM84 only)
2003-07-04 08:13:35 +00:00
# 0xfe: Company ID (all but LM84 and MAX1617)
# 0xff: Revision (ADM1021, ADM1021A/ADM1023 and MAX1617A)
1999-02-18 21:14:48 +00:00
# 0x02: Status
2003-10-10 20:57:40 +00:00
# 0x00-0x01, 0x05-0x08: Temperatures (MAX1617 and LM84)
2003-07-04 08:13:35 +00:00
# Note: Especially the MAX1617 has very bad detection; we give it a low
1999-02-18 21:14:48 +00:00
# confidence value.
sub adm1021_detect
{
my ($chip, $file,$addr) = @_;
2003-07-04 08:13:35 +00:00
return if $chip == 0 and i2c_smbus_read_byte_data($file,0xfe) != 0x41 ||
(i2c_smbus_read_byte_data($file,0xff) & 0xf0) != 0x00;
return if $chip == 1 and i2c_smbus_read_byte_data($file,0xfe) != 0x41 ||
(i2c_smbus_read_byte_data($file,0xff) & 0xf0) != 0x30;
return if $chip == 4 and i2c_smbus_read_byte_data($file,0xfe) != 0x49;
return if $chip == 5 and i2c_smbus_read_byte_data($file,0x04) != 0x00;
return if $chip == 6 and i2c_smbus_read_byte_data($file,0xfe) != 0x23;
return if $chip == 3 and i2c_smbus_read_byte_data($file,0xfe) != 0x4d ||
1999-04-10 00:05:10 +00:00
i2c_smbus_read_byte_data($file,0xff) != 0x01;
2003-07-04 08:13:35 +00:00
return if $chip == 7 and i2c_smbus_read_byte_data($file,0xfe) != 0x54;
1999-02-18 21:14:48 +00:00
# The remaining things are flaky at best. Perhaps something can be done
# with the fact that some registers are unreadable?
1999-02-19 02:30:17 +00:00
return if (i2c_smbus_read_byte_data($file,0x02) & 0x03) != 0;
2003-10-10 20:57:40 +00:00
# Extra checks for MAX1617 and LM84, since those are often misdetected
if ($chip == 2 || $chip == 5)
{
# Increase the misdetect value each time a temperature doesn't
# match reasonable expectations
my $misdetect = 0;
# Negative temperatures
2003-12-13 09:41:38 +00:00
$misdetect++ if ((my $lte=i2c_smbus_read_byte_data($file,0x00)) & 0x80);
$misdetect++ if ((my $rte=i2c_smbus_read_byte_data($file,0x01)) & 0x80);
2003-10-10 20:57:40 +00:00
# Negative high limits
2003-12-13 09:41:38 +00:00
my ($lhi, $rhi);
if (($lhi=i2c_smbus_read_byte_data($file,0x05)) & 0x80)
{
$misdetect++;
$lhi-=256;
}
if (($rhi=i2c_smbus_read_byte_data($file,0x07)) & 0x80)
{
$misdetect++;
$rhi-=256;
}
2003-10-10 20:57:40 +00:00
# Low limits over high limits
my $llo=i2c_smbus_read_byte_data($file,0x06);
my $rlo=i2c_smbus_read_byte_data($file,0x08);
2003-12-13 09:41:38 +00:00
$llo-=256 if ($llo & 0x80);
$rlo-=256 if ($rlo & 0x80);
2003-10-10 20:57:40 +00:00
$misdetect++ if $llo > $lhi;
$misdetect++ if $rlo > $rhi;
return if $misdetect >= 4;
2003-10-11 13:35:01 +00:00
# Also return if all six bytes have the same value
return if $lte == $rte and $lte == $lhi and $lte == $rhi
and $lte == $llo and $lte == $rlo;
2003-10-10 20:57:40 +00:00
}
2003-07-04 08:13:35 +00:00
return 3 if $chip == 2;
return 7 if $chip <= 3;
2003-10-11 13:35:01 +00:00
return 5;
1999-02-18 21:14:48 +00:00
}
1999-02-17 20:55:23 +00:00
1999-02-23 23:16:09 +00:00
# $_[0]: Address
# Returns: undef if not detected, (9) if detected.
# Note: It is already 99% certain this chip exists if we find the PCI
# entry. The exact address is encoded in PCI space.
sub sis5595_isa_detect
{
my ($addr) = @_;
1999-03-09 16:19:30 +00:00
my ($adapter,$try,$local_try);
1999-02-23 23:16:09 +00:00
my $found = 0;
1999-03-09 16:19:30 +00:00
foreach $local_try (@pci_adapters) {
2000-02-29 15:28:42 +00:00
if ($local_try->{procid} eq "Silicon Integrated Systems SIS5595") {
1999-03-09 16:19:30 +00:00
$try = $local_try;
1999-02-23 23:16:09 +00:00
$found = 1;
last;
}
}
return if not $found;
$found = 0;
1999-02-24 01:12:05 +00:00
foreach $adapter (@pci_list) {
1999-03-09 16:19:30 +00:00
if ((defined($adapter->{vendid}) and
1999-02-23 23:16:09 +00:00
$try->{vendid} == $adapter->{vendid} and
$try->{devid} == $adapter->{devid} and
$try->{func} == $adapter->{func}) or
(! defined($adapter->{vendid}) and
$adapter->{desc} =~ /$try->{procid}/ and
$try->{func} == $adapter->{func})) {
$found = 1;
last;
}
}
return if not $found;
1999-03-09 16:19:30 +00:00
return 9;
}
2000-03-04 16:21:48 +00:00
# $_[0]: Address
# Returns: undef if not detected, (9) if detected.
# Note: It is already 99% certain this chip exists if we find the PCI
# entry. The exact address is encoded in PCI space.
sub via686a_isa_detect
{
my ($addr) = @_;
my ($adapter,$try,$local_try);
my $found = 0;
foreach $local_try (@pci_adapters) {
2001-12-09 18:54:34 +00:00
if ($local_try->{procid} eq "VIA Technologies VT82C686 Apollo ACPI") {
2000-03-04 16:21:48 +00:00
$try = $local_try;
$found = 1;
last;
}
}
return if not $found;
$found = 0;
foreach $adapter (@pci_list) {
2002-05-27 21:21:29 +00:00
if ((defined($adapter->{vendid}) and
$try->{vendid} == $adapter->{vendid} and
$try->{devid} == $adapter->{devid} and
$try->{func} == $adapter->{func}) or
(! defined($adapter->{vendid}) and
$adapter->{desc} =~ /$try->{procid}/ and
$try->{func} == $adapter->{func})) {
$found = 1;
last;
}
}
return if not $found;
return 9;
}
# $_[0]: Address
# Returns: undef if not detected, (9) if detected.
# Note: It is already 99% certain this chip exists if we find the PCI
# entry. The exact address is encoded in PCI space.
sub via8231_isa_detect
{
my ($addr) = @_;
my ($adapter,$try,$local_try);
my $found = 0;
foreach $local_try (@pci_adapters) {
if ($local_try->{procid} eq "VIA Technologies VT8231 South Bridge") {
$try = $local_try;
$found = 1;
last;
}
}
return if not $found;
$found = 0;
foreach $adapter (@pci_list) {
2000-03-04 16:21:48 +00:00
if ((defined($adapter->{vendid}) and
$try->{vendid} == $adapter->{vendid} and
$try->{devid} == $adapter->{devid} and
$try->{func} == $adapter->{func}) or
(! defined($adapter->{vendid}) and
$adapter->{desc} =~ /$try->{procid}/ and
$try->{func} == $adapter->{func})) {
$found = 1;
last;
}
}
return if not $found;
return 9;
}
2000-08-06 17:03:09 +00:00
# $_[0]: Chip to detect (0 = ..., 1 = ...)
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
2002-01-05 16:17:22 +00:00
# Returns: undef if not detected, 8 if detected (tops LM78).
2000-08-06 17:03:09 +00:00
# Registers used:
2001-12-19 19:29:31 +00:00
# 0x00: Configuration
2000-08-06 17:03:09 +00:00
# 0x48: Full I2C Address
# 0x58: Mfr ID
# Note that this function is always called through a closure, so the
# arguments are shifted by one place.
sub ite_detect
{
my $reg;
my ($chip,$file,$addr) = @_;
return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
2001-12-19 19:29:31 +00:00
return unless (i2c_smbus_read_byte_data($file,0x00) & 0x80) == 0x00;
2000-08-06 17:03:09 +00:00
return unless i2c_smbus_read_byte_data($file,0x58) == 0x90;
2002-01-05 16:17:22 +00:00
return (8);
2000-08-06 17:03:09 +00:00
}
# $_[0]: Chip to detect (0 = ..., 1 = ...)
# $_[1]: Address
2002-01-05 16:17:22 +00:00
# Returns: undef if not detected, 8 if detected (tops LM78).
2000-08-06 17:03:09 +00:00
# Note: Only address 0x290 is scanned at this moment.
sub ite_isa_detect
{
my ($chip,$addr) = @_ ;
my $val = inb ($addr + 1);
return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
inb ($addr + 7) != $val;
$val = inb($addr + 5) & 0x7f;
2003-06-11 08:28:55 +00:00
outb($addr+5, ~$val & 0xff);
2000-08-06 17:03:09 +00:00
if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
outb($addr+5,$val);
return;
}
my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
2001-12-19 19:29:31 +00:00
return unless (&$readproc(0x00) & 0x80) == 0x00;
2000-08-06 17:03:09 +00:00
my $reg = &$readproc(0x58);
return unless ($reg == 0x90);
2002-01-05 16:17:22 +00:00
return 8;
2000-08-06 17:03:09 +00:00
}
# $_[0]: Chip to detect (0 = ..., 1 = ...)
# $_[1]: ISA address
# $_[2]: I2C file handle
# $_[3]: I2C address
sub ite_alias_detect
{
my ($chip,$isa_addr,$file,$i2c_addr) = @_;
my $i;
my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
return 0 unless &$readproc(0x48) == $i2c_addr;
for ($i = 0x2b; $i <= 0x3d; $i ++) {
return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
}
return 1;
}
2003-08-07 08:51:08 +00:00
# $_[0]: Chip to detect (0 = SPD EEPROM, 1 = Sony Vaio EEPROM)
# $_[1]: A reference to the file descriptor to access this chip
# $_[2]: Address
# Returns: 8 for a memory eeprom, 4 to 9 for a Sony Vaio eeprom,
# 1 for an unknown eeprom
1999-03-09 16:19:30 +00:00
# Registers used:
2003-08-07 08:51:08 +00:00
# 0-63: SPD Data and Checksum
# 0x80-0x83: Sony Vaio Data ("PCG-")
# 0xe2, 0xe5, 0xe8, 0xeb, Oxee: Sony Vaio Timestamp constant bytes.
# 0x1a-0x1c: Sony Vaio MAC address
# This detection function is a bit tricky; this is to workaround
# wrong misdetection messages that would else arise.
1999-03-09 16:19:30 +00:00
sub eeprom_detect
{
2003-08-07 08:51:08 +00:00
my ($chip,$file,$addr) = @_;
# Check the checksum for validity (works for most DIMMs and RIMMs)
1999-03-09 16:19:30 +00:00
my $checksum = 0;
2002-11-13 08:57:42 +00:00
for (my $i = 0; $i <= 62; $i ++) {
$checksum += i2c_smbus_read_byte_data($file,$i);
1999-03-09 16:19:30 +00:00
}
2002-11-13 08:57:42 +00:00
$checksum &= 255;
return 8
2003-08-07 08:51:08 +00:00
if $chip == 0 and i2c_smbus_read_byte_data($file,63) == $checksum;
# Look for a Sony Vaio EEPROM
my $vaioconf = 1;
$vaioconf += 4
if i2c_smbus_read_byte_data($file,0x80) == 0x50
&& i2c_smbus_read_byte_data($file,0x81) == 0x43
&& i2c_smbus_read_byte_data($file,0x82) == 0x47
&& i2c_smbus_read_byte_data($file,0x83) == 0x2d;
$vaioconf += 5
if i2c_smbus_read_byte_data($file,0xe2) == 0x2f
&& i2c_smbus_read_byte_data($file,0xe5) == 0x2f
&& i2c_smbus_read_byte_data($file,0xe8) == 0x20
&& i2c_smbus_read_byte_data($file,0xeb) == 0x3a
&& i2c_smbus_read_byte_data($file,0xee) == 0x3a;
$vaioconf += 3
if i2c_smbus_read_byte_data($file,0x1a) == 0x08
&& i2c_smbus_read_byte_data($file,0x1b) == 0x00
&& i2c_smbus_read_byte_data($file,0x1c) == 0x46;
$vaioconf = 9
if $vaioconf > 9;
if ($vaioconf > 1) {
return if $chip != 1;
return $vaioconf;
2002-11-13 08:57:42 +00:00
}
2003-08-07 08:51:08 +00:00
# Even if all tests fail, it still may be an eeprom
return if $chip != 0;
# Default to SPD EEPROM
2002-11-13 08:57:42 +00:00
return 1;
1999-02-23 23:16:09 +00:00
}
1999-04-08 19:33:03 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, (1) if detected.
# Detection is impossible!
sub ltc1710_detect
{
return (1);
}
1999-12-29 23:10:48 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, (1) if detected.
# Registers used:
# 0x00..0x07: DDC signature
# 0x08..0x7E: checksumed area
# 0x7F: checksum
2000-01-30 01:15:29 +00:00
### commented out additional location checks for now - don't work?
1999-12-29 23:10:48 +00:00
sub ddcmonitor_detect
{
my ($file,$addr) = @_;
my $i;
2000-01-30 01:15:29 +00:00
### for ($i = 0; $i < 8; $i ++) {
### i2c_set_slave_addr \*FILE,$addr+$i or goto FAILURE;
1999-12-29 23:10:48 +00:00
i2c_smbus_read_byte_data($file,0x00) == 0x00 or goto FAILURE;
i2c_smbus_read_byte_data($file,0x01) == 0xFF or goto FAILURE;
i2c_smbus_read_byte_data($file,0x02) == 0xFF or goto FAILURE;
i2c_smbus_read_byte_data($file,0x03) == 0xFF or goto FAILURE;
i2c_smbus_read_byte_data($file,0x04) == 0xFF or goto FAILURE;
i2c_smbus_read_byte_data($file,0x05) == 0xFF or goto FAILURE;
i2c_smbus_read_byte_data($file,0x06) == 0xFF or goto FAILURE;
i2c_smbus_read_byte_data($file,0x07) == 0x00 or goto FAILURE;
2000-01-30 01:15:29 +00:00
### }
### i2c_set_slave_addr \*FILE,$addr or return;
1999-12-29 23:10:48 +00:00
# Check the checksum for validity. We should do this for all addresses,
# but it would be too slow.
my $checksum = 0;
for ($i = 0; $i <= 127; $i = $i + 1) {
$checksum = $checksum + i2c_smbus_read_byte_data($file,$i);
}
$checksum=$checksum & 255;
if ($checksum != 0) {
# I have one such monitor...
return (2,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
}
return (8,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
FAILURE:
i2c_set_slave_addr \*FILE,$addr;
return;
}
1999-04-08 19:33:03 +00:00
2001-09-18 15:20:15 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
2001-09-19 15:57:06 +00:00
# Returns: undef if not detected, (8) if detected.
2001-09-18 15:20:15 +00:00
# Registers used:
2001-11-09 13:35:56 +00:00
# 0x00-0x02: Identification ('P','E','G' -> Pegasus ? :-)
2001-09-18 15:20:15 +00:00
sub fscpos_detect
{
my ($file,$addr) = @_;
# check the first 3 registers
if (i2c_smbus_read_byte_data($file,0x00) != 0x50) {
2001-09-19 15:57:06 +00:00
return;
2001-09-18 15:20:15 +00:00
}
if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
2001-09-19 15:57:06 +00:00
return;
2001-09-18 15:20:15 +00:00
}
if (i2c_smbus_read_byte_data($file,0x02) != 0x47) {
2001-09-19 15:57:06 +00:00
return;
2001-09-18 15:20:15 +00:00
}
2001-09-19 15:57:06 +00:00
return (8);
2001-09-18 15:20:15 +00:00
}
2001-11-09 13:35:56 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, (8) if detected.
# Registers used:
# 0x00-0x02: Identification ('S','C','Y')
sub fscscy_detect
{
my ($file,$addr) = @_;
# check the first 3 registers
if (i2c_smbus_read_byte_data($file,0x00) != 0x53) {
return;
}
if (i2c_smbus_read_byte_data($file,0x01) != 0x43) {
return;
}
if (i2c_smbus_read_byte_data($file,0x02) != 0x59) {
return;
}
return (8);
}
2003-09-27 08:19:20 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, (8) if detected.
# Registers used:
# 0x00-0x02: Identification ('H','E','R')
sub fscher_detect
{
my ($file,$addr) = @_;
# check the first 3 registers
if (i2c_smbus_read_byte_data($file,0x00) != 0x48) {
return;
}
if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
return;
}
if (i2c_smbus_read_byte_data($file,0x02) != 0x52) {
return;
}
return (8);
}
2003-07-18 08:06:05 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: undef if not detected, 4 or 7 if detected
# Detection is based on the fact that the SAA1064 has only one readable
# register, and thus ignores the read address. This register can have value
# 0x80 (first read since power-up) or 0x00.
sub saa1064_detect
{
my ($file,$addr) = @_;
my $status = i2c_smbus_read_byte_data ($file, 0x00);
return if ($status & 0x7f) != 0x00;
for (my $i=0 ; $i<256; $i++) {
return if i2c_smbus_read_byte_data ($file, $i) != 0x00;
}
return 7
if $status == 0x80;
return 4;
}
2001-12-04 00:32:59 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: 1
# This is a placeholder so we get a report if any device responds
# to the SMBus Device Default Address (0x61), which is used for
# ARP in SMBus 2.0.
sub arp_detect
{
return (1);
}
2002-10-13 15:48:34 +00:00
# $_[0]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[1]: Address
# Returns: 1
sub smartbatt_detect
{
my ($file,$addr) = @_;
# check some registers
if (i2c_smbus_read_byte_data($file,0x08) == 0xff) {
return;
}
if (i2c_smbus_read_byte_data($file,0x09) != 0xff) {
return;
}
if (i2c_smbus_read_byte_data($file,0x0a) != 0xff) {
return;
}
return (3);
}
2001-12-31 17:32:54 +00:00
# Returns: 4
# These are simple detectors that only look for a register at the
# standard location. No writes are performed.
# For KCS, use the STATUS register. For SMIC, use the FLAGS register.
sub ipmi_kcs_detect
{
return if inb (0x0ca3) == 0xff;
return (4);
}
sub ipmi_smic_detect
{
return if inb (0x0cab) == 0xff;
return (4);
}
2003-07-26 09:37:12 +00:00
# $_[0]: Chip to detect (0 = W83L784R/AR)
# $_[1]: A reference to the file descriptor to access this chip.
# $_[2]: Address
# Returns: undef if not detected, 8 if detected
# Registers used:
# 0x4a: Full I2C Address
# 0x4b: I2C addresses of emulated LM75 chips
# 0x4c: Winbond Vendor ID (Low Byte)
# 0x4d: Winbond Vendor ID (High Byte)
# 0x4e: Chip ID
# Note that this function is always called through a closure, so the
# arguments are shifted by one place.
sub w83l784r_detect
{
my ($reg,@res);
my ($chip,$file,$addr) = @_;
return unless i2c_smbus_read_byte_data($file,0x4a) == $addr;
return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
return unless i2c_smbus_read_byte_data($file,0x4e) == 0x50;
$reg = i2c_smbus_read_byte_data($file,0x4b);
@res = (8);
push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08 ;
push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
return @res;
}
# $_[0]: Chip to detect (0 = W83L785TS-S)
2003-06-21 15:26:38 +00:00
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
# Returns: undef if not detected, 8 if detected
# Registers used:
# 0x4C-4E: Mfr and Chip ID
# Note that this function is always called through a closure, so the
# arguments are shifted by one place.
sub w83l785ts_detect
{
my ($chip,$file,$addr) = @_;
return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
return unless i2c_smbus_read_byte_data($file,0x4e) == 0x70;
return (8);
}
2003-08-31 20:45:12 +00:00
# $_[0]: Chip to detect. Always zero for now, but available for future use
# if somebody finds a way to distinguish MAX6650 and MAX6651.
# $_[1]: A reference to the file descriptor to access this chip.
# We may assume an i2c_set_slave_addr was already done.
# $_[2]: Address
# Returns: undef if not detected, 4 if detected.
#
# The max6650 has no device ID register. However, a few registers have
# spare bits, which are documented as being always zero on read. We read
# all of these registers check the spare bits. Any non-zero means this
# is not a max6650/1.
#
# The always zero bits are:
# configuration byte register (0x02) - top 2 bits
# gpio status register (0x14) - top 3 bits
# alarm enable register (0x08) - top 3 bits
# alarm status register (0x0A) - top 3 bits
# tachometer count time register (0x16) - top 6 bits
sub max6650_detect
{
my ($chip, $file) = @_;
return if i2c_smbus_read_byte_data($file,0x16) & 0xFC;
return if i2c_smbus_read_byte_data($file,0x0A) & 0xE0;
return if i2c_smbus_read_byte_data($file,0x08) & 0xE0;
return if i2c_smbus_read_byte_data($file,0x14) & 0xE0;
return if i2c_smbus_read_byte_data($file,0x02) & 0xC0;
return 4;
}
2001-12-31 17:32:54 +00:00
2001-11-19 20:29:27 +00:00
1999-02-28 17:41:46 +00:00
################
# MAIN PROGRAM #
################
# $_[0]: reference to a list of chip hashes
sub print_chips_report
{
my ($listref) = @_;
my $data;
foreach $data (@$listref) {
my $is_i2c = exists $data->{i2c_addr};
my $is_isa = exists $data->{isa_addr};
print " * ";
if ($is_i2c) {
printf "Bus `%s' (%s)\n", $data->{i2c_adap}, $data->{i2c_algo};
printf " Busdriver `%s', I2C address 0x%02x",
$data->{i2c_driver}, $data->{i2c_addr};
if (exists $data->{i2c_sub_addrs}) {
print " (and";
my $sub_addr;
foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
printf " 0x%02x",$sub_addr;
}
print ")"
}
print "\n";
}
if ($is_isa) {
print " " if $is_i2c;
if ($data->{isa_addr}) {
printf "ISA bus address 0x%04x (Busdriver `i2c-isa')\n",
$data->{isa_addr};
} else {
printf "ISA bus, undetermined address (Busdriver `i2c-isa')\n"
}
}
printf " Chip `%s' (confidence: %d)\n",
$data->{chipname}, $data->{conf};
}
}
1999-03-09 18:11:26 +00:00
# $_[0]: 1 if ISA bus is prefered, 0 for SMBus
2000-02-01 21:12:43 +00:00
# We build here an array adapters, indexed on the number the adapter has
# at this moment (we assume only loaded adapters are interesting at all;
# everything that got scanned also got loaded). Each entry is a reference
# to a hash containing:
# driver: Name of the adapter driver
# nr_now: Number of the bus now
# nr_later: Number of the bus when the modprobes are done (not included if the
# driver should not be loaded)
# A second array, called
1999-03-09 16:19:30 +00:00
sub generate_modprobes
1999-02-28 16:17:49 +00:00
{
1999-03-09 18:11:26 +00:00
my ($prefer_isa) = @_;
2000-02-01 21:12:43 +00:00
my ($chip,$detection,$nr,$i,@optionlist,@probelist,$driver,$isa,$adap);
my @adapters;
1999-03-09 16:19:30 +00:00
my $modprobes = "";
my $configfile = "";
# These are always needed
$configfile .= "# I2C module options\n";
$configfile .= "alias char-major-89 i2c-dev\n";
2000-02-01 21:12:43 +00:00
# Collect all loaded adapters
2003-11-28 05:10:32 +00:00
# i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
open INPUTFILE,"i2cdetect -l |" or die "Couldn't find i2cdetect program!!";
2000-02-01 21:12:43 +00:00
while (<INPUTFILE>) {
my ($dev_nr,$type,$adap,$algo) = /^i2c-(\S+)\s+(\S+)\s+(.*?)\s*\t\s*(.*?)\s+$/;
next if ($type eq "dummy");
$adapters[$dev_nr]->{driver} = find_adapter_driver($adap,$algo);
2000-06-25 18:34:30 +00:00
$adapters[$dev_nr]->{adapname} = $adap;
$adapters[$dev_nr]->{algoname} = $algo;
2000-02-01 21:12:43 +00:00
}
close INPUTFILE;
# Collect all adapters used
1999-03-09 16:19:30 +00:00
$nr = 0;
2000-02-01 21:12:43 +00:00
$isa = 0;
1999-03-09 16:19:30 +00:00
$modprobes .= "# I2C adapter drivers\n";
foreach $chip (@chips_detected) {
foreach $detection (@{$chip->{detected}}) {
2000-02-01 21:12:43 +00:00
# If there is more than one bus detected by a driver, they are
# still all added. So we number them in the correct order
if (exists $detection->{i2c_driver} and
2000-02-02 20:57:46 +00:00
not exists $adapters[$detection->{i2c_devnr}]->{nr_later} and
2000-02-01 21:12:43 +00:00
not (exists $detection->{isa_addr} and $prefer_isa)) {
foreach $adap (@adapters) {
$adap->{nr_later} = $nr++ if $adap->{driver} eq $detection->{i2c_driver};
}
}
if (exists $detection->{isa_addr} and
not (exists $detection->{i2c_driver} and not $prefer_isa)) {
$isa=1;
}
1999-03-09 16:19:30 +00:00
}
1999-02-28 17:24:41 +00:00
}
2000-02-01 21:12:43 +00:00
for ($i = 0; $i < $nr; $i++) {
foreach $adap (@adapters) {
2000-06-25 18:25:52 +00:00
if ($adap->{driver} eq "UNKNOWN") {
2000-06-25 18:34:30 +00:00
$modprobes .= "# modprobe unknown adapter ".$adap->{adapname}." using ". $adap->{algoname}."\n";
2003-07-17 08:50:05 +00:00
} elsif ($adap->{driver} eq "DISABLED") {
$modprobes .= "# modprobe disabled adapter ".$adap->{adapname}." using ". $adap->{algoname}."\n";
2003-08-07 13:03:25 +00:00
} elsif ($adap->{driver} eq "to-be-written") {
$modprobes .= "# no driver available for adapter ".$adap->{adapname}." using ". $adap->{algoname}."\n";
2000-06-25 18:25:52 +00:00
} else {
$modprobes .= "modprobe $adap->{driver}\n" if (defined($adap->{nr_later}) and $adap->{nr_later} == $i) and not $modprobes =~ /modprobe $adap->{driver}\n/;
}
1999-03-10 20:31:58 +00:00
}
1999-02-28 17:24:41 +00:00
}
2000-02-01 21:12:43 +00:00
$modprobes .= "modprobe i2c-isa\n" if ($isa);
1999-02-28 17:24:41 +00:00
1999-03-09 16:19:30 +00:00
# Now determine the chip probe lines
$modprobes .= "# I2C chip drivers\n";
foreach $chip (@chips_detected) {
next if not @{$chip->{detected}};
2003-08-07 13:03:25 +00:00
if ($chip->{driver} eq "to-be-written") {
2003-08-30 20:58:02 +00:00
$modprobes .= "# no driver for $chip->{detected}[0]{chipname} yet, ask us for one!\n";
2003-08-07 13:03:25 +00:00
} else {
$modprobes .= "modprobe $chip->{driver}\n";
}
1999-03-09 16:19:30 +00:00
@optionlist = ();
1999-03-23 21:48:41 +00:00
@probelist = ();
2000-02-01 21:12:43 +00:00
# Handle detects at addresses normally not probed
1999-03-23 21:48:41 +00:00
foreach $detection (@{$chip->{detected}}) {
2000-02-01 21:12:43 +00:00
push @probelist, $adapters[$detection->{i2c_devnr}]->{nr_later},
1999-03-23 21:48:41 +00:00
$detection->{i2c_addr}
2000-02-01 21:12:43 +00:00
if exists $detection->{i2c_addr} and
1999-03-23 21:48:41 +00:00
exists $detection->{i2c_extra};
push @probelist, -1, $detection->{isa_addr}
if exists $detection->{isa_addr} and
exists $detection->{isa_extra};
}
# Handle misdetects
1999-03-09 16:19:30 +00:00
foreach $detection (@{$chip->{misdetected}}) {
2000-02-01 21:12:43 +00:00
push @optionlist, $adapters[$detection->{i2c_devnr}]->{nr_later},
1999-03-09 16:19:30 +00:00
$detection->{i2c_addr}
2000-02-01 21:12:43 +00:00
if exists $detection->{i2c_addr} and
exists $adapters[$detection->{i2c_devnr}]->{nr_later};
1999-03-09 16:19:30 +00:00
push @optionlist, -1, $detection->{isa_addr}
2000-02-01 21:12:43 +00:00
if exists $detection->{isa_addr} and $isa;
1999-03-09 16:19:30 +00:00
}
1999-03-09 18:11:26 +00:00
# Handle aliases
foreach $detection (@{$chip->{detected}}) {
if (exists $detection->{i2c_driver} and
exists $detection->{isa_addr} and
2000-02-01 21:12:43 +00:00
exists $adapters[$detection->{i2c_devnr}]->{nr_later} and
$isa) {
1999-03-09 18:11:26 +00:00
if ($prefer_isa) {
2000-02-01 21:12:43 +00:00
push @optionlist,$adapters[$detection->{i2c_devnr}]->{nr_later},
1999-03-09 18:11:26 +00:00
$detection->{i2c_addr};
} else {
push @optionlist, -1, $detection->{isa_addr}
}
}
}
1999-03-23 21:48:41 +00:00
next if not (@probelist or @optionlist);
1999-03-09 16:19:30 +00:00
$configfile .= "options $chip->{driver}";
1999-03-23 21:48:41 +00:00
$configfile .= sprintf " ignore=%d,0x%02x",shift @optionlist,
shift @optionlist
if @optionlist;
$configfile .= sprintf ",%d,0x%02x",shift @optionlist, shift @optionlist
while @optionlist;
$configfile .= sprintf " probe=%d,0x%02x",shift @probelist,
shift @probelist
if @probelist;
$configfile .= sprintf ",%d,0x%02x",shift @probelist, shift @probelist
while @probelist;
1999-03-09 16:19:30 +00:00
$configfile .= "\n";
}
return ($modprobes,$configfile);
}
1999-02-17 20:55:23 +00:00
2002-11-07 23:15:28 +00:00
# returns:
2003-11-29 19:37:34 +00:00
# 0, could not determine (can't read /dev/mem...)
# 1, safe system (VPD record not found)
# bios string (e.g. "INET32WW"), unsafe system
2003-11-11 22:08:07 +00:00
# VPD is documented here:
# http://www.pc.ibm.com/qtechinfo/MIGR-45120.html
2003-11-29 19:37:34 +00:00
sub vpd_bios_build_id
2003-11-11 22:08:07 +00:00
{
my $pos = 0xF0000;
my $found = 0;
my $bbid;
return 0
unless open MEM, '/dev/mem';
binmode MEM;
unless (seek MEM, $pos, SEEK_SET)
{
close MEM;
return 0;
}
while ($pos <= 0xFFFD0 && !$found)
{
my $r = read(MEM, my $buf, 48);
unless ($r == 48)
{
close MEM;
return 0;
}
seek (MEM, -32, SEEK_CUR);
my $len;
if (substr($buf, 0, 5) eq "\xAA\x55VPD"
2003-12-10 07:35:33 +00:00
&& ord(substr($buf, 5, 1)) >= 0x30)
2003-11-11 22:08:07 +00:00
{
2003-12-10 07:35:33 +00:00
if (unpack('%8C*', substr($buf, 0x0D, 0x30-0x0D)) != 0)
{
printf " Bad VPD checksum (0x%02X)! Please report.\n",
ord(substr($buf, 0x2F, 1));
}
2003-11-11 22:08:07 +00:00
$bbid = substr($buf, 13, 9);
$bbid =~ s/[\x00 ]*$//; # right trim
$found++;
}
$pos += 16;
}
close MEM;
2003-11-29 19:37:34 +00:00
return 1 unless $found;
print " System vendor: IBM\n";
print " BIOS version: $bbid\n";
return "$bbid";
2003-11-11 22:08:07 +00:00
}
2002-11-07 23:15:28 +00:00
# returns:
# 1 : the system is known to be safe
# 0 : the system safeness is unknown
# If the system is know to be unsafe (i.e. for now, IBM systems), never
# return.
sub safe_system_vendor
{
if ($> != 0)
{
print " As you are not root, we can't determine your system vendor.\n";
return 0;
}
2003-11-29 19:37:34 +00:00
my $vpd_bbid = vpd_bios_build_id();
2002-11-07 23:15:28 +00:00
2003-11-29 19:37:34 +00:00
return 0 if $vpd_bbid eq '0';
return 1 if $vpd_bbid eq '1';
2003-11-11 22:08:07 +00:00
2003-11-29 19:37:34 +00:00
# This is where we'll be able to differenciate between different
# IBM systems (safe and unsafe). For now, everyone is blacklisted.
print " Sorry, we won't let you go on. IBM systems are known to have\n",
2002-11-21 20:44:31 +00:00
" serious problems with lm_sensors, resulting in hardware failures.\n",
" For more information, see README.thinkpad or\n",
2003-11-29 19:37:34 +00:00
" http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/README.thinkpad.\n",
" Not all IBM systems are affected, and we plan to establish a\n",
" \"white list\" of safe systems soon. Stay tuned!\n\n";
2002-11-07 23:15:28 +00:00
exit;
2002-08-11 21:53:21 +00:00
}
1999-02-19 01:52:29 +00:00
sub main
{
my (@adapters,$res,$did_adapter_detection,$detect_others,$adapter);
2003-08-07 09:31:24 +00:00
initialize_conf;
1999-02-19 01:52:29 +00:00
initialize_proc_pci;
initialize_modules_list;
2003-08-07 09:31:24 +00:00
print "\nThis program will help you determine which I2C/SMBus modules you need to\n",
"load to use lm_sensors most effectively. You need to have i2c and\n",
"lm_sensors installed before running this program.\n";
print "Also, you need to be `root', or at least have access to the $dev_i2c*\n",
"files, for most things.\n";
2003-11-21 23:12:04 +00:00
print "If you have patched your kernel and have some drivers built in, you can\n",
2003-08-07 09:31:24 +00:00
"safely answer NO if asked to load some modules. In this case, things may\n",
"seem a bit confusing, but they will still work.\n\n";
1999-02-19 01:52:29 +00:00
2002-08-11 21:53:21 +00:00
unless (safe_system_vendor ())
{
print " IF THIS IS AN IBM THINKPAD, PRESS CTRL-C NOW!\n";
print " IBM Thinkpads have a severely broken i2c/SMBus implementation, ";
print "just scanning\n";
print " the bus will break your Thinkpad forever!\n";
print " If this is a non-Thinkpad IBM, we still suggest you press CTRL+C. We have\n";
print " had users reporting system breakage on other IBM systems as well.\n\n";
}
2001-03-23 20:27:31 +00:00
1999-02-19 01:52:29 +00:00
print " We can start with probing for (PCI) I2C or SMBus adapters.\n";
print " You do not need any special privileges for this.\n";
print " Do you want to probe now? (YES/no): ";
@adapters = adapter_pci_detection
if ($did_adapter_detection = not <STDIN> =~ /\s*[Nn]/);
print "\n";
if (not $did_adapter_detection) {
print " As you skipped adapter detection, we will only scan already ",
"loaded adapter\n",
" modules. You can still be prompted for non-detectable adapters.\n",
" Do you want to? (yes/NO): ";
$detect_others = <STDIN> =~ /^\s*[Yy]/;
} elsif ($> != 0) {
print " As you are not root, we can't load adapter modules. We will only ",
"scan\n",
" already loaded adapters.\n";
$detect_others = 0;
} else {
print " We will now try to load each adapter module in turn.\n";
foreach $adapter (@adapters) {
2003-07-17 08:50:05 +00:00
next if $adapter eq "DISABLED";
1999-02-19 01:52:29 +00:00
if (contains $adapter, @modules_list) {
print "Module `$adapter' already loaded.\n";
} else {
1999-09-30 15:59:13 +00:00
print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
1999-02-19 01:52:29 +00:00
unless (<STDIN> =~ /^\s*[Nn]/) {
if (system ("modprobe", $adapter)) {
2002-11-15 16:11:18 +00:00
print "Loading failed... skipping.\n";
2003-07-17 08:50:05 +00:00
if ($adapter eq "rivatv") {
print "** Note: rivatv module is available at http://rivatv.sourceforge.net/\n";
2000-09-23 01:42:32 +00:00
}
1999-02-19 01:52:29 +00:00
} else {
print "Module loaded succesfully.\n";
}
}
}
}
print " Do you now want to be prompted for non-detectable adapters? ",
1999-02-23 14:14:32 +00:00
"(yes/NO): ";
$detect_others = <STDIN> =~ /^\s*[Yy]/ ;
1999-02-19 01:52:29 +00:00
}
if ($detect_others) {
foreach $adapter (@undetectable_adapters) {
1999-09-30 15:59:13 +00:00
print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
1999-02-19 01:52:29 +00:00
unless (<STDIN> =~ /^\s*[Nn]/) {
if (system ("modprobe", $adapter)) {
2002-11-15 16:11:18 +00:00
print "Loading failed... skipping.\n";
1999-02-19 01:52:29 +00:00
} else {
print "Module loaded succesfully.\n";
}
}
}
}
1999-07-21 20:11:27 +00:00
print " To continue, we need module `i2c-dev' to be loaded.\n";
1999-09-30 15:59:13 +00:00
print " If it is built-in into your kernel, you can safely skip this.\n";
1999-02-19 01:52:29 +00:00
if (contains "i2c-dev", @modules_list) {
print "i2c-dev is already loaded.\n";
} else {
if ($> != 0) {
print " i2c-dev is not loaded. As you are not root, we will just hope ",
"you edited\n",
2003-08-07 09:31:24 +00:00
" `$modules_conf' for automatic loading of\n",
" this module. If not, you won't be able to open any $dev_i2c* file.\n";
1999-02-19 01:52:29 +00:00
} else {
print " i2c-dev is not loaded. Do you want to load it now? (YES/no): ";
if (<STDIN> =~ /^\s*[Nn]/) {
print " Well, you will know best. We will just hope you edited ",
2003-08-07 09:31:24 +00:00
"`$modules_conf'\n",
" for automatic loading of this module. If not,\n",
" you won't be able to open any $dev_i2c* file (unless you",
1999-09-30 15:59:13 +00:00
"have it built-in\n",
" into your kernel)\n";
1999-02-19 18:11:03 +00:00
} elsif (system "modprobe","i2c-dev") {
2002-11-15 16:11:18 +00:00
print " Loading failed, expect problems later on.\n";
1999-02-19 01:52:29 +00:00
} else {
print " Module loaded succesfully.\n";
}
}
}
1999-02-23 14:14:32 +00:00
print "\n We are now going to do the adapter probings. Some adapters may ",
1999-02-19 01:52:29 +00:00
"hang halfway\n",
" through; we can't really help that. Also, some chips will be double ",
"detected;\n",
1999-04-22 13:08:59 +00:00
" we choose the one with the highest confidence value in that case.\n",
1999-02-24 00:22:52 +00:00
" If you found that the adapter hung after probing a certain address, ",
"you can\n",
2001-09-19 15:57:06 +00:00
" specify that address to remain unprobed. That ",
1999-04-22 13:08:59 +00:00
"often\n",
2001-09-19 15:57:06 +00:00
" includes address 0x69 (clock chip).\n";
1999-02-19 01:52:29 +00:00
1999-02-24 00:22:52 +00:00
my ($inp,@not_to_scan,$inp2);
2003-11-28 05:10:32 +00:00
# i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
open INPUTFILE,"i2cdetect -l |" or die "Couldn't find i2cdetect program!!";
1999-02-19 01:52:29 +00:00
while (<INPUTFILE>) {
1999-11-13 22:57:17 +00:00
my ($dev_nr,$type,$adap,$algo) = /^i2c-(\S+)\s+(\S+)\s+(.*?)\s*\t\s*(.*?)\s+$/;
next if ($type eq "dummy");
1999-02-19 01:52:29 +00:00
print "\n";
1999-02-23 14:14:32 +00:00
print "Next adapter: $adap ($algo)\n";
1999-02-24 00:22:52 +00:00
print "Do you want to scan it? (YES/no/selectively): ";
$inp = <STDIN>;
@not_to_scan=();
if ($inp =~ /^\s*[Ss]/) {
print "Please enter one or more addresses not to scan. Separate them ",
"with comma's.\n",
"You can specify a range by using dashes. Addresses may be ",
"decimal (like 54)\n",
"or hexadecimal (like 0x33).\n",
"Addresses: ";
$inp2 = <STDIN>;
chop $inp2;
@not_to_scan = parse_not_to_scan 0,0x7f,$inp2;
}
scan_adapter $dev_nr, $adap, $algo, find_adapter_driver($adap,$algo),
\@not_to_scan unless $inp =~ /^\s*[Nn]/;
1999-02-19 18:11:03 +00:00
}
1999-02-23 14:14:32 +00:00
print "\n Some chips are also accessible through the ISA bus. ISA probes ",
"are\n",
" typically a bit more dangerous, as we have to write to I/O ports ",
"to do\n",
" this. ";
if ($> != 0) {
print "As you are not root, we shall skip this step.\n";
} else {
print " Do you want to scan the ISA bus? (YES/no): ";
if (not <STDIN> =~ /^\s*[Nn]/) {
2003-06-28 08:25:19 +00:00
initialize_ioports();
scan_isa_bus();
close_ioports();
1999-02-23 14:14:32 +00:00
}
}
2002-12-09 03:01:23 +00:00
print "\n Some Super I/O chips may also contain sensors. Super I/O probes ",
"are\n",
" typically a bit more dangerous, as we have to write to I/O ports ",
"to do\n",
" this. ";
if ($> != 0) {
print "As you are not root, we shall skip this step.\n";
} else {
print " Do you want to scan for Super I/O sensors? (YES/no): ";
if (not <STDIN> =~ /^\s*[Nn]/) {
2003-06-28 08:25:19 +00:00
initialize_ioports();
scan_superio();
close_ioports();
2002-12-09 03:01:23 +00:00
}
}
2002-11-21 23:43:05 +00:00
if(! @chips_detected) {
print "\n Sorry, no chips were detected.\n",
" Either your sensors are not supported, or they are\n",
" connected to an I2C bus adapter that we do not support.\n",
" See doc/FAQ, doc/lm_sensors-FAQ.html, or\n",
" http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/doc/lm_sensors-FAQ.html\n",
" (FAQ #4.24.3) for further information.\n",
" If you find out what chips are on your board, see\n",
" http://secure.netroedge.com/~lm78/newdrivers.html for driver status.\n";
exit;
}
1999-02-19 18:11:03 +00:00
print "\n Now follows a summary of the probes I have just done.\n";
1999-03-09 18:11:26 +00:00
print " Just press ENTER to continue: ";
<STDIN>;
1999-02-19 18:11:03 +00:00
my ($chip,$data);
foreach $chip (@chips_detected) {
print "\nDriver `$$chip{driver}' ";
if (@{$$chip{detected}}) {
if (@{$$chip{misdetected}}) {
print "(should be inserted but causes problems):\n";
} else {
print "(should be inserted):\n";
}
} else {
if (@{$$chip{misdetected}}) {
print "(may not be inserted):\n";
} else {
print "(should not be inserted, but is harmless):\n";
}
}
if (@{$$chip{detected}}) {
1999-02-19 18:12:27 +00:00
print " Detects correctly:\n";
1999-02-28 17:41:46 +00:00
print_chips_report $chip->{detected};
1999-02-19 18:11:03 +00:00
}
if (@{$$chip{misdetected}}) {
print " Misdetects:\n";
1999-02-28 17:41:46 +00:00
print_chips_report $chip->{misdetected};
1999-02-19 18:11:03 +00:00
}
1999-02-19 01:52:29 +00:00
}
1999-03-09 16:19:30 +00:00
1999-03-09 18:11:26 +00:00
print "\n\n",
" I will now generate the commands needed to load the I2C modules.\n",
" Sometimes, a chip is available both through the ISA bus and an ",
"I2C bus.\n",
" ISA bus access is faster, but you need to load an additional driver ",
"module\n",
" for it. If you have the choice, do you want to use the ISA bus or ",
"the\n",
" I2C/SMBus (ISA/smbus)? ";
my $use_isa = not <STDIN> =~ /\s*[Ss]/;
my ($modprobes,$configfile) = generate_modprobes $use_isa;
2003-08-07 09:31:24 +00:00
print "\nTo make the sensors modules behave correctly, add these lines to\n",
"$modules_conf:\n\n";
2003-07-08 13:07:59 +00:00
print "#----cut here----\n";
print $configfile;
print "#----cut here----\n";
1999-03-09 18:11:26 +00:00
print "\nTo load everything that is needed, add this to some /etc/rc* ",
1999-03-09 16:19:30 +00:00
"file:\n\n";
print "#----cut here----\n";
print $modprobes;
2003-07-08 13:07:59 +00:00
print "# sleep 2 # optional\n",
"/usr/local/bin/sensors -s # recommended\n";
1999-03-09 16:19:30 +00:00
print "#----cut here----\n";
2003-07-08 13:07:59 +00:00
print "\nWARNING! If you have some things built into your kernel, the list above\n",
"will contain too many modules. Skip the appropriate ones! You really should\n",
"try these commands right now to make sure everything is working properly.\n",
"Monitoring programs won't work until it's done.\n";
1999-03-09 16:19:30 +00:00
2002-10-17 17:42:00 +00:00
my $have_sysconfig = -d '/etc/sysconfig';
print "\nDo you want to generate /etc/sysconfig/lm_sensors? (".
($have_sysconfig?"YES/no":"yes/NO")."): ";
2002-06-30 23:57:34 +00:00
if ($> != 0) {
print "\nAs you are not root, we shall skip this step.\n";
} else {
2002-10-17 17:42:00 +00:00
if (($have_sysconfig and not <STDIN> =~ /^\s*[Nn]/) or <STDIN> =~ /^\s*[Yy]/) {
unless ($have_sysconfig) {
2002-11-08 09:38:29 +00:00
mkdir '/etc/sysconfig', 0777
2002-10-17 17:42:00 +00:00
or die "Sorry, can't create /etc/sysconfig ($!)?!?";
}
2002-06-30 23:57:34 +00:00
open(SYSCONFIG, ">/etc/sysconfig/lm_sensors")
or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)?!?";
print SYSCONFIG <<'EOT';
# /etc/sysconfig/sensors - Defines modules loaded by /etc/rc.d/init.d/lm_sensors
# Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#
# See also the lm_sensors homepage at:
# http://www2.lm-sensors.nu/~lm78/index.html
#
# This file is used by /etc/rc.d/init.d/lm_sensors and defines the modules to
# be loaded/unloaded. This file is sourced into /etc/rc.d/init.d/lm_sensors.
#
# The format of this file is a shell script that simply defines the modules
# in order as normal variables with the special names:
2002-09-28 20:42:02 +00:00
# MODULE_0, MODULE_1, MODULE_2, etc.
2002-06-30 23:57:34 +00:00
#
# List the modules that are to be loaded for your system
#
EOT
print SYSCONFIG
2002-07-10 01:34:32 +00:00
"# Generated by sensors-detect on " . scalar localtime() . "\n";
2002-06-30 23:57:34 +00:00
my @modules = grep /^modprobe /, split "\n", $modprobes;
2002-08-18 02:46:40 +00:00
my $i = 0;
2002-06-30 23:57:34 +00:00
my $sysconfig = "";
foreach (@modules) {
s/^modprobe //;
$sysconfig .= "MODULE_$i=$_\n";
$i++;
}
print SYSCONFIG $sysconfig;
close(SYSCONFIG);
print "Copy prog/init/lm_sensors.init to /etc/rc.d/init.d/lm_sensors\n";
print "for initialization at boot time.\n";
}
}
1999-02-19 01:52:29 +00:00
}
main;