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

Revision 2509, 145.8 KB (checked in by khali, 9 years ago)

Patch by Aurelien Jarno:

When running sensors-detect on a system with devfs enabled, and the
/proc/mounts report its device different from 'none' (for example devfsd
uses 'devfs' as device name), sensors-detect don't detect devfs and try
to use normal names for i2c devices.

The attached patch fixes that.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/perl -w
2
3#
4#    sensors-detect - Detect PCI bus and chips
5#    Copyright (C) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>
6#    Copyright (C) 2000 - 2004  The lm_sensors team
7#
8#    This program is free software; you can redistribute it and/or modify
9#    it under the terms of the GNU General Public License as published by
10#    the Free Software Foundation; either version 2 of the License, or
11#    (at your option) any later version.
12#
13#    This program is distributed in the hope that it will be useful,
14#    but WITHOUT ANY WARRANTY; without even the implied warranty of
15#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16#    GNU General Public License for more details.
17#
18#    You should have received a copy of the GNU General Public License
19#    along with this program; if not, write to the Free Software
20#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21#
22
23# TODO: Better handling of chips with several addresses
24
25# A Perl wizard really ought to look upon this; the PCI and I2C stuff should
26# each be put in a separate file, using modules and packages. That is beyond
27# me.
28
29require 5.004;
30
31use strict;
32use Fcntl;
33use POSIX;
34
35# Just in case a root user doesn't have /sbin in his/her path for some reason
36# (was seen once)
37$ENV{PATH} = '/sbin:'.$ENV{PATH}
38        unless $ENV{PATH} =~ m,(^|:)/sbin/?(:|$),;
39# Same for /usr/local/sbin since we need i2cdetect which is installed there
40# by default (reported by Lennard Klein)
41$ENV{PATH} = '/usr/local/sbin:'.$ENV{PATH}
42        unless $ENV{PATH} =~ m,(^|:)/usr/local/sbin/?(:|$),;
43
44#########################
45# CONSTANT DECLARATIONS #
46#########################
47
48use vars qw(@pci_adapters @chip_ids @superio_ids);
49
50# This is the list of SMBus or I2C adapters we recognize by their PCI
51# signature. This is an easy and fast way to determine which SMBus or I2C
52# adapters should be present.
53# Each entry must have a vendid (Vendor ID), devid (Device ID), func (PCI
54# Function) and procid (string as appears in /proc/pci; see linux/driver/pci,
55# either pci.c or oldproc.c). If no driver is written yet, set the
56# driver (Driver Name) field to "to-be-written".
57# The match (Match Description) field should
58# contain a function which returns zero if its two parameter matches
59# the text as it would appear in /proc/bus/i2c.
60@pci_adapters = ( 
61     { 
62       vendid => 0x8086,
63       devid  => 0x7113,
64       func => 3,
65       procid => "Intel 82371AB PIIX4 ACPI",
66       driver => "i2c-piix4",
67       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
68     } , 
69     { 
70       vendid => 0x8086,
71       devid  => 0x719b,
72       func => 3,
73       procid => "Intel 82443MX Mobile",
74       driver => "i2c-piix4",
75       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
76     } , 
77     { 
78       vendid => 0x8086,
79       devid  => 0x2413,
80       func => 3,
81       procid => "Intel 82801AA ICH",
82       driver => "i2c-i801",
83       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
84     } , 
85     { 
86       vendid => 0x8086,
87       devid  => 0x2423,
88       func => 3,
89       procid => "Intel 82801AB ICH0",
90       driver => "i2c-i801",
91       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
92     } , 
93     { 
94       vendid => 0x8086,
95       devid  => 0x2443,
96       func => 3,
97       procid => "Intel 82801BA ICH2",
98       driver => "i2c-i801",
99       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
100     } , 
101     { 
102       vendid => 0x8086,
103       devid  => 0x2483,
104       func => 3,
105       procid => "Intel 82801CA/CAM ICH3",
106       driver => "i2c-i801",
107       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
108     } , 
109     { 
110       vendid => 0x8086,
111       devid  => 0x24C3,
112       func => 3,
113       procid => "Intel 82801DB ICH4",
114       driver => "i2c-i801",
115       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
116     } , 
117     { 
118       vendid => 0x8086,
119       devid  => 0x24D3,
120       func => 3,
121       procid => "Intel 82801EB ICH5",
122       driver => "i2c-i801",
123       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
124     } , 
125     { 
126       vendid => 0x1106,
127       devid  => 0x3040,
128       func => 3,
129       procid => "VIA Technologies VT82C586B Apollo ACPI",
130       driver => "i2c-via",
131       match => sub { $_[0] =~ /^VIA i2c/ },
132     } ,
133     { 
134       vendid => 0x1106,
135       devid  => 0x3050,
136       func => 3,
137       procid => "VIA Technologies VT82C596 Apollo ACPI",
138       driver => "i2c-viapro",
139       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
140     } ,
141     { 
142       vendid => 0x1106,
143       devid  => 0x3051,
144       func => 3,
145       procid => "VIA Technologies VT82C596B ACPI",
146       driver => "i2c-viapro",
147       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
148     } ,
149     { 
150       vendid => 0x1106,
151       devid  => 0x3057,
152       func => 4,
153       procid => "VIA Technologies VT82C686 Apollo ACPI",
154       driver => "i2c-viapro",
155       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
156     } ,
157     { 
158       vendid => 0x1106,
159       devid  => 0x3074,
160       func => 0,
161       procid => "VIA Technologies VT8233 VLink South Bridge",
162       driver => "i2c-viapro",
163       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
164     } ,
165     { 
166       vendid => 0x1106,
167       devid  => 0x3147,
168       func => 0,
169       procid => "VIA Technologies VT8233A South Bridge",
170       driver => "i2c-viapro",
171       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
172     } ,
173     { 
174       vendid => 0x1106,
175       devid  => 0x3177,
176       func => 0,
177       procid => "VIA Technologies VT8233A/8235 South Bridge",
178       driver => "i2c-viapro",
179       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
180     } ,
181     {
182       vendid => 0x1106,
183       devid  => 0x3227,
184       func => 0,
185       procid => "VIA Technologies VT8237 South Bridge",
186       driver => "i2c-viapro",
187       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
188     } ,
189     { 
190       vendid => 0x1106,
191       devid  => 0x8235,
192       func => 4,
193       procid => "VIA Technologies VT8231 South Bridge",
194       driver => "i2c-viapro",
195       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
196     } ,
197     {
198       vendid => 0x1039,
199       devid  => 0x5597,
200       func => 0,
201       procid => "Silicon Integrated Systems SIS5581/5582/5597/5598 (To be written - Do not use 5595 drivers)",
202       driver => "to-be-written",
203       match => sub { 0 },
204     } ,
205     {
206       vendid => 0x1039,
207       devid  => 0x5598,
208       func => 0,
209       procid => "Silicon Integrated Systems SIS5598 (To be written - Do not use 5595 drivers)",
210       driver => "to-be-written",
211       match => sub { 0 },
212     } ,
213     {
214       vendid => 0x1039,
215       devid  => 0x0540,
216       func => 0,
217       procid => "Silicon Integrated Systems SIS540 (To be written - Do not use 5595 drivers)",
218       driver => "to-be-written",
219       match => sub { 0 },
220     } ,
221     {
222       vendid => 0x1039,
223       devid  => 0x0630,
224       func => 0,
225       procid => "Silicon Integrated Systems SIS630",
226       driver => "i2c-sis630",
227       match => sub { $_[0] =~ /^SMBus SIS630 adapter at [0-9,a-f]{4}/ },
228     } ,
229     {
230       vendid => 0x1039,
231       devid  => 0x0730,
232       func => 0,
233       procid => "Silicon Integrated Systems SIS730",
234       driver => "i2c-sis630",
235       match => sub { $_[0] =~ /^SMBus SIS630 adapter at [0-9,a-f]{4}/ },
236     } ,
237#
238# Both Ali chips below have same PCI ID. Can't be helped. Only one should load.
239#
240     {
241       vendid => 0x10b9,
242       devid => 0x7101,
243       func => 0,
244       procid => "Acer Labs 1533/1543",
245       driver => "i2c-ali15x3",
246       match => sub { $_[0] =~ /^SMBus ALI15X3 adapter at/ },
247     },
248     {
249       vendid => 0x10b9,
250       devid => 0x7101,
251       func => 0,
252       procid => "Acer Labs 1535",
253       driver => "i2c-ali1535",
254       match => sub { $_[0] =~ /^SMBus ALI1535 adapter at/ },
255     },
256     {
257       vendid => 0x10b9,
258       devid => 0x1563,
259       func => 0,
260       procid => "Acer Labs 1563",
261       driver => "i2c-ali1563",
262       match => sub { $_[0] =~ /^SMBus ALi 1563 Adapter @/ },
263     },
264     { 
265       vendid => 0x106b,
266       devid  => 0x000e,
267       func => 0,
268       procid => "Apple Computer Inc. Hydra Mac I/O",
269       driver => "i2c-hydra",
270       match => sub { $_[0] =~ /^Hydra i2c/ },
271     },
272     { 
273       vendid => 0x1022,
274       devid  => 0x740b,
275       func => 3,
276       procid => "AMD-756 Athlon ACPI",
277       driver => "i2c-amd756",
278       match => sub { $_[0] =~ /^SMBus AMD756 adapter at [0-9,a-f]{4}/ },
279     },
280     { 
281       vendid => 0x1022,
282       devid  => 0x7413,
283       func => 3,
284       procid => "AMD-766 Athlon ACPI",
285       driver => "i2c-amd756",
286       match => sub { $_[0] =~ /^SMBus AMD766 adapter at [0-9,a-f]{4}/ },
287     },
288     { 
289       vendid => 0x1022,
290       devid  => 0x7443,
291       func => 3,
292       procid => "AMD-768 System Management",
293       driver => "i2c-amd756",
294       match => sub { $_[0] =~ /^SMBus AMD768 adapter at [0-9,a-f]{4}/ },
295     },
296     { 
297       vendid => 0x1022,
298       devid  => 0x746b,
299       func => 3,
300       procid => "AMD-8111 ACPI",
301       driver => "i2c-amd756",
302       match => sub { $_[0] =~ /^SMBus AMD8111 adapter at [0-9,a-f]{4}/ },
303     },
304     { 
305       vendid => 0x1022,
306       devid  => 0x746a,
307       func => 2,
308       procid => "AMD-8111 SMBus 2.0",
309       driver => "i2c-amd8111",
310       match => sub { $_[0] =~ /^SMBus2 AMD8111 adapter at [0-9,a-f]{4}/ },
311     },
312     {
313       vendid => 0x102b,
314       devid  => 0x0519,
315       func   => 0,
316       procid => "MGA 2064W [Millennium]",
317       driver => "i2c-matroxfb",
318       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
319     },
320     {
321       vendid => 0x102b,
322       devid  => 0x051a,
323       func   => 0,
324       procid => "MGA 1064SG [Mystique]",
325       driver => "i2c-matroxfb",
326       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
327     },
328     {
329       vendid => 0x102b,
330       devid  => 0x051b,
331       func   => 0,
332       procid => "MGA 2164W [Millennium II]",
333       driver => "i2c-matroxfb",
334       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
335     },
336     {
337       vendid => 0x102b,
338       devid  => 0x051e,
339       func   => 0,
340       procid => "MGA 1064SG [Mystique] AGP",
341       driver => "i2c-matroxfb",
342       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
343     },
344     {
345       vendid => 0x102b,
346       devid  => 0x051f,
347       func   => 0,
348       procid => "MGA 2164W [Millennium II] AGP",
349       driver => "i2c-matroxfb",
350       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
351     },
352     {
353       vendid => 0x102b,
354       devid  => 0x1000,
355       func   => 0,
356       procid => "MGA G100 [Productiva]",
357       driver => "i2c-matroxfb",
358       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
359     },
360     {
361       vendid => 0x102b,
362       devid  => 0x1001,
363       func   => 0,
364       procid => "MGA G100 [Productiva] AGP",
365       driver => "i2c-matroxfb",
366       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
367     },
368     {
369       vendid => 0x102b,
370       devid  => 0x0520,
371       func   => 0,
372       procid => "MGA G200",
373       driver => "i2c-matroxfb",
374       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
375     },
376     {
377       vendid => 0x102b,
378       devid  => 0x0521,
379       func   => 0,
380       procid => "MGA G200 AGP",
381       driver => "i2c-matroxfb",
382       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
383     },
384     {
385       vendid => 0x102b,
386       devid  => 0x0525,
387       func   => 0,
388       procid => "MGA G400 AGP",
389       driver => "i2c-matroxfb",
390       match  => sub { $_[0] =~ /^(DDC,MAVEN):fb[0-9]{1,2}/ },
391     },
392     {
393       vendid => 0x121a,
394       devid  => 0x0005,
395       func   => 0,
396       procid => "3Dfx Voodoo3",
397       driver => "i2c-voodoo3",
398       match  => sub { $_[0] =~ /Banshee adapter/ },
399     },
400     {
401       vendid => 0x121a,
402       devid  => 0x0003,
403       func   => 0,
404       procid => "3Dfx Voodoo Banshee",
405       driver => "i2c-voodoo3",
406       match  => sub { $_[0] =~ /Banshee adapter/ },
407     },
408     { 
409       vendid => 0x8086,
410       devid  => 0x7121,
411       func => 0,
412       procid => "Intel 82810 GMCH",
413       driver => "i2c-i810",
414       match => sub { $_[0] =~ /^I810/ },
415     } , 
416     { 
417       vendid => 0x8086,
418       devid  => 0x7123,
419       func => 0,
420       procid => "Intel 82810-DC100 GMCH",
421       driver => "i2c-i810",
422       match => sub { $_[0] =~ /^I810/ },
423     } , 
424     { 
425       vendid => 0x8086,
426       devid  => 0x7125,
427       func => 0,
428       procid => "Intel 82810E GMCH",
429       driver => "i2c-i810",
430       match => sub { $_[0] =~ /^I810/ },
431     } , 
432     { 
433       vendid => 0x8086,
434       devid  => 0x1132,
435       func => 0,
436       procid => "Intel 82815 GMCH",
437       driver => "i2c-i810",
438       match => sub { $_[0] =~ /^I810/ },
439     } , 
440     { 
441       vendid => 0x12d2,
442       devid  => 0x0018,
443       func => 0,
444       procid => "RIVA 128",
445       driver => "rivatv",
446       match => sub { $_[0] =~ /^NVIDIA display/ },
447     } , 
448     { 
449       vendid => 0x10de,
450       devid  => 0x0020,
451       func => 0,
452       procid => "RIVA TNT",
453       driver => "rivatv",
454       match => sub { $_[0] =~ /^NVIDIA display/ },
455     } , 
456     { 
457       vendid => 0x10de,
458       devid  => 0x0028,
459       func => 0,
460       procid => "RIVA TNT2",
461       driver => "rivatv",
462       match => sub { $_[0] =~ /^NVIDIA display/ },
463     } , 
464     { 
465       vendid => 0x10de,
466       devid  => 0x0029,
467       func => 0,
468       procid => "RIVA UTNT2",
469       driver => "rivatv",
470       match => sub { $_[0] =~ /^NVIDIA display/ },
471     } , 
472     { 
473       vendid => 0x10de,
474       devid  => 0x002c,
475       func => 0,
476       procid => "RIVA VTNT2",
477       driver => "rivatv",
478       match => sub { $_[0] =~ /^NVIDIA display/ },
479     } , 
480     { 
481       vendid => 0x10de,
482       devid  => 0x002d,
483       func => 0,
484       procid => "RIVA UVTNT2",
485       driver => "rivatv",
486       match => sub { $_[0] =~ /^NVIDIA display/ },
487     } , 
488     { 
489       vendid => 0x10de,
490       devid  => 0x00a0,
491       func => 0,
492       procid => "RIVA ITNT2",
493       driver => "rivatv",
494       match => sub { $_[0] =~ /^NVIDIA display/ },
495     } , 
496     { 
497       vendid => 0x10de,
498       devid  => 0x0100,
499       func => 0,
500       procid => "GeForce SDR",
501       driver => "rivatv",
502       match => sub { $_[0] =~ /^NVIDIA display/ },
503     } , 
504     { 
505       vendid => 0x10de,
506       devid  => 0x0101,
507       func => 0,
508       procid => "GeForce DDR",
509       driver => "rivatv",
510       match => sub { $_[0] =~ /^NVIDIA display/ },
511     } , 
512     { 
513       vendid => 0x10de,
514       devid  => 0x0102,
515       func => 0,
516       procid => "Quadro",
517       driver => "rivatv",
518       match => sub { $_[0] =~ /^NVIDIA display/ },
519     } , 
520     { 
521       vendid => 0x10de,
522       devid  => 0x0150,
523       func => 0,
524       procid => "GeForce2 GTS",
525       driver => "rivatv",
526       match => sub { $_[0] =~ /^NVIDIA display/ },
527     } , 
528     { 
529       vendid => 0x10de,
530       devid  => 0x0110,
531       func => 0,
532       procid => "GeForce2 MX",
533       driver => "rivatv",
534       match => sub { $_[0] =~ /^NVIDIA display/ },
535     } , 
536     { 
537       vendid => 0x10de,
538       devid  => 0x0111,
539       func => 0,
540       procid => "GeForce2 MX2",
541       driver => "rivatv",
542       match => sub { $_[0] =~ /^NVIDIA display/ },
543     } , 
544     { 
545       vendid => 0x10de,
546       devid  => 0x0113,
547       func => 0,
548       procid => "Quadro2 MXR",
549       driver => "rivatv",
550       match => sub { $_[0] =~ /^NVIDIA display/ },
551     } , 
552     { 
553       vendid => 0x10de,
554       devid  => 0x0151,
555       func => 0,
556       procid => "GeForce2 GTS2",
557       driver => "rivatv",
558       match => sub { $_[0] =~ /^NVIDIA display/ },
559     } , 
560     { 
561       vendid => 0x10de,
562       devid  => 0x0152,
563       func => 0,
564       procid => "GeForce2 Ultra",
565       driver => "rivatv",
566       match => sub { $_[0] =~ /^NVIDIA display/ },
567     } , 
568     { 
569       vendid => 0x10de,
570       devid  => 0x0153,
571       func => 0,
572       procid => "Quadro2 Pro",
573       driver => "rivatv",
574       match => sub { $_[0] =~ /^NVIDIA display/ },
575     } , 
576     { 
577       vendid => 0x10de,
578       devid  => 0x0312,
579       func => 0,
580       procid => "GeForce FX 5600",
581       driver => "rivatv",
582       match => sub { $_[0] =~ /^NVIDIA display/ },
583     },
584     {
585       vendid => 0x10de,
586       devid  => 0x0330,
587       func => 0,
588       procid => "GeForce FX 5900 Ultra",
589       driver => "rivatv",
590       match => sub { $_[0] =~ /^NVIDIA display/ },
591     },
592     {
593       vendid => 0x10de,
594       devid  => 0x0331,
595       func => 0,
596       procid => "GeForce FX 5900",
597       driver => "rivatv",
598       match => sub { $_[0] =~ /^NVIDIA display/ },
599     },
600     {
601       vendid => 0x10de,
602       devid  => 0x0332,
603       func => 0,
604       procid => "GeForce FX 5900 XT",
605       driver => "rivatv",
606       match => sub { $_[0] =~ /^NVIDIA display/ },
607     },
608     {
609       vendid => 0x10de,
610       devid  => 0x0333,
611       func => 0,
612       procid => "GeForce FX 5950 Ultra",
613       driver => "rivatv",
614       match => sub { $_[0] =~ /^NVIDIA display/ },
615     },
616     {
617       vendid => 0x10de,
618       devid  => 0x01b4,
619       func => 1,
620       procid => "nVidia nForce SMBus",
621       driver => "i2c-amd756",
622       match => sub { $_[0] =~ /^SMBus nVidia nForce adapter at [0-9,a-f]{4}/ },
623     } , 
624     { 
625       vendid => 0x10de,
626       devid  => 0x0064,
627       func => 1,
628       procid => "nVidia Corporation nForce2 SMBus (MCP)",
629       driver => "i2c-nforce2",
630       match => sub { $_[0] =~ /^SMBus nForce2 adapter at / },
631     } , 
632     { 
633       vendid => 0x1166,
634       devid  => 0x0200,
635       func => 0,
636       procid => "ServerWorks OSB4 South Bridge",
637       driver => "i2c-piix4",
638       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
639     } , 
640     { 
641       vendid => 0x1055,
642       devid  => 0x9463,
643       func => 0,
644       procid => "SMSC Victory66 South Bridge",
645       driver => "i2c-piix4",
646       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
647     } , 
648     { 
649       vendid => 0x1166,
650       devid  => 0x0201,
651       func => 0,
652       procid => "ServerWorks CSB5 South Bridge",
653       driver => "i2c-piix4",
654       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
655     } , 
656     { 
657       vendid => 0x1166,
658       devid  => 0x0203,
659       func => 0,
660       procid => "ServerWorks CSB6 South Bridge",
661       driver => "i2c-piix4",
662       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
663     } , 
664     { 
665       vendid => 0x1283,
666       devid  => 0x8172,
667       func => 0,
668       procid => "ITE 8172G MIPS/SH4 Support Chip",
669       driver => "i2c-adap-ite",
670       match => sub { $_[0] =~ /^ITE IIC adapter/ },
671     } , 
672     { 
673       vendid => 0x5333,
674       devid  => 0x8A20,
675       func => 0,
676       procid => "S3 Savage 3D",
677       driver => "to-be-written",
678       match => sub { 0 },
679     } , 
680     { 
681       vendid => 0x5333,
682       devid  => 0x8A21,
683       func => 0,
684       procid => "S3 Savage 3D MV",
685       driver => "to-be-written",
686       match => sub { 0 },
687     } , 
688     { 
689       vendid => 0x5333,
690       devid  => 0x8A22,
691       func => 0,
692       procid => "S3 Savage 4",
693       driver => "i2c-savage4",
694       match => sub { $_[0] =~ /Savage4 adapter/ },
695     } , 
696     { 
697       vendid => 0x5333,
698       devid  => 0x9102,
699       func => 0,
700       procid => "S3 Savage 2000",
701       driver => "i2c-savage4",
702       match => sub { $_[0] =~ /Savage4 adapter/ },
703     } , 
704     { 
705       vendid => 0x5333,
706       devid  => 0x8A25,
707       func => 0,
708       procid => "S3 ProSavage PM",
709       driver => "to-be-written",
710       match => sub { $_[0] =~ /^dontmatchthis/ },
711     } , 
712     { 
713       vendid => 0x5333,
714       devid  => 0x8A26,
715       func => 0,
716       procid => "S3 ProSavage KM",
717       driver => "to-be-written",
718       match => sub { 0 },
719     } , 
720     { 
721       vendid => 0x5333,
722       devid  => 0x8C10,
723       func => 0,
724       procid => "S3 Savage MX MV",
725       driver => "to-be-written",
726       match => sub { 0 },
727     } , 
728     { 
729       vendid => 0x5333,
730       devid  => 0x8C11,
731       func => 0,
732       procid => "S3 Savage MX",
733       driver => "to-be-written",
734       match => sub { 0 },
735     } , 
736     { 
737       vendid => 0x5333,
738       devid  => 0x8C12,
739       func => 0,
740       procid => "S3 Savage IX MV",
741       driver => "to-be-written",
742       match => sub { 0 },
743     } , 
744     { 
745       vendid => 0x5333,
746       devid  => 0x8C13,
747       func => 0,
748       procid => "S3 Savage IX",
749       driver => "to-be-written",
750       match => sub { 0 },
751     } , 
752);
753
754# The following entries used to appear directly in @pci_adapters.
755# Because of the tendency of SiS chipsets to have their real PCI
756# IDs obscured, we have to qualify these with a custom detection
757# routine before we add them to the @pci_adapters list.
758#
759use vars qw(@pci_adapters_sis5595 @pci_adapters_sis645 @pci_adapters_sis96x);
760@pci_adapters_sis5595 = (
761     {
762       vendid => 0x1039,
763       devid  => 0x0008,
764       func => 0,
765       procid => "Silicon Integrated Systems SIS5595",
766       driver => "i2c-sis5595",
767       match => sub {  $_[0] =~ /^SMBus SIS5595 adapter at [0-9,a-f]{4}/ },
768     } ,
769);
770
771@pci_adapters_sis645 = (
772     {
773       vendid => 0x1039,
774       devid  => 0x0008,
775       func => 0,
776       procid => "Silicon Integrated Systems SIS5595",
777       driver => "i2c-sis645",
778       match => sub {  $_[0] =~ /^SiS645 SMBus adapter at [0-9,a-f]{4}/ },
779     } ,
780     {
781       vendid => 0x1039,
782       devid  => 0x0016,
783       func => 1,
784       procid => "Silicon Integrated Systems SMBus Controller",
785       driver => "i2c-sis645",
786       match => sub { $_[0] =~ /^SiS645 SMBus adapter at 0x[0-9,a-f]{4}/ },
787     } ,
788     {
789       vendid => 0x1039,
790       devid  => 0x0018,
791       func => 0,
792       procid => "Silicon Integrated Systems 85C503/5513 (LPC Bridge)",
793       driver => "i2c-sis645",
794       match => sub { $_[0] =~ /^SiS645 SMBus adapter at 0x[0-9,a-f]{4}/ },
795     } ,
796);
797
798@pci_adapters_sis96x = (
799     {
800       vendid => 0x1039,
801       devid  => 0x0016,
802       func => 1,
803       procid => "Silicon Integrated Systems SMBus Controller",
804       driver => "i2c-sis96x",
805       match => sub { $_[0] =~ /^SiS96x SMBus adapter at 0x[0-9,a-f]{4}/ },
806     } ,
807);
808
809use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect
810            lm75_detect lm80_detect w83781d_detect w83781d_alias_detect
811            adm1025_detect w83781d_isa_detect gl518sm_detect gl520sm_detect
812            adm9240_detect adm1021_detect sis5595_isa_detect eeprom_detect
813            via686a_isa_detect adm1022_detect gl525sm_detect
814            lm87_detect ite_detect ite_isa_detect ite_alias_detect
815            ddcmonitor_detect ds1621_detect adm1024_detect fscpos_detect
816            fscscy_detect arp_detect ipmi_kcs_detect
817            ipmi_smic_detect via8231_isa_detect lm85_detect smartbatt_detect
818            adm1026_detect w83l785ts_detect lm83_detect lm90_detect
819            saa1064_detect w83l784r_detect mozart_detect max6650_detect
820            fscher_detect adm1029_detect adm1031_detect max6900_detect
821            m5879_detect pca9540_detect smartbatt_mgr_detect
822            smartbatt_chgr_detect adt7467_detect lm92_detect);
823
824# This is a list of all recognized chips.
825# Each entry must have the following fields:
826#  name: The full chip name
827#  driver: The driver name (without .o extension). Put in exactly
828#      "to-be-written" if it is not yet available.
829#  i2c_addrs (optional): For I2C chips, the range of valid I2C addresses to
830#      probe. Recommend avoiding 0x69 because of clock chips.
831#  i2c_driver_addrs (optional): For I2C chips, the range of valid I2C
832#      addresses probed by the kernel driver. Strictly optional.
833#  i2c_detect (optional): For I2C chips, the function to call to detect
834#      this chip. The function should take two parameters: an open file
835#      descriptor to access the bus, and the I2C address to probe.
836#  isa_addrs (optional): For ISA chips, the range of valid port addresses to
837#      probe.
838#  isa_driver_addrs (optional): For ISA chips, the range of valid ISA
839#      addresses probed by the kernel driver. Strictly optional.
840#  isa_detect (optional): For ISA chips, the function to call to detect
841#      this chip. The function should take one parameter: the ISA address
842#      to probe.
843#  alias_detect (optional): For chips which can be both on the ISA and the
844#      I2C bus, a function which detectes whether two entries are the same.
845#      The function should take three parameters: The ISA address, the
846#      I2C bus number, and the I2C address.
847@chip_ids = (
848     {
849       name => "Myson MTP008",
850       driver => "mtp008",
851       i2c_addrs => [0x2c..0x2e], 
852       i2c_detect => sub { mtp008_detect @_},
853     } ,
854     {
855       name => "National Semiconductor LM78",
856       driver => "lm78",
857       i2c_addrs => [0x20..0x2f], 
858       i2c_detect => sub { lm78_detect 0, @_},
859       isa_addrs => [0x290],
860       isa_detect => sub { lm78_isa_detect 0, @_ },
861       alias_detect => sub { lm78_alias_detect 0, @_ },
862     } ,
863     {
864       name => "National Semiconductor LM78-J",
865       driver => "lm78",
866       i2c_addrs => [0x20..0x2f], 
867       i2c_detect => sub { lm78_detect 1, @_ },
868       isa_addrs => [0x290],
869       isa_detect => sub { lm78_isa_detect 1, @_ },
870       alias_detect => sub { lm78_alias_detect 1, @_ },
871     } ,
872     {
873       name => "National Semiconductor LM79",
874       driver => "lm78",
875       i2c_addrs => [0x20..0x2f], 
876       i2c_detect => sub { lm78_detect 2, @_ },
877       isa_addrs => [0x290],
878       isa_detect => sub { lm78_isa_detect 2, @_ },
879       alias_detect => sub { lm78_alias_detect 2, @_ },
880     } ,
881     {
882       name => "National Semiconductor LM75",
883       driver => "lm75",
884       i2c_addrs => [0x48..0x4f],
885       i2c_detect => sub { lm75_detect @_},
886     } ,
887     {
888       name => "National Semiconductor LM80",
889       driver => "lm80",
890       i2c_addrs => [0x28..0x2f],
891       i2c_detect => sub { lm80_detect @_} ,
892     },
893     {
894       name => "National Semiconductor LM85",
895       driver => "lm85",
896       i2c_addrs => [0x2c..0x2e],
897       i2c_detect => sub { lm85_detect 0x01, @_},
898     },
899     {
900       name => "Analog Devices ADM1027, ADT7460 or ADT7463",
901       driver => "lm85",
902       i2c_addrs => [0x2c..0x2e],
903       i2c_detect => sub { lm85_detect 0x41, @_},
904     },
905     {
906       name => "SMSC EMC6D100 or EMC6D101",
907       driver => "lm85",
908       i2c_addrs => [0x2c..0x2e],
909       i2c_detect => sub { lm85_detect 0x5c, @_},
910     },
911     {
912       name => "Analog Devices ADT7467",
913       driver => "to-be-written",
914       i2c_addrs => [0x2e],
915       i2c_detect => sub { adt7467_detect 0, @_},
916     },
917     {
918       name => "National Semiconductor LM87",
919       driver => "lm87",
920       i2c_addrs => [0x2c..0x2e],
921       i2c_detect => sub { lm87_detect @_} ,
922     },
923     {
924       name => "Winbond W83781D",
925       driver => "w83781d",
926       i2c_detect => sub { w83781d_detect 0, @_},
927       i2c_addrs => [0x20..0x2f], 
928       isa_addrs => [0x290],
929       isa_detect => sub { w83781d_isa_detect 0, @_ },
930       alias_detect => sub { w83781d_alias_detect 0, @_ },
931     } ,
932     {
933       name => "Winbond W83782D",
934       driver => "w83781d",
935       i2c_addrs => [0x20..0x2f], 
936       i2c_detect => sub { w83781d_detect 1, @_},
937       isa_addrs => [0x290],
938       isa_detect => sub { w83781d_isa_detect 1, @_ },
939       alias_detect => sub { w83781d_alias_detect 1, @_ },
940     } ,
941     {
942       name => "Winbond W83783S",
943       driver => "w83781d",
944       i2c_addrs => [0x2d],
945       i2c_detect => sub { w83781d_detect 2, @_},
946     } ,
947     {
948       name => "Winbond W83791D",
949       driver => "w83781d",
950       i2c_addrs => [0x2c..0x2f],
951       i2c_detect => sub { w83781d_detect 7, @_},
952     } ,
953     {
954       name => "Winbond W83627HF",
955       driver => "w83781d",
956       i2c_addrs => [0x20..0x2f], 
957       i2c_detect => sub { w83781d_detect 3, @_},
958       isa_addrs => [0x290],
959       isa_detect => sub { w83781d_isa_detect 3, @_ },
960       alias_detect => sub { w83781d_alias_detect 3, @_ },
961     } ,
962     {
963       name => "Asus AS99127F (rev.1)",
964       driver => "w83781d",
965       i2c_addrs => [0x28..0x2f],
966       i2c_detect => sub { w83781d_detect 4, @_},
967     } ,
968     {
969       name => "Asus AS99127F (rev.2)",
970       driver => "w83781d",
971       i2c_addrs => [0x28..0x2f],
972       i2c_detect => sub { w83781d_detect 5, @_},
973     } ,
974     {
975       name => "Asus ASB100 Bach",
976       driver => "asb100",
977       i2c_addrs => [0x28..0x2f],
978       i2c_detect => sub { w83781d_detect 6, @_},
979     } ,
980     {
981       name => "Asus ASM58 Mozart-2",
982       driver => "to-be-written",
983       i2c_addrs => [0x77],
984       i2c_detect => sub { mozart_detect 0, @_},
985     } ,
986     {
987       name => "Asus AS2K129R Mozart-2",
988       driver => "to-be-written",
989       i2c_addrs => [0x77],
990       i2c_detect => sub { mozart_detect 1, @_},
991     } ,
992     {
993       name => "Asus Mozart-2",
994       driver => "to-be-written",
995       i2c_addrs => [0x77],
996       i2c_detect => sub { mozart_detect 2, @_},
997     } ,
998     {
999       name => "Winbond W83L784R/AR",
1000       driver => "to-be-written",
1001       i2c_addrs => [0x2d],
1002       i2c_detect => sub { w83l784r_detect 0, @_},
1003     } ,
1004     {
1005       name => "Winbond W83L785R",
1006       driver => "to-be-written",
1007       i2c_addrs => [0x2d],
1008       i2c_detect => sub { w83l784r_detect 1, @_},
1009     } ,
1010     {
1011       name => "Winbond W83L785TS-S",
1012       driver => "w83l785ts",
1013       i2c_addrs => [0x2e], 
1014       i2c_detect => sub { w83l785ts_detect 0, @_},
1015     } ,
1016     {
1017       name => "Winbond W83697HF",
1018       driver => "w83781d",
1019       isa_addrs => [0x290],
1020       isa_detect => sub { w83781d_isa_detect 5, @_ },
1021     } ,
1022     {
1023       name => "Genesys Logic GL518SM Revision 0x00",
1024       driver => "gl518sm",
1025       i2c_addrs => [0x2c, 0x2d],
1026       i2c_detect => sub { gl518sm_detect 0, @_} ,
1027     },
1028     {
1029       name => "Genesys Logic GL518SM Revision 0x80",
1030       driver => "gl518sm",
1031       i2c_addrs => [0x2c, 0x2d],
1032       i2c_detect => sub { gl518sm_detect 1, @_} ,
1033     },
1034     {
1035       name => "Genesys Logic GL520SM",
1036       driver => "gl520sm",
1037       i2c_addrs => [0x2c, 0x2d],
1038       i2c_detect => sub { gl520sm_detect @_} ,
1039     },
1040     {
1041       name => "Genesys Logic GL525SM",
1042       driver => "Unwritten (GL525SM)",
1043       i2c_addrs => [0x2d],
1044       i2c_detect => sub { gl525sm_detect @_} ,
1045     },
1046     {
1047       name => "Analog Devices ADM9240",
1048       driver => "adm9240",
1049       i2c_addrs => [0x2c..0x2f],
1050       i2c_detect => sub { adm9240_detect 0, @_ }
1051     },
1052     {
1053       name => "Dallas Semiconductor DS1621",
1054       driver => "ds1621",
1055       i2c_addrs => [0x48..0x4f],
1056       i2c_detect => sub { ds1621_detect @_},
1057     } ,
1058     {
1059       name => "Dallas Semiconductor DS1780",
1060       driver => "adm9240",
1061       i2c_addrs => [0x2c..0x2f],
1062       i2c_detect => sub { adm9240_detect 1, @_ }
1063     },
1064     {
1065       name => "National Semiconductor LM81",
1066       driver => "adm9240",
1067       i2c_addrs => [0x2c..0x2f],
1068       i2c_detect => sub { adm9240_detect 2, @_ }
1069     },
1070     {
1071       name => "Analog Devices ADM1026",
1072       driver => "adm1026",
1073       i2c_addrs => [0x2c,0x2d,0x2e],
1074       i2c_detect => sub { adm1026_detect 0, @_ }
1075     },
1076     {
1077       name => "Analog Devices ADM1025",
1078       driver => "adm1025",
1079       i2c_addrs => [0x2c..0x2e],
1080       i2c_detect => sub { adm1025_detect 0, @_ }
1081     },
1082     {
1083       name => "Philips NE1619",
1084       driver => "adm1025",
1085       i2c_addrs => [0x2c..0x2d],
1086       i2c_detect => sub { adm1025_detect 1, @_ }
1087     },
1088     {
1089       name => "Analog Devices ADM1024",
1090       driver => "adm1024",
1091       i2c_addrs => [0x2c..0x2e],
1092       i2c_detect => sub { adm1024_detect 0, @_ }
1093     },
1094     {
1095       name => "Analog Devices ADM1021",
1096       driver => "adm1021",
1097       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1098       i2c_detect => sub { adm1021_detect 0, @_ },
1099     },
1100     {
1101       name => "Analog Devices ADM1021A/ADM1023",
1102       driver => "adm1021",
1103       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1104       i2c_detect => sub { adm1021_detect 1, @_ },
1105     },
1106     {
1107       name => "Maxim MAX1617",
1108       driver => "adm1021",
1109       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1110       i2c_detect => sub { adm1021_detect 2, @_ },
1111     },
1112     {
1113       name => "Maxim MAX1617A",
1114       driver => "adm1021",
1115       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1116       i2c_detect => sub { adm1021_detect 3, @_ },
1117     },
1118     {
1119       name => "Maxim MAX6650/MAX6651",
1120       driver => "max6650",
1121       i2c_addrs => [0x1b,0x1f,0x48,0x4b],
1122       i2c_detect => sub { max6650_detect 0, @_ },
1123     },
1124     {
1125       name => "TI THMC10",
1126       driver => "adm1021",
1127       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1128       i2c_detect => sub { adm1021_detect 4, @_ },
1129     },
1130     {
1131       name => "National Semiconductor LM84",
1132       driver => "adm1021",
1133       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1134       i2c_detect => sub { adm1021_detect 5, @_ },
1135     },
1136     {
1137       name => "Genesys Logic GL523SM",
1138       driver => "adm1021",
1139       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1140       i2c_detect => sub { adm1021_detect 6, @_ },
1141     },
1142     {
1143       name => "Onsemi MC1066",
1144       driver => "adm1021",
1145       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1146       i2c_detect => sub { adm1021_detect 7, @_ },
1147     },
1148     {
1149       name => "National Semiconductor LM82",
1150       driver => "to-be-written",
1151       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1152       i2c_detect => sub { lm83_detect 1, @_ },
1153     },
1154     {
1155       name => "National Semiconductor LM83",
1156       driver => "lm83",
1157       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1158       i2c_detect => sub { lm83_detect 0, @_ },
1159     },
1160     {
1161       name => "National Semiconductor LM90",
1162       driver => "lm90",
1163       i2c_addrs => [0x4c],
1164       i2c_detect => sub { lm90_detect 0, @_ },
1165     },
1166     {
1167       name => "National Semiconductor LM89/LM99",
1168       driver => "lm90",
1169       i2c_addrs => [0x4c..0x4d],
1170       i2c_detect => sub { lm90_detect 1, @_ },
1171     },
1172     {
1173       name => "National Semiconductor LM86",
1174       driver => "to-be-written",
1175       i2c_addrs => [0x4c],
1176       i2c_detect => sub { lm90_detect 2, @_ },
1177     },
1178     {
1179       name => "Analog Devices ADM1032",
1180       driver => "lm90",
1181       i2c_addrs => [0x4c],
1182       i2c_detect => sub { lm90_detect 3, @_ },
1183     },
1184     {
1185       name => "Maxim MAX6657/MAX6658",
1186       driver => "to-be-written",
1187       i2c_addrs => [0x4c],
1188       i2c_detect => sub { lm90_detect 4, @_ },
1189     },
1190     {
1191       name => "National Semiconductor LM92",
1192       driver => "lm92",
1193       i2c_addrs => [0x48..0x4b],
1194       i2c_detect => sub { lm92_detect 0, @_ },
1195     },
1196     {
1197       name => "National Semiconductor LM76",
1198       driver => "lm92",
1199       i2c_addrs => [0x48..0x4b],
1200       i2c_detect => sub { lm92_detect 1, @_ },
1201     },
1202     {
1203       name => "Maxim MAX6633/MAX6634/MAX6635",
1204       driver => "lm92",
1205       i2c_addrs => [0x40..0x4f],
1206       i2c_detect => sub { lm92_detect 2, @_ },
1207     },
1208     {
1209       name => "Analog Devices ADT7461",
1210       driver => "to-be-written",
1211       i2c_addrs => [0x4c],
1212       i2c_detect => sub { lm90_detect 5, @_ },
1213     },
1214     {
1215       name => "Analog Devices ADM1029",
1216       driver => "to-be-written",
1217       i2c_addrs => [0x28..0x2f],
1218       i2c_detect => sub { adm1029_detect 0, @_ },
1219     },
1220     {
1221       name => "Analog Devices ADM1030",
1222       driver => "to-be-written",
1223       i2c_addrs => [0x2c..0x2e],
1224       i2c_detect => sub { adm1031_detect 0, @_ },
1225     },
1226     {
1227       name => "Analog Devices ADM1031",
1228       driver => "to-be-written",
1229       i2c_addrs => [0x2c..0x2e],
1230       i2c_detect => sub { adm1031_detect 1, @_ },
1231     },
1232     {
1233       name => "Analog Devices ADM1022",
1234       driver => "thmc50",
1235       i2c_addrs => [0x2c..0x2e],
1236       i2c_detect => sub { adm1022_detect 0, @_ },
1237     },
1238     {
1239       name => "Texas Instruments THMC50",
1240       driver => "thmc50",
1241       i2c_addrs => [0x2c..0x2e],
1242       i2c_detect => sub { adm1022_detect 1, @_ },
1243     },
1244     {
1245       name => "Analog Devices ADM1028",
1246       driver => "thmc50",
1247       i2c_addrs => [0x2e],
1248       i2c_detect => sub { adm1022_detect 2, @_ },
1249     },
1250     {
1251       name => "Silicon Integrated Systems SIS5595",
1252       driver => "sis5595",
1253       isa_addrs => [ 0 ],
1254       isa_detect => sub { sis5595_isa_detect @_ },
1255     },
1256     {
1257       name => "VIA Technologies VT82C686 Integrated Sensors",
1258       driver => "via686a",
1259       isa_addrs => [ 0 ],
1260       isa_detect => sub { via686a_isa_detect @_ },
1261     },
1262     {
1263       name => "VIA Technologies VT8231 Integrated Sensors",
1264       driver => "vt8231",
1265       isa_addrs => [ 0 ],
1266       isa_detect => sub { via8231_isa_detect @_ },
1267     },
1268     {
1269       name => "ITE IT8705F / IT8712F / SiS 950",
1270       driver => "it87",
1271       i2c_addrs => [0x20..0x2f],
1272       i2c_detect => sub { ite_detect 0, @_ },
1273       isa_addrs => [0x290],
1274       isa_detect => sub { ite_isa_detect 0, @_ },
1275     } ,
1276     {
1277       name => "SPD EEPROM",
1278       driver => "eeprom",
1279       i2c_addrs => [0x50..0x57],
1280       i2c_detect => sub { eeprom_detect 0, @_ },
1281     },
1282     {
1283       name => "Sony Vaio EEPROM",
1284       driver => "eeprom",
1285       i2c_addrs => [0x57],
1286       i2c_detect => sub { eeprom_detect 1, @_ },
1287     },
1288# Disabled by default (potentially dangerous)
1289#     {
1290#       name => "SPD EEPROM with Software Write-Protect",
1291#       driver => "eeprom",
1292#       i2c_addrs => [0x50..0x57],
1293#       i2c_detect => sub { eeprom_detect 2, @_ },
1294#     },
1295     {
1296       name => "DDC monitor",
1297       driver => "ddcmon",
1298       i2c_addrs => [0x50],
1299       i2c_detect => sub { ddcmonitor_detect @_ },
1300     },
1301     {
1302       name => "FSC Poseidon",
1303       driver => "fscpos",
1304       i2c_addrs => [0x73],
1305       i2c_detect => sub { fscpos_detect @_ },
1306     },
1307     {
1308       name => "FSC Scylla",
1309       driver => "fscscy",
1310       i2c_addrs => [0x73],
1311       i2c_detect => sub { fscscy_detect @_ },
1312     },
1313     {
1314       name => "FSC Hermes",
1315       driver => "fscher",
1316       i2c_addrs => [0x73],
1317       i2c_detect => sub { fscher_detect @_ },
1318     },
1319     {
1320       name => "ALi M5879",
1321       driver => "to-be-written",
1322       i2c_addrs => [0x2c..0x2d],
1323       i2c_detect => sub { m5879_detect @_},
1324     } ,
1325     {
1326       name => "Philips Semiconductors SAA1064",
1327       driver => "saa1064",
1328       i2c_addrs => [0x38..0x3b],
1329       i2c_detect => sub { saa1064_detect @_ },
1330     },
1331     {
1332       name => "Philips Semiconductors PCA9540",
1333       driver => "pca9540",
1334       i2c_addrs => [0x70],
1335       i2c_detect => sub { pca9540_detect @_ },
1336     },
1337     {
1338       name => "Maxim MAX6900",
1339       driver => "to-be-written",
1340       i2c_addrs => [0x50],
1341       i2c_detect => sub { max6900_detect @_ },
1342     },
1343     {
1344       name => "SMBus 2.0 ARP-Capable Device",
1345       driver => "smbus-arp",
1346       i2c_addrs => [0x61],
1347       i2c_detect => sub { arp_detect @_},
1348     },
1349     {
1350       name => "IPMI BMC KCS",
1351       driver => "bmcsensors",
1352       isa_addrs => [ 0x0ca0 ],
1353       isa_detect => sub { ipmi_kcs_detect @_ },
1354     },
1355     {
1356       name => "IPMI BMC SMIC",
1357       driver => "bmcsensors",
1358       isa_addrs => [ 0x0ca8 ],
1359       isa_detect => sub { ipmi_smic_detect @_ },
1360     },
1361     {
1362       name => "Smart Battery Charger",
1363       driver => "to-be-written",
1364       i2c_addrs => [0x09],
1365       i2c_detect => sub { smartbatt_chgr_detect @_},
1366     },
1367     {
1368       name => "Smart Battery Manager/Selector",
1369       driver => "to-be-written",
1370       i2c_addrs => [0x0a],
1371       i2c_detect => sub { smartbatt_mgr_detect @_},
1372     },
1373     {
1374       name => "Smart Battery",
1375       driver => "smartbatt",
1376       i2c_addrs => [0x0b],
1377       i2c_detect => sub { smartbatt_detect @_},
1378     },
1379);
1380
1381# This is a list of all recognized superio chips.
1382# Each entry must have the following fields:
1383#  name: The full chip name
1384#  driver: The driver name (without .o extension). Put in
1385#      "to-be-written" if it is not yet available.
1386#      Put in "not-a-sensor" if the chip doesn't have hardware monitoring
1387#      capabilities (listing such chips here removes the need of manual
1388#      lookup when people report them).
1389#  enter: The password sequence to write to the address register
1390#  devid: The device ID(s) we have to match (base device)
1391#  logdev: The logical device containing the sensors
1392#  exit (optional): Sequence to write to the address register to exit config
1393#      mode. If not provided, a default reset operation is performed.
1394#  alias_detect (optional): For chips which can be both on the ISA and the
1395#      I2C bus, a function which detectes whether two entries are the same.
1396#      The function should take three parameters: The ISA address, the
1397#      I2C bus number, and the I2C address.
1398@superio_ids = (
1399  {
1400    enter => [0x87, 0x01, 0x55, 0x55],
1401    chips =>
1402    [
1403      {
1404        name => "ITE 8702F Super IO Sensors",
1405        driver => "to-be-written",
1406        devid => 0x8702,
1407        logdev => 0x04,
1408      },
1409      {
1410        name => "ITE 8705F Super IO Sensors",
1411        driver => "it87",
1412        devid => 0x8705,
1413        logdev => 0x04,
1414      },
1415      {
1416        name => "ITE 8712F Super IO Sensors",
1417        driver => "it87",
1418        devid => 0x8712,
1419        logdev => 0x04,
1420      },
1421    ],
1422  },
1423  {
1424    enter => [],
1425    chips =>
1426    [
1427      {
1428        name => "Nat. Semi. PC87351 Super IO Fan Sensors",
1429        driver => "to-be-written",
1430        devid => 0xe2,
1431        logdev => 0x08,
1432      },
1433      {
1434        name => "Nat. Semi. PC87360 Super IO Fan Sensors",
1435        driver => "pc87360",
1436        devid => 0xe1,
1437        logdev => 0x09,
1438      },
1439      {
1440        name => "Nat. Semi. PC87363 Super IO Fan Sensors",
1441        driver => "pc87360",
1442        devid => 0xe8,
1443        logdev => 0x09,
1444      },
1445      {
1446        name => "Nat. Semi. PC87364 Super IO Fan Sensors",
1447        driver => "pc87360",
1448        devid => 0xe4,
1449        logdev => 0x09,
1450      },
1451      {
1452        name => "Nat. Semi. PC87365 Super IO Fan Sensors",
1453        driver => "pc87360",
1454        devid => 0xe5,
1455        logdev => 0x09,
1456      },
1457      {
1458        name => "Nat. Semi. PC87365 Super IO Voltage Sensors",
1459        driver => "pc87360",
1460        devid => 0xe5,
1461        logdev => 0x0d,
1462      },
1463      {
1464        name => "Nat. Semi. PC87365 Super IO Thermal Sensors",
1465        driver => "pc87360",
1466        devid => 0xe5,
1467        logdev => 0x0e,
1468      },
1469      {
1470        name => "Nat. Semi. PC87366 Super IO Fan Sensors",
1471        driver => "pc87360",
1472        devid => 0xe9,
1473        logdev => 0x09,
1474      },
1475      {
1476        name => "Nat. Semi. PC87366 Super IO Voltage Sensors",
1477        driver => "pc87360",
1478        devid => 0xe9,
1479        logdev => 0x0d,
1480      },
1481      {
1482        name => "Nat. Semi. PC87366 Super IO Thermal Sensors",
1483        driver => "pc87360",
1484        devid => 0xe9,
1485        logdev => 0x0e,
1486      },
1487      {
1488        name => "Nat. Semi. PC87372 Super IO Fan Sensors",
1489        driver => "to-be-written",
1490        devid => 0xf0,
1491        logdev => 0x09,
1492      },
1493      {
1494        name => "Nat. Semi. PC8741x Super IO",
1495        driver => "not-a-sensor",
1496        devid => 0xee,
1497      },
1498    ],
1499  },
1500  {
1501    enter => [0x55],
1502    exit => [0xaa],
1503    chips =>
1504    [
1505      {
1506        name => "SMSC 47B27x Super IO Fan Sensors",
1507        driver => "smsc47m1",
1508        devid => 0x51,
1509        logdev => 0x0a,
1510      },
1511      {
1512        name => "SMSC 47M10x/13x Super IO Fan Sensors",
1513        driver => "smsc47m1",
1514        devid => 0x59,
1515        logdev => 0x0a,
1516      },
1517      {
1518        name => "SMSC 47M14x Super IO Fan Sensors",
1519        driver => "smsc47m1",
1520        devid => 0x5f,
1521        logdev => 0x0a,
1522      },
1523      {
1524        name => "SMSC 47M15x/192 Super IO Fan Sensors",
1525        driver => "to-be-written",
1526        devid => 0x60,
1527        logdev => 0x0a,
1528      },
1529      {
1530        name => "SMSC 47S42x Super IO Fan Sensors",
1531        driver => "to-be-written",
1532        devid => 0x57,
1533        logdev => 0x0a,
1534      },
1535      {
1536        name => "SMSC 47S45x Super IO Fan Sensors",
1537        driver => "to-be-written",
1538        devid => 0x62,
1539        logdev => 0x0a,
1540      },
1541      {
1542        name => "SMSC 47M172 Super IO",
1543        driver => "not-a-sensor",
1544        devid => 0x14,
1545      },
1546    ],
1547  },
1548  {
1549    enter => [0x87, 0x87],
1550    exit => [0xaa],
1551    chips =>
1552    [
1553      {
1554        name => "VT1211 Super IO Sensors",
1555        driver => "vt1211",
1556        devid => 0x3c,
1557        logdev => 0x0b,
1558      },
1559      {
1560        name => "Winbond W83627HF Super IO Sensors",
1561        driver => "w83627hf",
1562        devid => 0x52,
1563        logdev => 0x0b,
1564      },
1565      {
1566        name => "Winbond W83627THF Super IO Sensors",
1567        driver => "w83627hf",
1568        devid => 0x82,
1569        logdev => 0x0b,
1570      },
1571      {
1572        name => "Winbond W83637HF Super IO Sensors",
1573        driver => "w83627hf",
1574        devid => 0x70,
1575        logdev => 0x0b,
1576      },
1577      {
1578        name => "Winbond W83697HF Super IO Sensors",
1579        driver => "w83627hf",
1580        devid => 0x60,
1581        logdev => 0x0b,
1582      },
1583      {
1584        name => "Winbond W83697SF/UF Super IO PWM",
1585        driver => "to-be-written",
1586        devid => 0x68,
1587        logdev => 0x0b,
1588      },
1589      {
1590        name => "Winbond W83L517D Super IO",
1591        driver => "not-a-sensor",
1592        devid => 0x61,
1593      },
1594    ],
1595  },
1596);
1597
1598#######################
1599# AUXILIARY FUNCTIONS #
1600#######################
1601
1602sub swap_bytes
1603{
1604  return (($_[0] & 0xff00) >> 8) + (($_[0] & 0x00ff) << 8)
1605}
1606
1607# $_[0] is the sought value
1608# @_[1..] is the list to seek in
1609# Returns: 0 on failure, 1 if found.
1610sub contains
1611{
1612  my $sought = shift;
1613  foreach (@_) {
1614    return 1 if $sought eq $_;
1615  }
1616  return 0;
1617}
1618
1619sub parse_not_to_scan
1620{
1621  my ($min,$max,$to_parse) = @_;
1622  my @ranges = split /\s*,\s*/, $to_parse;
1623  my @res = ();
1624  my $range;
1625  foreach $range (@ranges) {
1626    my ($start,$end) = split /\s*-s*/, $range;
1627    $start = oct $start if $start =~ /^0/;
1628    if (defined $end) {
1629      $end = oct $end if $end =~ /^0/;
1630      $start = $min if $start < $min;
1631      $end = $max if $end > $max;
1632      push @res, ($start+0..$end+0);
1633    } else {
1634      push @res, $start+0 if $start >= $min and $start <= $max;
1635    }
1636  }
1637  return sort { $a <=> $b } @res;
1638}
1639
1640# @_[0]: Reference to list 1
1641# @_[1]: Reference to list 2
1642# Result: 0 if they have no elements in common, 1 if they have
1643# Elements must be numeric.
1644sub any_list_match
1645{
1646  my ($list1,$list2) = @_;
1647  my ($el1,$el2);
1648  foreach $el1 (@$list1) {
1649    foreach $el2 (@$list2) {
1650      return 1 if $el1 == $el2;
1651    }
1652  }
1653  return 0;
1654}
1655
1656###################
1657# I/O port access #
1658###################
1659
1660sub initialize_ioports
1661{
1662  sysopen (IOPORTS, "/dev/port", O_RDWR)
1663    or die "/dev/port: $!\n";
1664  binmode IOPORTS;
1665}
1666
1667sub close_ioports
1668{
1669  close (IOPORTS)
1670    or print "Warning: $!\n";
1671}
1672
1673# $_[0]: port to read
1674# Returns: -1 on failure, read value on success.
1675sub inb
1676{
1677  my ($res,$nrchars);
1678  sysseek IOPORTS, $_[0], 0 or return -1;
1679  $nrchars = sysread IOPORTS, $res, 1;
1680  return -1 if not defined $nrchars or $nrchars != 1;
1681  $res = unpack "C",$res ;
1682  return $res;
1683}
1684
1685# $_[0]: port to write
1686# $_[1]: value to write
1687# Returns: -1 on failure, 0 on success.
1688sub outb
1689{
1690  if ($_[1] > 0xff)
1691  {
1692    my ($package, $filename, $line, $sub) = caller(1);
1693    print "\n*** Called outb with value=$_[1] from line $line\n",
1694          "*** (in $sub). PLEASE REPORT!\n",
1695          "*** Terminating.\n";
1696    exit(-1);
1697  }
1698  my $towrite = pack "C", $_[1];
1699  sysseek IOPORTS, $_[0], 0 or return -1;
1700  my $nrchars = syswrite IOPORTS, $towrite, 1;
1701  return -1 if not defined $nrchars or $nrchars != 1;
1702  return 0;
1703}
1704
1705# $_[0]: Address register
1706# $_[1]: Data register
1707# $_[2]: Register to read
1708# Returns: read value
1709sub isa_read_byte
1710{
1711  outb $_[0],$_[2];
1712  return inb $_[1];
1713}
1714
1715# $_[0]: Address register
1716# $_[1]: Data register
1717# $_[2]: Register to write
1718# $_[3}: Value to write
1719# Returns: nothing
1720sub isa_write_byte
1721{
1722  outb $_[0],$_[2];
1723  outb $_[1],$_[3];
1724}
1725
1726#################
1727# AUTODETECTION #
1728#################
1729
1730use vars qw($modules_conf $dev_i2c);
1731
1732sub initialize_conf
1733{
1734  my $use_devfs = 0;
1735  open INPUTFILE, "/proc/mounts" or die "Can't access /proc/mounts!";
1736  while (<INPUTFILE>) {
1737    if (m@^\w+ /dev devfs @) {
1738      $use_devfs = 1;
1739      $dev_i2c = '/dev/i2c/';
1740      last;
1741    }
1742  }
1743  close INPUTFILE;
1744
1745  if (-f '/etc/modules.conf') {
1746    $modules_conf = '/etc/modules.conf';
1747  } elsif (-f '/etc/conf.modules') {
1748    $modules_conf = '/etc/conf.modules';
1749  } else { # default
1750    $modules_conf = '/etc/modules.conf';
1751  }
1752
1753  if (!$use_devfs) {
1754    if (-c '/dev/i2c-0') {
1755      $dev_i2c = '/dev/i2c-';
1756    } else { # default
1757      print "No i2c device files found. Use prog/mkdev/mkdev.sh to create them.\n";
1758      exit -1;
1759    }
1760  }
1761}
1762
1763# [0] -> VERSION
1764# [1] -> PATCHLEVEL
1765# [2] -> SUBLEVEL
1766# [3] -> EXTRAVERSION
1767#
1768use vars qw(@kernel_version);
1769
1770sub initialize_kernel_version
1771{
1772  `uname -r` =~ /(\d+)\.(\d+)\.(\d+)(.*)/;
1773  @kernel_version = ($1, $2, $3, $4);
1774}
1775
1776sub kernel_version_at_least
1777{
1778  my ($vers, $plvl, $slvl) = @_;
1779  return 1 if ($kernel_version[0]  > $vers ||
1780                ($kernel_version[0] == $vers && 
1781                  ($kernel_version[1]  > $plvl || 
1782                    ($kernel_version[1] == $plvl && 
1783                      ($kernel_version[2] >= $slvl)))));
1784  return 0;
1785}
1786
1787###########
1788# MODULES #
1789###########
1790
1791use vars qw(%modules_list);
1792
1793sub initialize_modules_list
1794{
1795  open INPUTFILE, "/proc/modules" or die "Can't access /proc/modules!";
1796  while (<INPUTFILE>) {
1797    tr/_/-/;
1798    $modules_list{$1} = 1 if m/^(\S*)/;
1799  }
1800  close INPUTFILE;
1801}
1802
1803##############
1804# PCI ACCESS #
1805##############
1806
1807use vars qw(%pci_list);
1808
1809# This function returns a hash of hashes. Each hash has some PCI information
1810# (more than we will ever need, probably). The most important
1811# fields are 'bus', 'slot', 'func' (they uniquely identify a PCI device in
1812# a computer) and 'vendid','devid' (they uniquely identify a type of device).
1813sub read_proc_dev_pci
1814{
1815  my ($dfn,$vend,%pci_list);
1816  open INPUTFILE, "/proc/bus/pci/devices" or return;
1817  while (<INPUTFILE>) {
1818    my $record = {};
1819    ($dfn,$vend,$record->{irq},$record->{base_addr0},$record->{base_addr1},
1820          $record->{base_addr2},$record->{base_addr3},$record->{base_addr4},
1821          $record->{base_addr5},$record->{rom_base_addr}) = 
1822          map { oct "0x$_" } (split) [0..9];
1823    $record->{bus} = $dfn >> 8;
1824    $record->{slot} = ($dfn & 0xf8) >> 3;
1825    $record->{func} = $dfn & 0x07;
1826    $record->{vendid} = $vend >> 16;
1827    $record->{devid} = $vend & 0xffff;
1828   
1829    $pci_list{ sprintf("%04x:%04x",$record->{vendid},$record->{devid}) } =
1830        $record;
1831  }
1832  close INPUTFILE or return;
1833  return %pci_list;
1834}
1835
1836sub initialize_proc_pci
1837{
1838  %pci_list = read_proc_dev_pci;
1839  die "Can't access /proc/bus/pci/devices!" if not defined %pci_list;
1840}
1841
1842#####################
1843# ADAPTER DETECTION #
1844#####################
1845
1846sub all_available_adapters
1847{
1848  my @res = ();
1849  foreach my $adapter (@pci_adapters) {
1850    push @res, $adapter->{driver}
1851      if exists $modules_list{$adapter->{driver}};
1852  }
1853  return @res;
1854}
1855
1856sub adapter_pci_detection_sis_96x
1857{
1858  my $driver="";
1859
1860  # first, determine which driver if any...
1861  if (kernel_version_at_least(2,6,0)) {
1862    if (exists $pci_list{"1039:0016"}) {
1863      $driver = "i2c-sis96x";
1864    } elsif (exists $pci_list{"1039:0008"}) {
1865      $driver = "i2c-sis5595";
1866    }
1867  } elsif (kernel_version_at_least(2,4,0)) {
1868    if (exists $pci_list{"1039:0008"}) {
1869      if ((exists $pci_list{"1039:0645"}) ||
1870          (exists $pci_list{"1039:0646"}) ||
1871          (exists $pci_list{"1039:0648"}) ||
1872          (exists $pci_list{"1039:0650"}) ||
1873          (exists $pci_list{"1039:0651"}) ||
1874          (exists $pci_list{"1039:0655"}) ||
1875          (exists $pci_list{"1039:0735"}) ||
1876          (exists $pci_list{"1039:0745"}) ||
1877          (exists $pci_list{"1039:0746"})) {
1878        $driver = "i2c-sis645";
1879      } else {
1880        $driver = "i2c-sis5595";
1881      }
1882    } elsif ((exists $pci_list{"1039:0016"}) ||
1883             (exists $pci_list{"1039:0018"})) {
1884      $driver = "i2c-sis645";
1885    }
1886  }
1887
1888  # then, add the appropriate entries to @pci_adapters
1889  if ($driver eq "i2c-sis5595") {
1890    push @pci_adapters, @pci_adapters_sis5595;
1891  } elsif ($driver eq "i2c-sis645") {
1892    push @pci_adapters, @pci_adapters_sis645;
1893  } elsif ($driver eq "i2c-sis96x") {
1894    push @pci_adapters, @pci_adapters_sis96x;
1895  }
1896}
1897
1898sub adapter_pci_detection
1899{
1900  my ($key,$device,$try,@res);
1901  print "Probing for PCI bus adapters...\n";
1902
1903  # Custom detection routine for some SiS chipsets
1904  adapter_pci_detection_sis_96x();
1905
1906  # Generic detection loop
1907  while ( ($key, $device) = each %pci_list) {
1908    foreach $try (@pci_adapters) {
1909      if ((defined($device->{vendid}) and 
1910           $try->{vendid} == $device->{vendid} and
1911           $try->{devid} == $device->{devid} and
1912           $try->{func} == $device->{func}) or
1913          (! defined($device->{vendid}) and
1914           $device->{desc} =~ /$try->{procid}/ and
1915           $try->{func} == $device->{func})) {
1916        printf "Use driver `%s' for device %02x:%02x.%x: %s\n",
1917               $try->{driver}?$try->{driver}:"<To Be Written>",
1918               $device->{bus},$device->{slot},$device->{func},$try->{procid};
1919        push @res,$try->{driver};
1920      }
1921    }
1922  }
1923  if (! @res) {
1924    print ("Sorry, no PCI bus adapters found.\n");
1925  } else {
1926    printf ("Probe succesfully concluded.\n");
1927  }
1928  return @res;
1929}
1930
1931# $_[0]: Adapter description as found in /proc/bus/i2c
1932# $_[1]: Algorithm description as found in /proc/bus/i2c
1933sub find_adapter_driver
1934{
1935  my $adapter;
1936  for $adapter (@pci_adapters) {
1937    return $adapter->{driver} if &{$adapter->{match}} ($_[0],$_[1]);
1938  }
1939  return "UNKNOWN";
1940}
1941
1942#############################
1943# I2C AND SMBUS /DEV ACCESS #
1944#############################
1945
1946# This should really go into a separate module/package.
1947
1948# To do: support i2c-level access (through sysread/syswrite, probably).
1949# I can't test this at all (PIIX4 does not support this), so I have not
1950# included it.
1951
1952use vars qw($IOCTL_I2C_RETRIES $IOCTL_I2C_TIMEOUT $IOCTL_I2C_UDELAY
1953            $IOCTL_I2C_MDELAY $IOCTL_I2C_SLAVE $IOCTL_I2C_TENBIT
1954            $IOCTL_I2C_SMBUS);
1955
1956# These are copied from <linux/i2c.h> and <linux/smbus.h>
1957
1958# For bit-adapters:
1959$IOCTL_I2C_RETRIES = 0x0701;
1960$IOCTL_I2C_TIMEOUT = 0x0702;
1961$IOCTL_I2C_UDELAY = 0x0705;
1962$IOCTL_I2C_MDELAY = 0x0706;
1963
1964# General ones:
1965$IOCTL_I2C_SLAVE = 0x0703;
1966$IOCTL_I2C_TENBIT = 0x0704;
1967$IOCTL_I2C_SMBUS = 0x0720;
1968
1969
1970
1971use vars qw($SMBUS_READ $SMBUS_WRITE $SMBUS_QUICK $SMBUS_BYTE $SMBUS_BYTE_DATA
1972            $SMBUS_WORD_DATA $SMBUS_PROC_CALL $SMBUS_BLOCK_DATA);
1973
1974# These are copied from <linux/smbus.h>
1975
1976$SMBUS_READ = 1;
1977$SMBUS_WRITE = 0;
1978$SMBUS_QUICK = 0;
1979$SMBUS_BYTE = 1;
1980$SMBUS_BYTE_DATA  = 2;
1981$SMBUS_WORD_DATA  = 3;
1982$SMBUS_PROC_CALL = 4;
1983$SMBUS_BLOCK_DATA = 5;
1984
1985# Select the device to communicate with through its address.
1986# $_[0]: Reference to an opened filehandle
1987# $_[1]: Address to select
1988# Returns: 0 on failure, 1 on success.
1989sub i2c_set_slave_addr
1990{
1991  my ($file,$addr) = @_;
1992  ioctl $file, $IOCTL_I2C_SLAVE, $addr or return 0;
1993  return 1;
1994}
1995
1996# i2c_smbus_access is based upon the corresponding C function (see
1997# <linux/i2c-dev.h>). You should not need to call this directly.
1998# Exact calling conventions are intricate; read i2c-dev.c if you really need
1999# to know.
2000# $_[0]: Reference to an opened filehandle
2001# $_[1]: $SMBUS_READ for reading, $SMBUS_WRITE for writing
2002# $_[2]: Command (usually register number)
2003# $_[3]: Transaction kind ($SMBUS_BYTE, $SMBUS_BYTE_DATA, etc.)
2004# $_[4]: Reference to an array used for input/output of data
2005# Returns: 0 on failure, 1 on success.
2006# Note that we need to get back to Integer boundaries through the 'x2'
2007# in the pack. This is very compiler-dependent; I wish there was some other
2008# way to do this.
2009sub i2c_smbus_access
2010{
2011  my ($file,$read_write,$command,$size,$data) = @_;
2012  my $data_array = pack "C32", @$data;
2013  my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
2014  ioctl $file, $IOCTL_I2C_SMBUS, $ioctl_data or return 0;
2015  $_[4] = [ unpack "C32",$data_array ];
2016  return 1;
2017}
2018
2019# $_[0]: Reference to an opened filehandle
2020# $_[1]: Either 0 or 1
2021# Returns: -1 on failure, the 0 on success.
2022sub i2c_smbus_write_quick
2023{
2024  my ($file,$value) = @_;
2025  my $data = [];
2026  i2c_smbus_access $file, $value, 0, $SMBUS_QUICK, $data 
2027         or return -1;
2028  return 0;
2029}
2030
2031# $_[0]: Reference to an opened filehandle
2032# Returns: -1 on failure, the read byte on success.
2033sub i2c_smbus_read_byte
2034{
2035  my ($file) = @_;
2036  my $data = [];
2037  i2c_smbus_access $file, $SMBUS_READ, 0, $SMBUS_BYTE, $data 
2038         or return -1;
2039  return $$data[0];
2040}
2041
2042# $_[0]: Reference to an opened filehandle
2043# $_[1]: Byte to write
2044# Returns: -1 on failure, 0 on success.
2045sub i2c_smbus_write_byte
2046{
2047  my ($file,$command) = @_;
2048  my $data = [$command];
2049  i2c_smbus_access $file, $SMBUS_WRITE, 0, $SMBUS_BYTE, $data 
2050         or return -1;
2051  return 0;
2052}
2053
2054# $_[0]: Reference to an opened filehandle
2055# $_[1]: Command byte (usually register number)
2056# Returns: -1 on failure, the read byte on success.
2057sub i2c_smbus_read_byte_data
2058{
2059  my ($file,$command) = @_;
2060  my $data = [];
2061  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BYTE_DATA, $data 
2062         or return -1;
2063  return $$data[0];
2064}
2065 
2066# $_[0]: Reference to an opened filehandle
2067# $_[1]: Command byte (usually register number)
2068# $_[2]: Byte to write
2069# Returns: -1 on failure, 0 on success.
2070sub i2c_smbus_write_byte_data
2071{
2072  my ($file,$command,$value) = @_;
2073  my $data = [$value];
2074  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BYTE_DATA, $data 
2075         or return -1;
2076  return 0;
2077}
2078
2079# $_[0]: Reference to an opened filehandle
2080# $_[1]: Command byte (usually register number)
2081# Returns: -1 on failure, the read word on success.
2082# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2083# this.
2084sub i2c_smbus_read_word_data
2085{
2086  my ($file,$command) = @_;
2087  my $data = [];
2088  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_WORD_DATA, $data 
2089         or return -1;
2090  return $$data[0] + 256 * $$data[1];
2091}
2092
2093# $_[0]: Reference to an opened filehandle
2094# $_[1]: Command byte (usually register number)
2095# $_[2]: Byte to write
2096# Returns: -1 on failure, 0 on success.
2097# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2098# this.
2099sub i2c_smbus_write_word_data
2100{
2101  my ($file,$command,$value) = @_;
2102  my $data = [$value & 0xff, $value >> 8];
2103  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_WORD_DATA, $data 
2104         or return -1;
2105  return 0;
2106}
2107
2108# $_[0]: Reference to an opened filehandle
2109# $_[1]: Command byte (usually register number)
2110# $_[2]: Word to write
2111# Returns: -1 on failure, read word on success.
2112# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2113# this.
2114sub i2c_smbus_process_call
2115{
2116  my ($file,$command,$value) = @_;
2117  my $data = [$value & 0xff, $value >> 8];
2118  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_PROC_CALL, $data 
2119         or return -1;
2120  return $$data[0] + 256 * $$data[1];
2121}
2122
2123# $_[0]: Reference to an opened filehandle
2124# $_[1]: Command byte (usually register number)
2125# Returns: Undefined on failure, a list of read bytes on success
2126# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2127# this.
2128sub i2c_smbus_read_block_data
2129{
2130  my ($file,$command) = @_;
2131  my $data = [];
2132  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BLOCK_DATA, $data 
2133         or return;
2134  shift @$data;
2135  return @$data;
2136}
2137
2138# $_[0]: Reference to an opened filehandle
2139# $_[1]: Command byte (usually register number)
2140# @_[2..]: List of values to write
2141# Returns: -1 on failure, 0 on success.
2142# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2143# this.
2144sub i2c_smbus_write_block_data
2145{
2146  my ($file,$command,@data) = @_;
2147  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BLOCK_DATA, \@data 
2148         or return;
2149  return 0;
2150}
2151
2152# $_[0]: Reference to an opened filehandle
2153# $_[1]: Address
2154# Returns: 1 on successful probing, 0 else.
2155# This function is meant to prevent AT24RF08 corruption and write-only
2156# chips locks. This is done by choosing the best probing method depending
2157# on the address range.
2158sub i2c_probe
2159{
2160  my ($file, $addr) = @_;
2161  my $data = [];
2162  if (($addr >= 0x50 && $addr <= 0x5F)
2163   || ($addr >= 0x30 && $addr <= 0x37)) {
2164    # This covers all EEPROMs we know of, including page protection addresses.
2165    # Note that some page protection addresses will not reveal themselves with
2166    # this, because they ack on write only, but this is probably better since
2167    # some EEPROMs write-protect themselves permanently on almost any write to
2168    # their page protection address.
2169    return i2c_smbus_access($file, $SMBUS_READ, 0, $SMBUS_BYTE, $data);
2170  } else {
2171    return i2c_smbus_access($file, $SMBUS_WRITE, 0, $SMBUS_QUICK, $data);
2172  }
2173}
2174
2175####################
2176# ADAPTER SCANNING #
2177####################
2178
2179use vars qw(@chips_detected);
2180
2181# We will build a complicated structure @chips_detected here, being:
2182# A list of
2183#  references to hashes
2184#    with field 'driver', being a string with the driver name for this chip;
2185#    with field 'detected'
2186#      being a reference to a list of
2187#        references to hashes of type 'detect_data';
2188#    with field 'misdetected'
2189#      being a reference to a list of
2190#        references to hashes of type 'detect_data'
2191
2192# Type detect_data:
2193# A hash
2194#   with field 'i2c_adap' containing an adapter string as appearing
2195#        in /proc/bus/i2c (if this is an I2C detection)
2196#  with field 'i2c_algo' containing an algorithm string as appearing
2197#       in /proc/bus/i2c (if this is an I2C detection)
2198#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
2199#       adapter (if this is an I2C detection)
2200#  with field 'i2c_driver', containing the driver name for this adapter
2201#       (if this is an I2C detection)
2202#  with field 'i2c_addr', containing the I2C address of the detection;
2203#       (if this is an I2C detection)
2204#  with field 'i2c_sub_addrs', containing a reference to a list of
2205#       other I2C addresses (if this is an I2C detection)
2206#  with field 'i2c_extra' if this is an I2C detection and the address
2207#       is not normally probed by the kernel driver
2208#  with field 'isa_addr' containing the ISA address this chip is on
2209#       (if this is an ISA detection)
2210#  with field 'isa_extra' if this is an ISA detection and the address
2211#       is not normally probed by the kernel driver
2212#  with field 'conf', containing the confidence level of this detection
2213#  with field 'chipname', containing the chip name
2214
2215# This adds a detection to the above structure. We do no alias detection
2216# here; so you should do ISA detections *after* all I2C detections.
2217# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
2218# In all normal cases, it should be all right.
2219# $_[0]: chip driver
2220# $_[1]: reference to data hash
2221# Returns: Nothing
2222sub add_i2c_to_chips_detected
2223{
2224  my ($chipdriver,$datahash) = @_;
2225  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2226      $main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs,
2227      $do_not_add);
2228
2229  # First determine where the hash has to be added.
2230  for ($i = 0; $i < @chips_detected; $i++) {
2231    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2232  }
2233  if ($i == @chips_detected) {
2234    push @chips_detected, { driver => $chipdriver,
2235                            detected => [],
2236                            misdetected => [] };
2237  }
2238  $new_detected_ref = $chips_detected[$i]->{detected};
2239  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2240
2241  # Find out whether our new entry should go into the detected or the
2242  # misdetected list. We compare all i2c addresses; if at least one matches,
2243  # but our conf value is lower, we assume this is a misdetect.
2244  @hash_addrs = ($datahash->{i2c_addr});
2245  push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
2246       if exists $datahash->{i2c_sub_addrs};
2247  $put_in_detected = 1;
2248  $do_not_add = 0;
2249  FIND_LOOP:
2250  foreach $main_entry (@chips_detected) {
2251    foreach $detected_entry (@{$main_entry->{detected}}) {
2252      @entry_addrs = ($detected_entry->{i2c_addr});
2253      push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
2254               if exists $detected_entry->{i2c_sub_addrs};
2255      if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
2256          any_list_match \@entry_addrs, \@hash_addrs) {
2257        if ($detected_entry->{conf} >= $datahash->{conf}) {
2258          $put_in_detected = 0;
2259        }
2260        if ($chipdriver eq $main_entry->{driver}) {
2261          $do_not_add = 1;
2262        }
2263        last FIND_LOOP;
2264      }
2265    }
2266  }
2267
2268  if ($put_in_detected) {
2269    # Here, we move all entries from detected to misdetected which
2270    # match at least in one main or sub address. This may not be the
2271    # best idea to do, as it may remove detections without replacing
2272    # them with second-best ones. Too bad.
2273    # (Khali 2003-09-13) If the driver is the same, the "misdetected"
2274    # entry is simply deleted; failing to do so cause the configuration
2275    # lines generated later to look very confusing (the driver will
2276    # be told to ignore valid addresses).
2277    @hash_addrs = ($datahash->{i2c_addr});
2278    push @hash_addrs, @{$datahash->{i2c_sub_addrs}} 
2279         if exists $datahash->{i2c_sub_addrs};
2280    foreach $main_entry (@chips_detected) {
2281      $detected_ref = $main_entry->{detected};
2282      $misdetected_ref = $main_entry->{misdetected};
2283      for ($i = @$detected_ref-1; $i >=0; $i--) {
2284        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
2285        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
2286             if exists $detected_ref->[$i]->{i2c_sub_addrs};
2287        if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} and
2288            any_list_match \@entry_addrs, \@hash_addrs) {
2289          push @$misdetected_ref,$detected_ref->[$i]
2290            unless $chipdriver eq $main_entry->{driver};
2291          splice @$detected_ref, $i, 1;
2292        }
2293      }
2294    }
2295
2296    # Now add the new entry to detected
2297    push @$new_detected_ref, $datahash;
2298  } else {
2299    # No hard work here
2300    push @$new_misdetected_ref, $datahash
2301      unless $do_not_add;
2302  }
2303}
2304
2305# This adds a detection to the above structure. We also do alias detection
2306# here; so you should do ISA detections *after* all I2C detections.
2307# $_[0]: alias detection function
2308# $_[1]: chip driver
2309# $_[2]: reference to data hash
2310# Returns: 0 if it is not an alias, datahash reference if it is.
2311sub add_isa_to_chips_detected
2312{
2313  my ($alias_detect,$chipdriver,$datahash) = @_;
2314  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2315      $main_entry,$isalias);
2316
2317  # First determine where the hash has to be added.
2318  $isalias=0;
2319  for ($i = 0; $i < @chips_detected; $i++) {
2320    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2321  }
2322  if ($i == @chips_detected) {
2323    push @chips_detected, { driver => $chipdriver,
2324                            detected => [],
2325                            misdetected => [] };
2326  }
2327  $new_detected_ref = $chips_detected[$i]->{detected};
2328  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2329
2330  # Now, we are looking for aliases. An alias can only be the same chiptype.
2331  # If an alias is found in the misdetected list, we add the new information
2332  # and terminate this function. If it is found in the detected list, we
2333  # still have to check whether another chip has claimed this ISA address.
2334  # So we remove the old entry from the detected list and put it in datahash.
2335
2336  # Misdetected alias detection:
2337  for ($i = 0; $i < @$new_misdetected_ref; $i++) {
2338    if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
2339        not exists $new_misdetected_ref->[$i]->{isa_addr} and
2340        defined $alias_detect and
2341        $new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2342      open FILE,"$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}" or
2343        print("Can't open $dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2344        next;
2345      binmode FILE;
2346      i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{i2c_addr} or
2347           print("Can't set I2C address for ",
2348                 "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2349           next;
2350      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2351                          $new_misdetected_ref->[$i]->{i2c_addr})) {
2352        $new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2353        $new_misdetected_ref->[$i]->{isa_extra} = $datahash->{isa_extra} 
2354               if exists $datahash->{isa_extra};
2355        close FILE;
2356        return $new_misdetected_ref->[$i]; 
2357      }
2358      close FILE;
2359    }
2360  }
2361
2362  # Detected alias detection:
2363  for ($i = 0; $i < @$new_detected_ref; $i++) {
2364    if (exists $new_detected_ref->[$i]->{i2c_addr} and
2365        not exists $new_detected_ref->[$i]->{isa_addr} and
2366        defined $alias_detect and
2367        $new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2368      open FILE,"$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}" or
2369        print("Can't open $dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2370        next;
2371      binmode FILE;
2372      i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{i2c_addr} or
2373           print("Can't set I2C address for ",
2374                 "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2375           next;
2376      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2377                          $new_detected_ref->[$i]->{i2c_addr})) {
2378        $new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2379        $new_detected_ref->[$i]->{isa_extra} = $datahash->{isa_extra} 
2380               if exists $datahash->{isa_extra};
2381        ($datahash) = splice (@$new_detected_ref, $i, 1);
2382        close FILE;
2383        $isalias=1;
2384        last;
2385      }
2386      close FILE;
2387    }
2388  }
2389
2390
2391  # Find out whether our new entry should go into the detected or the
2392  # misdetected list. We only compare main isa_addr here, of course.
2393  foreach $main_entry (@chips_detected) {
2394    $detected_ref = $main_entry->{detected};
2395    $misdetected_ref = $main_entry->{misdetected};
2396    for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
2397      if (exists $detected_ref->[$i]->{isa_addr} and
2398          $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
2399        if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
2400          push @$new_misdetected_ref, $datahash;
2401        } else {
2402          push @$misdetected_ref,$detected_ref->[$i];
2403          splice @$detected_ref, $i,1;
2404          push @$new_detected_ref, $datahash;
2405        }
2406        if ($isalias) {
2407          return $datahash;
2408        } else {
2409          return 0;
2410        }
2411      }
2412    }
2413  }
2414
2415  # Not found? OK, put it in the detected list
2416  push @$new_detected_ref, $datahash;
2417  if ($isalias) {
2418    return $datahash;
2419  } else {
2420    return 0;
2421  }
2422}
2423
2424# $_[0]: The number of the adapter to scan
2425# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
2426# $_[2]: The name of the algorithm, as appearing in /proc/bus/i2c
2427# $_[3]: The driver of the adapter
2428# @_[4..]: Addresses not to scan
2429sub scan_adapter
2430{
2431  my ( $adapter_nr,$adapter_name,$algorithm_name,$adapter_driver, 
2432       $not_to_scan) = @_;
2433  my ($chip, $addr, $conf,@chips,$new_hash,$other_addr);
2434
2435  # As we modify it, we need a copy
2436  my @not_to_scan = @$not_to_scan;
2437
2438  open FILE,"$dev_i2c$adapter_nr" or 
2439    (print "Can't open $dev_i2c$adapter_nr\n"), return;
2440  binmode FILE;
2441
2442  # Now scan each address in turn
2443  foreach $addr (0x03..0x77) {
2444    # As the not_to_scan list is sorted, we can check it fast
2445    if (@not_to_scan and $not_to_scan[0] == $addr) {
2446      shift @not_to_scan;
2447      next;
2448    }
2449
2450    i2c_set_slave_addr(\*FILE,$addr) or 
2451        printf("Client at address 0x%02x can not be probed - unload all client drivers first!\n",$addr), next;
2452
2453    next unless i2c_probe(\*FILE, $addr);
2454    printf "Client found at address 0x%02x\n",$addr;
2455
2456    foreach $chip (@chip_ids) {
2457      if (exists $$chip{i2c_addrs} and contains $addr, @{$$chip{i2c_addrs}}) {
2458        print "Probing for `$$chip{name}'... ";
2459        if (($conf,@chips) = &{$$chip{i2c_detect}} (\*FILE ,$addr)) {
2460          print "Success!\n",
2461                "    (confidence $conf, driver `$$chip{driver}')";
2462          if (@chips) {
2463            print ", other addresses:";
2464            @chips = sort @chips;
2465            foreach $other_addr (sort @chips) {
2466              printf(" 0x%02x",$other_addr);
2467            }
2468          }
2469          printf "\n";
2470          $new_hash = { conf => $conf,
2471                        i2c_addr => $addr,
2472                        chipname =>  $$chip{name},
2473                        i2c_adap => $adapter_name,
2474                        i2c_algo => $algorithm_name,
2475                        i2c_driver => $adapter_driver,
2476                        i2c_devnr => $adapter_nr,
2477                      };
2478          if (@chips) {
2479            my @chips_copy = @chips;
2480            $new_hash->{i2c_sub_addrs} = \@chips_copy;
2481          }
2482          $new_hash->{i2c_extra} = 0 
2483                 if exists $chip->{i2c_driver_addrs} and
2484                    not contains( $addr , @{$chip->{i2c_driver_addrs}});
2485          add_i2c_to_chips_detected $$chip{driver}, $new_hash;
2486        } else {
2487          print "Failed!\n";
2488        }
2489      }
2490    }
2491  }
2492}
2493
2494sub scan_isa_bus
2495{
2496  my ($chip,$addr,$conf);
2497  foreach $chip (@chip_ids) {
2498    next if not exists $$chip{isa_addrs} or not exists $$chip{isa_detect};
2499    print "Probing for `$$chip{name}'\n";
2500    foreach $addr (@{$$chip{isa_addrs}}) {
2501      if ($addr) {
2502        printf "  Trying address 0x%04x... ", $addr;
2503      } else {
2504        print "  Trying general detect... ";
2505      }
2506      $conf = &{$$chip{isa_detect}} ($addr);
2507      print("Failed!\n"), next if not defined $conf;
2508      print "Success!\n";
2509      printf "    (confidence %d, driver `%s')\n", $conf, $$chip{driver};
2510      my $new_hash = { conf => $conf,
2511                       isa_addr => $addr,
2512                       chipname =>  $$chip{name}
2513                     };
2514      $new_hash->{isa_extra} = 0 
2515             if exists $chip->{isa_driver_addrs} and
2516                not contains ($addr, @{$chip->{isa_driver_addrs}});
2517      $new_hash = add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver},
2518                                            $new_hash;
2519      if ($new_hash) {
2520        printf "    Alias of the chip on I2C bus `%s', address 0x%04x\n",
2521                        $new_hash->{i2c_adap},$new_hash->{i2c_addr};
2522      }
2523    }
2524  }
2525}
2526
2527sub exit_superio
2528{
2529  my ($addrreg, $datareg, $family, $success) = @_;
2530
2531  # If detection succeeded and an exit sequence exists, use it
2532  if ($success && defined ($$family{exit})) {
2533    foreach my $byte (@{$$family{exit}}) {
2534      outb($addrreg, $byte);
2535    }
2536    return;
2537  }
2538
2539  # Else return to "Wait For Key" state (PNP-ISA spec)
2540  outb($addrreg, 0x02);
2541  outb($datareg, 0x02);
2542}
2543
2544# The following are taken from the PNP ISA spec (so it's supposed
2545# to be common to all Super I/0 chips):
2546#  devidreg: The device ID register(s)
2547#  logdevreg: The logical device register
2548#  actreg: The activation register within the logical device
2549#  actmask: The activation bit in the activation register
2550#  basereg: The I/O base register within the logical device
2551sub scan_superio
2552{
2553  my ($addrreg, $datareg) = @_;
2554  my ($val, $addr);
2555
2556  my %superio = (
2557    devidreg => 0x20,
2558    logdevreg => 0x07,
2559    actreg => 0x30,
2560    actmask => 0x01,
2561    basereg => 0x60,
2562  );
2563 
2564  FAMILY:
2565  foreach my $family (@superio_ids) {
2566# write the password
2567    foreach $val (@{$$family{enter}}) {
2568      outb($addrreg, $val);
2569    }
2570    foreach my $chip (@{$$family{chips}}) {
2571      print "Probing for `$$chip{name}'\n";
2572# check the device ID
2573      outb($addrreg, $superio{devidreg});
2574      $val = inb($datareg);
2575      if ($val == 0x00 || $val == 0xff) {
2576        print "  Failed! (skipping family)\n";
2577        exit_superio($addrreg, $datareg, $family, 0);
2578        next FAMILY;
2579      }
2580      if ($$chip{devid}>0xff) {
2581        outb($addrreg, $superio{devidreg} + 1);
2582        $val = ($val << 8) | inb($datareg);
2583      }
2584      if ($val != $$chip{devid}) {
2585        printf "  Failed! (0x%02x)\n", $val;
2586        next;
2587      }
2588      print "  Success...";
2589# does it have hardware monitoring capabilities
2590      if($$chip{driver} eq "not-a-sensor") {
2591        print " (no hardware monitoring capabilities)\n";
2592        next;
2593      }
2594# switch to the sensor logical device
2595      outb($addrreg, $superio{logdevreg});
2596      outb($datareg, $$chip{logdev});
2597# check the activation register
2598      outb($addrreg, $superio{actreg});
2599      $val = inb($datareg);
2600      if(!($val & $superio{actmask})) {
2601        print " but not activated\n";
2602        next;
2603      }
2604# Get the IO base register
2605      outb($addrreg, $superio{basereg});
2606      $addr = inb($datareg);
2607      outb($addrreg, $superio{basereg} + 1);
2608      $addr = ($addr << 8) | inb($datareg);
2609      if($addr == 0) {
2610        print " but no address specified\n";
2611        next;
2612      }         
2613      printf " found at address 0x%04x\n", $addr;
2614      my $new_hash = { conf => 9,
2615                       isa_addr => $addr,
2616                       chipname =>  $$chip{name}
2617                     };
2618      add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver},
2619                                            $new_hash;
2620    }
2621    exit_superio($addrreg, $datareg, $family, 1);
2622  }
2623}
2624
2625
2626##################
2627# CHIP DETECTION #
2628##################
2629
2630# Each function returns a confidence value. The higher this value, the more
2631# sure we are about this chip. A Winbond W83781D, for example, will be
2632# detected as a LM78 too; but as the Winbond detection has a higher confidence
2633# factor, you should identify it as a Winbond.
2634
2635# Each function returns a list. The first element is the confidence value;
2636# Each element after it is an SMBus address. In this way, we can detect
2637# chips with several SMBus addresses. The SMBus address for which the
2638# function was called is never returned.
2639
2640# If there are devices which get confused if they are only read from, then
2641# this program will surely confuse them. But we guarantee never to write to
2642# any of these devices.
2643
2644
2645# $_[0]: A reference to the file descriptor to access this chip.
2646#        We may assume an i2c_set_slave_addr was already done.
2647# $_[1]: Address
2648# Returns: undef if not detected, (7) if detected.
2649# Registers used: 0x58
2650sub mtp008_detect
2651{
2652  my ($file,$addr) = @_;
2653  return if (i2c_smbus_read_byte_data($file,0x58)) != 0xac;
2654  return (8);
2655}
2656 
2657# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
2658# $_[1]: A reference to the file descriptor to access this chip.
2659#        We may assume an i2c_set_slave_addr was already done.
2660# $_[2]: Address
2661# Returns: undef if not detected, (6) if detected.
2662# Registers used:
2663#   0x40: Configuration
2664#   0x48: Full I2C Address
2665#   0x49: Device ID
2666# Note that this function is always called through a closure, so the
2667# arguments are shifted by one place.
2668sub lm78_detect
2669{
2670  my $reg;
2671  my ($chip,$file,$addr) = @_;
2672  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
2673  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
2674  $reg = i2c_smbus_read_byte_data($file,0x49);
2675  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
2676                    ($chip == 1 and $reg == 0x40) or
2677                    ($chip == 2 and ($reg & 0xfe) == 0xc0);
2678  return (6);
2679}
2680
2681# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
2682# $_[1]: Address
2683# Returns: undef if not detected, 7 if detected.
2684# Note: Only address 0x290 is scanned at this moment.
2685sub lm78_isa_detect
2686{
2687  my ($chip,$addr) = @_ ;
2688  my $val = inb ($addr + 1);
2689  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
2690            inb ($addr + 7) != $val;
2691
2692  $val = inb($addr + 5) & 0x7f;
2693  outb($addr + 5, ~$val & 0xff);
2694  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
2695    outb($addr+5,$val);
2696    return;
2697  }
2698  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
2699  return unless (&$readproc(0x40) & 0x80) == 0x00;
2700  my $reg = &$readproc(0x49);
2701  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
2702                ($chip == 1 and $reg == 0x40) or
2703                ($chip == 2 and ($reg & 0xfe) == 0xc0);
2704  return 7;
2705}
2706
2707
2708# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
2709# $_[1]: ISA address
2710# $_[2]: I2C file handle
2711# $_[3]: I2C address
2712sub lm78_alias_detect
2713{
2714  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
2715  my $i;
2716  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
2717  return 0 unless &$readproc(0x48) == $i2c_addr;
2718  for ($i = 0x2b; $i <= 0x3d; $i ++) {
2719    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
2720  }
2721  return 1;
2722}
2723
2724# $_[0]: A reference to the file descriptor to access this chip.
2725#        We may assume an i2c_set_slave_addr was already done.
2726# $_[1]: Address
2727# Returns: undef if not detected, 2 to 6 if detected;
2728#   6 means that the LM75 was found in its default power up state;
2729#   5 means that the LM75 was found in another known default state;
2730#   4 means that the LM75 was found in a probable state (temperatures
2731#       make sense);
2732#   3 means that the configuration register passes the test;
2733# Registers used:
2734#   0x00: Temperature
2735#   0x01: Configuration
2736#   0x02: Hysteresis
2737#   0x03: Overtemperature Shutdown
2738# The first detection step is only based on the fact that the LM75 has only
2739# four registers. Any other chip in the valid address range with only four
2740# registers will be detected too.
2741# Note that register $00 may change, so we can't use the modulo trick on it.
2742sub lm75_detect
2743{
2744  my $i;
2745  my ($file,$addr) = @_;
2746  my $cur = i2c_smbus_read_word_data($file,0x00);
2747  my $cur_varies = 0;
2748  my $conf = i2c_smbus_read_byte_data($file,0x01);
2749  my $hyst = i2c_smbus_read_word_data($file,0x02);
2750  my $os = i2c_smbus_read_word_data($file,0x03);
2751  for ($i = 0x00; $i <= 0x1f; $i += 1) {
2752    return if i2c_smbus_read_byte_data($file,($i * 0x08) + 0x01) != $conf;
2753    return if i2c_smbus_read_word_data($file,($i * 0x08) + 0x02) != $hyst;
2754    return if i2c_smbus_read_word_data($file,($i * 0x08) + 0x03) != $os;
2755        $cur_varies = 1
2756      if (! $cur_varies) and
2757        i2c_smbus_read_word_data($file,($i * 0x08)) != $cur;
2758  }
2759  # Default power up state (from specs)
2760  return 6
2761    if $conf == 0 and ($hyst&0x80ff) == 0x004b and ($os&0x80ff) == 0x0050;
2762  # Default state as seen on the Asus TX97-E
2763  return 5
2764    if $conf == 0 and ($hyst&0x80ff) == 0x002d and ($os&0x80ff) == 0x0034;
2765  # All registers hold the same value, obviously a misdetection
2766  return
2767    if (! $cur_varies) and $conf == ($cur&0xff) and $cur == $hyst
2768      and $cur == $os;
2769  # Unused bits in conf register
2770  return
2771    if ($conf&0xe0) != 0;
2772  # Most probable value ranges
2773  return 4
2774    if (($cur&0x00ff) <= 125 || ($cur&0x00ff) >= 201)
2775       and ($hyst&0x00ff) <= 125 and ($os&0x00ff) <= 125 and $hyst<$os;
2776  return 3;
2777}
2778
2779# $_[0]: Chip to detect (0 = LM92, 1 = LM76, 2 = MAX6633/MAX6634/MAX6635)
2780# $_[1]: A reference to the file descriptor to access this chip.
2781#        We may assume an i2c_set_slave_addr was already done.
2782# $_[2]: Address
2783# Returns: undef if not detected, 2 or 4 if detected;
2784# Registers used:
2785#   0x01: Configuration (National Semiconductor only)
2786#   0x02: Hysteresis
2787#   0x03: Critical Temp
2788#   0x04: Low Limit
2789#   0x05: High Limit
2790#   0x07: Manufacturer ID (LM92 only)
2791# One detection step is based on the fact that the LM92 and clones have a
2792# limited number of registers, which cycle modulo 16 address values.
2793# Note that register 0x00 may change, so we can't use the modulo trick on it.
2794sub lm92_detect
2795{
2796  my ($chip, $file, $addr) = @_;
2797
2798  my $cur = i2c_smbus_read_word_data($file, 0x00);
2799  my $conf = i2c_smbus_read_byte_data($file, 0x01);
2800  my $hyst = i2c_smbus_read_word_data($file, 0x02);
2801  my $crit = i2c_smbus_read_word_data($file, 0x03);
2802  my $low = i2c_smbus_read_word_data($file, 0x04);
2803  my $high = i2c_smbus_read_word_data($file, 0x05);
2804
2805  return if $chip == 0
2806        and i2c_smbus_read_word_data($file, 0x07) != 0x0180;
2807 
2808  return if ($chip == 0 || $chip == 1)
2809        and ($conf & 0xE0);
2810
2811  for (my $i = 0; $i < 8; $i++) {
2812    return if i2c_smbus_read_byte_data($file, $i*16+0x01) != $conf;
2813    return if i2c_smbus_read_word_data($file, $i*16+0x02) != $hyst;
2814    return if i2c_smbus_read_word_data($file, $i*16+0x03) != $crit;
2815    return if i2c_smbus_read_word_data($file, $i*16+0x04) != $low;
2816    return if i2c_smbus_read_word_data($file, $i*16+0x05) != $high;
2817  }
2818 
2819  foreach my $temp ($hyst, $crit, $low, $high) {
2820    return if $chip == 2 and ($temp & 0x7F00);
2821    return if $chip != 2 and ($temp & 0x0700);
2822  }
2823
2824  return 4 if $chip == 0;
2825  return 2;
2826}
2827 
2828# $_[0]: A reference to the file descriptor to access this chip.
2829#        We may assume an i2c_set_slave_addr was already done.
2830# $_[1]: Address
2831# Returns: undef if not detected, (3) if detected,
2832#   (5) or (7) if even more bits match.
2833# Registers used:
2834#   0xAA: Temperature
2835#   0xA1: High limit
2836#   0xA2: Low limit
2837#   0xAC: Configuration
2838# Detection is weak. We check if Bit 3 is set and Bit 2 is clear.
2839# The DS1621 will aways have a config like 0x????10??. A even better
2840# match would be 0x0??01000.
2841# Temperature checkings will hopefully prevent LM75 chips from being
2842# detected as a DS1621.
2843sub ds1621_detect
2844{
2845  my $i;
2846  my ($file,$addr) = @_;
2847  my $temp = i2c_smbus_read_word_data($file,0xAA);
2848  return if ($temp & 0x007F);
2849  $temp = i2c_smbus_read_word_data($file,0xA1);
2850  return if ($temp & 0x007F);
2851  $temp = i2c_smbus_read_word_data($file,0xA2);
2852  return if ($temp & 0x007F);
2853  my $conf = i2c_smbus_read_byte_data($file,0xAC);
2854  return (7) if ($conf & 0x9F) == 0x98;
2855  return (5) if ($conf & 0x0F) == 0x08;
2856  return (3) if ($conf & 0x0C) == 0x08;
2857  return ;
2858}
2859
2860# $_[0]: A reference to the file descriptor to access this chip.
2861#        We may assume an i2c_set_slave_addr was already done.
2862# $_[1]: Address
2863# Returns: undef if not detected, 1 to 3 if detected.
2864# Registers used:
2865#   0x00: Configuration register
2866#   0x02: Interrupt state register
2867#   0x2a-0x3d: Limits registers
2868# This one is easily misdetected since it doesn't provide identification
2869# registers. So we have to use some tricks:
2870#   - 6-bit addressing, so limits readings modulo 0x40 should be unchanged
2871#   - positive temperature limits
2872#   - limits order correctness
2873# Hopefully this should limit the rate of false positives, without increasing
2874# the rate of false negatives.
2875# Thanks to Lennard Klein for testing on a non-LM80 chip, which was
2876# previously misdetected, and isn't anymore. For reference, it scored
2877# a final confidence of 0, and changing from strict limit comparisons
2878# to loose comparisons did not change the score.
2879sub lm80_detect
2880{
2881  my ($i,$reg);
2882  my ($file,$addr) = @_;
2883
2884  return if (i2c_smbus_read_byte_data($file,0x00) & 0x80) != 0;
2885  return if (i2c_smbus_read_byte_data($file,0x02) & 0xc0) != 0;
2886
2887  for ($i = 0x2a; $i <= 0x3d; $i++) {
2888    $reg = i2c_smbus_read_byte_data($file,$i);
2889    return if i2c_smbus_read_byte_data($file,$i+0x40) != $reg;
2890    return if i2c_smbus_read_byte_data($file,$i+0x80) != $reg;
2891    return if i2c_smbus_read_byte_data($file,$i+0xc0) != $reg;
2892  }
2893 
2894  # Refine a bit by checking wether limits are in the correct order
2895  # (min<max for voltages, hyst<max for temperature). Since it is still
2896  # possible that the chip is an LM80 with limits not properly set,
2897  # a few "errors" are tolerated.
2898  my $confidence = 0;
2899  for ($i = 0x2a; $i <= 0x3a; $i++) {
2900    $confidence++
2901      if i2c_smbus_read_byte_data($file,$i) < i2c_smbus_read_byte_data($file,$i+1);
2902  }
2903  # hot temp<OS temp
2904  $confidence++
2905    if i2c_smbus_read_byte_data($file,0x38) < i2c_smbus_read_byte_data($file,0x3a);
2906
2907  # Negative temperature limits are unlikely.
2908  for ($i = 0x3a; $i <= 0x3d; $i++) {
2909    $confidence++ if (i2c_smbus_read_byte_data($file,$i) & 0x80) == 0;
2910  }
2911
2912  # $confidence is between 0 and 14
2913  $confidence = ($confidence >> 1) - 4;
2914  # $confidence is now between -4 and 3
2915
2916  return unless $confidence > 0;
2917
2918  return $confidence;
2919}
2920
2921# $_[0]: Chip to detect
2922#   (0 = LM83, 1 = LM82)
2923# $_[1]: A reference to the file descriptor to access this chip.
2924#        We may assume an i2c_set_slave_addr was already done.
2925# $_[2]: Address
2926# Returns: undef if not detected, 5 to 8 if detected.
2927# Registers used:
2928#   0x02: Status 1
2929#   0x03: Configuration
2930#   0x04: Company ID of LM84
2931#   0x35: Status 2
2932#   0xfe: Manufacturer ID
2933#   0xff: Chip ID / die revision
2934# We can use the LM84 Company ID register because the LM83 and the LM82 are
2935# compatible with the LM84.
2936# The LM83 chip ID is missing from the datasheet and was contributed by
2937# Magnus Forsstrom.
2938sub lm83_detect
2939{
2940  my ($chip, $file) = @_;
2941  return if i2c_smbus_read_byte_data($file,0xfe) != 0x01;
2942  return if $chip == 0 and i2c_smbus_read_byte_data($file,0xff) != 0x03;
2943  return if $chip == 1 and i2c_smbus_read_byte_data($file,0xff) != 0x01;
2944
2945  my $confidence = 4;
2946  $confidence++
2947    if (i2c_smbus_read_byte_data($file,0x02) & 0xa8) == 0x00;
2948  $confidence++
2949    if (i2c_smbus_read_byte_data($file,0x03) & 0x41) == 0x00;
2950  $confidence++
2951    if i2c_smbus_read_byte_data($file,0x04) == 0x00;
2952  $confidence++
2953    if $chip == 0
2954    && (i2c_smbus_read_byte_data($file,0x35) & 0x48) == 0x00;
2955
2956  return $confidence;
2957}
2958
2959# $_[0]: Chip to detect
2960#   (0 = LM90, 1=LM89, 2=LM86, 3=ADM1032, 4=MAX6657/MAX6658,
2961#    5 = ADT7461)
2962# $_[1]: A reference to the file descriptor to access this chip.
2963#        We may assume an i2c_set_slave_addr was already done.
2964# $_[2]: Address
2965# Returns: undef if not detected, 3, 5, 7 or 8 if detected.
2966#   The Maxim chips have a low confidence value (3)
2967#   because the die revision codes are not known.
2968# Registers used:
2969#   0x03: Configuration
2970#   0xfe: Manufacturer ID
2971#   0xff: Chip ID / die revision
2972sub lm90_detect
2973{
2974  my ($chip, $file, $addr) = @_;
2975  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
2976  my $cid = i2c_smbus_read_byte_data($file, 0xff);
2977  my $conf = i2c_smbus_read_byte_data($file, 0x03);
2978
2979  if ($chip == 0) {
2980    return if ($conf & 0x2a) != 0;
2981    return if $mid != 0x01;     # National Semiconductor
2982    return 8 if $cid == 0x21;   # LM90
2983    return 7 if $cid > 0x21 and $cid < 0x30;
2984  }
2985  if ($chip == 1) {
2986    return if ($conf & 0x2a) != 0;
2987    return if $mid != 0x01;     # National Semiconductor
2988    return 8 if $addr == 0x4c and $cid == 0x31; # LM89/LM99
2989    return 8 if $addr == 0x4d and $cid == 0x34; # LM89-1/LM99-1
2990    return 5 if $cid > 0x31 and $cid < 0x40;
2991  }
2992  if ($chip == 2) {
2993    return if ($conf & 0x2a) != 0;
2994    return if $mid != 0x01;     # National Semiconductor
2995    return 8 if $cid == 0x11;   # LM86
2996    return 7 if $cid > 0x11 and $cid < 0x20;
2997  }
2998  if ($chip == 3) {
2999    return if ($conf & 0x3f) != 0;
3000    return if $mid != 0x41;     # Analog Devices
3001    return 8 if ($cid & 0xf0) == 0x40; # ADM1032
3002  }
3003  if ($chip == 4) {
3004    return if ($conf & 0x1f) != 0;
3005    return if $mid != 0x4d;     # Maxim
3006    return 3;
3007  }
3008  if ($chip == 5) {
3009    return if ($conf & 0x1b) != 0;
3010    return if $mid != 0x41;     # Analog Devices
3011    return 8 if $cid == 0x61;   # ADT7461
3012  }
3013  return;
3014}
3015
3016# $_[0]: Chip to detect
3017#   (0 = ADM1029)
3018# $_[1]: A reference to the file descriptor to access this chip.
3019#        We may assume an i2c_set_slave_addr was already done.
3020# $_[2]: Address
3021# Returns: undef if not detected, 3 to 9 if detected.
3022# Registers used:
3023#   0x02, 0x03: Fan support
3024#   0x05: GPIO config
3025#   0x07, 0x08, 0x09: Fan config
3026#   0x0d: Manufacturer ID
3027#   0x0e: Chip ID / die revision
3028sub adm1029_detect
3029{
3030  my ($chip, $file, $addr) = @_;
3031  my $mid = i2c_smbus_read_byte_data($file, 0x0d);
3032  my $cid = i2c_smbus_read_byte_data($file, 0x0e);
3033  my $fansc = i2c_smbus_read_byte_data($file, 0x02);
3034  my $fanss = i2c_smbus_read_byte_data($file, 0x03);
3035  my $gpio = i2c_smbus_read_byte_data($file, 0x05);
3036  my $fanas = i2c_smbus_read_byte_data($file, 0x07);
3037  my $fanhps = i2c_smbus_read_byte_data($file, 0x08);
3038  my $fanfs = i2c_smbus_read_byte_data($file, 0x09);
3039  my $confidence = 3;
3040
3041  if ($chip == 0) {
3042    return if $mid != 0x41;     # Analog Devices
3043    $confidence++ if ($cid & 0xF0) == 0x00; # ADM1029
3044    $confidence+=2 if ($fansc & 0xFC) == 0x00
3045                   && ($fanss & 0xFC) == 0x00;
3046    $confidence+=2 if ($fanas & 0xFC) == 0x00
3047                   && ($fanhps & 0xFC) == 0x00
3048                   && ($fanfs & 0xFC) == 0x00;
3049    $confidence++ if ($gpio & 0x80) == 0x00;
3050    return $confidence;
3051  }
3052  return;
3053}
3054
3055# $_[0]: Chip to detect
3056#   (0 = ADM1030, 1=ADM1031)
3057# $_[1]: A reference to the file descriptor to access this chip.
3058#        We may assume an i2c_set_slave_addr was already done.
3059# $_[2]: Address
3060# Returns: undef if not detected, 3 to 7 (ADM1031) or 9 (ADM1030)
3061#          if detected.
3062# Registers used:
3063#   0x01: Config 2
3064#   0x03: Status 2
3065#   0x0d, 0x0e, 0x0f: Temperature offsets
3066#   0x22: Fan speed config
3067#   0x3d: Chip ID
3068#   0x3e: Manufacturer ID
3069#   0x3f: Die revision
3070sub adm1031_detect
3071{
3072  my ($chip, $file, $addr) = @_;
3073  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3074  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3075  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3076  my $conf2 = i2c_smbus_read_byte_data($file, 0x01);
3077  my $stat2 = i2c_smbus_read_byte_data($file, 0x03);
3078  my $fsc = i2c_smbus_read_byte_data($file, 0x22);
3079  my $lto = i2c_smbus_read_byte_data($file, 0x0d);
3080  my $r1to = i2c_smbus_read_byte_data($file, 0x0e);
3081  my $r2to = i2c_smbus_read_byte_data($file, 0x0f);
3082  my $confidence = 3;
3083
3084  if ($chip == 0) {
3085    return if $mid != 0x41;     # Analog Devices
3086    return if $cid != 0x30;     # ADM1030
3087    $confidence++ if ($drev & 0x70) == 0x00;
3088    $confidence++ if ($conf2 & 0x4A) == 0x00;
3089    $confidence++ if ($stat2 & 0x3F) == 0x00;
3090    $confidence++ if ($fsc & 0xF0) == 0x00;
3091    $confidence++ if ($lto & 0x70) == 0x00;
3092    $confidence++ if ($r1to & 0x70) == 0x00;
3093    return $confidence;
3094  }
3095  if ($chip == 1) {
3096    return if $mid != 0x41;     # Analog Devices
3097    return if $cid != 0x31;     # ADM1031
3098    $confidence++ if ($drev & 0x70) == 0x00;
3099    $confidence++ if ($lto & 0x70) == 0x00;
3100    $confidence++ if ($r1to & 0x70) == 0x00;
3101    $confidence++ if ($r2to & 0x70) == 0x00;
3102    return $confidence;
3103  }
3104  return;
3105}
3106
3107# $_[0]: Chip to detect
3108#   (0 = ADT7467)
3109# $_[1]: A reference to the file descriptor to access this chip.
3110#        We may assume an i2c_set_slave_addr was already done.
3111# $_[2]: Address
3112# Returns: undef if not detected, 5 if detected.
3113# Registers used:
3114#   0x3d: Chip ID
3115#   0x3e: Manufacturer ID
3116#   0x3f: Die revision
3117sub adt7467_detect
3118{
3119  my ($chip, $file, $addr) = @_;
3120  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3121  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3122  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3123
3124  if ($chip == 0) {
3125    return if $mid != 0x41;     # Analog Devices
3126    return if $cid != 0x68;     # ADT7467
3127    return if ($drev & 0xf0) != 0x70;
3128    return 5;
3129  }
3130  return
3131}
3132
3133# $_[0]: Vendor to check for
3134#   (0x01 = National Semi, 0x41 = Analog Dev, 0x5c = SMSC)
3135# $_[1]: A reference to the file descriptor to access this chip.
3136# #_[2]: Base address.
3137# Returns: undef if not detected, (7) or (8) if detected.
3138# Registers used: 0x3e == Vendor register.
3139#                 0x3d == Device ID register (Analog Devices only).
3140#                 0x3f == Version/Stepping register.
3141# Constants used: 0x01 == National Semiconductor Vendor Id.
3142#                 0x41 == Analog Devices Vendor Id.
3143#                 0x5c == SMSC Vendor Id.
3144#                 0x60 == Version number. The lower 4 stepping
3145#                         bits are masked and ignored.
3146sub lm85_detect
3147{
3148  my ($vendor,$file,$addr) = @_;
3149  return if (i2c_smbus_read_byte_data($file,0x3e)) != $vendor ;
3150  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) != 0x60;
3151
3152  if ($vendor == 0x41) # Analog Devices
3153  {
3154    return if i2c_smbus_read_byte_data($file, 0x3d) != 0x27;
3155    return (8);
3156  }
3157
3158  return (7);
3159}
3160
3161# $_[0]: A reference to the file descriptor to access this chip.
3162#        We may assume an i2c_set_slave_addr was already done.
3163# $_[1]: Address
3164# Returns: undef if not detected, (7) if detected.
3165# Registers used: 0x3E, 0x3F
3166#        Assume lower 2 bits of reg 0x3F are for revisions.
3167sub lm87_detect
3168{
3169  my ($file,$addr) = @_;
3170  return if (i2c_smbus_read_byte_data($file,0x3e)) != 0x02;
3171  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xfc) != 0x04;
3172  return (7);
3173}
3174 
3175# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S,
3176#                        3 = W83627HF, 4 = AS99127F (rev.1),
3177#                        5 = AS99127F (rev.2), 6 = ASB100, 7 = W83791D
3178# $_[1]: A reference to the file descriptor to access this chip.
3179#        We may assume an i2c_set_slave_addr was already done.
3180# $_[2]: Address
3181# Returns: undef if not detected, (8,addr1,addr2) if detected, but only
3182#          if the LM75 chip emulation is enabled.
3183# Registers used:
3184#   0x48: Full I2C Address
3185#   0x4a: I2C addresses of emulated LM75 chips
3186#   0x4e: Vendor ID byte selection, and bank selection
3187#   0x4f: Vendor ID
3188#   0x58: Device ID (only when in bank 0)
3189# Note: Fails if the W8378xD is not in bank 0!
3190# Note: Detection overrules a previous LM78 detection
3191# Note: Asus chips do not have their I2C address at register 0x48?
3192#       AS99127F rev.1 and ASB100 have 0x00, confirmation wanted for
3193#       AS99127F rev.2.
3194sub w83781d_detect
3195{
3196  my ($reg1,$reg2,@res);
3197  my ($chip,$file,$addr) = @_;
3198
3199  return unless (i2c_smbus_read_byte_data($file,0x48) == $addr)
3200    or ($chip >= 4 && $chip <= 6);
3201
3202  $reg1 = i2c_smbus_read_byte_data($file,0x4e);
3203  $reg2 = i2c_smbus_read_byte_data($file,0x4f);
3204  if ($chip == 4) { # Asus AS99127F (rev.1)
3205    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or 
3206                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x12);
3207  } elsif ($chip == 6) { # Asus ASB100
3208    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0x94) or 
3209                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x06);
3210  } else { # Winbond and Asus AS99127F (rev.2)
3211    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
3212                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
3213  }
3214
3215  return unless ($reg1 & 0x07) == 0x00;
3216
3217  $reg1 = i2c_smbus_read_byte_data($file,0x58);
3218  return if $chip == 0 and ($reg1 != 0x10 && $reg1 != 0x11);
3219  return if $chip == 1 and  $reg1 != 0x30;
3220  return if $chip == 2 and  $reg1 != 0x40;
3221  return if $chip == 3 and  $reg1 != 0x21;
3222  return if $chip == 4 and  $reg1 != 0x31;
3223  return if $chip == 5 and  $reg1 != 0x31;
3224  return if $chip == 6 and  $reg1 != 0x31;
3225  return if $chip == 7 and  $reg1 != 0x71;
3226  $reg1 = i2c_smbus_read_byte_data($file,0x4a);
3227  @res = (8);
3228  @res = (7) # Asus chips were always seen at 0x2d
3229    if ($chip >= 4 && $chip <= 6 && $addr != 0x2d);
3230  push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08;
3231  push @res, (($reg1 & 0x70) >> 4) + 0x48 unless ($reg1 & 0x80 or $chip == 2);
3232  return @res;
3233}
3234
3235# $_[0]: Chip to detect (0 = ASM58, 1 = AS2K129R, 2 = ???)
3236# $_[1]: A reference to the file descriptor to access this chip
3237# $_[2]: Address (unused)
3238# Returns: undef if not detected, 5 if detected
3239# Registers used:
3240#   0x4e: Vendor ID high byte
3241#   0x4f: Vendor ID low byte
3242#   0x58: Device ID
3243# Note: The values were given by Alex van Kaam, we don't have datasheets
3244#       to confirm.
3245sub mozart_detect
3246{
3247  my ($vid,$dev);
3248  my ($chip,$file,$addr) = @_;
3249
3250  $vid = (i2c_smbus_read_byte_data($file,0x4e) << 8)
3251       +  i2c_smbus_read_byte_data($file,0x4f);
3252  $dev = i2c_smbus_read_byte_data($file,0x58);
3253
3254  return if ($chip == 0) and ($dev != 0x56 || $vid != 0x9436);
3255  return if ($chip == 1) and ($dev != 0x56 || $vid != 0x9406);
3256  return if ($chip == 2) and ($dev != 0x10 || $vid != 0x5ca3);
3257
3258  return 5;
3259}
3260
3261# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S, 3 = W83627HF)
3262# $_[1]: ISA address
3263# $_[2]: I2C file handle
3264# $_[3]: I2C address
3265sub w83781d_alias_detect
3266{
3267  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
3268  my $i;
3269  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
3270  return 0 unless &$readproc(0x48) == $i2c_addr;
3271  for ($i = 0x2b; $i <= 0x3d; $i ++) {
3272    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
3273  }
3274  return 1;
3275}
3276
3277# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF, 5 = W83697HF)
3278#        (W83783S and AS99127F not on ISA bus)
3279# $_[1]: Address
3280# Returns: undef if not detected, (8) if detected.
3281sub w83781d_isa_detect
3282{
3283  my ($chip,$addr) = @_ ;
3284  my ($reg1,$reg2);
3285  my $val = inb ($addr + 1);
3286  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
3287            inb ($addr + 7) != $val;
3288
3289  $val = inb($addr + 5) & 0x7f;
3290  outb($addr+5, ~$val & 0xff);
3291  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
3292    outb($addr+5,$val);
3293    return;
3294  }
3295
3296  my $read_proc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
3297  $reg1 = &$read_proc(0x4e);
3298  $reg2 = &$read_proc(0x4f);
3299  return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
3300                (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
3301  return unless ($reg1 & 0x07) == 0x00;
3302  $reg1 = &$read_proc(0x58) & 0xfe;
3303  return if $chip == 0 and  $reg1 != 0x10;
3304  return if $chip == 1 and  $reg1 != 0x30;
3305  return if $chip == 3 and  $reg1 != 0x20;
3306  return if $chip == 5 and  $reg1 != 0x60;
3307  return 8;
3308}
3309
3310# $_[0]: Chip to detect (0 = Revision 0x00, 1 = Revision 0x80)
3311# $_[1]: A reference to the file descriptor to access this chip.
3312#        We may assume an i2c_set_slave_addr was already done.
3313# $_[2]: Address
3314# Returns: undef if not detected, (6) if detected.
3315# Registers used:
3316#   0x00: Device ID
3317#   0x01: Revision ID
3318#   0x03: Configuration
3319# Mediocre detection
3320sub gl518sm_detect
3321{
3322  my $reg;
3323  my ($chip,$file,$addr) = @_;
3324  return unless i2c_smbus_read_byte_data($file,0x00) == 0x80;
3325  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
3326  $reg = i2c_smbus_read_byte_data($file,0x01);
3327  return unless ($chip == 0 and $reg == 0x00) or
3328                ($chip == 1 and $reg == 0x80);
3329  return (6);
3330}
3331
3332# $_[0]: A reference to the file descriptor to access this chip.
3333#        We may assume an i2c_set_slave_addr was already done.
3334# $_[1]: Address
3335# Returns: undef if not detected, (5) if detected.
3336# Registers used:
3337#   0x00: Device ID
3338#   0x01: Revision ID
3339#   0x03: Configuration
3340# Mediocre detection
3341sub gl520sm_detect
3342{
3343  my ($file,$addr) = @_;
3344  return unless i2c_smbus_read_byte_data($file,0x00) == 0x20;
3345  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
3346  # The line below must be better checked before I dare to use it.
3347  # return unless i2c_smbus_read_byte_data($file,0x01) == 0x00;
3348  return (5);
3349}
3350
3351# $_[0]: A reference to the file descriptor to access this chip.
3352#        We may assume an i2c_set_slave_addr was already done.
3353# $_[1]: Address
3354# Returns: undef if not detected, (5) if detected.
3355# Registers used:
3356#   0x00: Device ID
3357# Mediocre detection
3358sub gl525sm_detect
3359{
3360  my ($file,$addr) = @_;
3361  return unless i2c_smbus_read_byte_data($file,0x00) == 0x25;
3362  return (5);
3363}
3364
3365# $_[0]: Chip to detect (0 = ADM9240, 1 = DS1780, 2 = LM81)
3366# $_[1]: A reference to the file descriptor to access this chip.
3367#        We may assume an i2c_set_slave_addr was already done.
3368# $_[2]: Address
3369# Returns: undef if not detected, (7) if detected.
3370# Registers used:
3371#   0x3e: Company ID
3372#   0x40: Configuration
3373#   0x48: Full I2C Address
3374# Note: Detection overrules a previous LM78 detection
3375sub adm9240_detect
3376{
3377  my $reg;
3378  my ($chip, $file,$addr) = @_;
3379  $reg = i2c_smbus_read_byte_data($file,0x3e);
3380  return unless ($chip == 0 and $reg == 0x23) or
3381                ($chip == 1 and $reg == 0xda) or
3382                ($chip == 2 and $reg == 0x01);
3383  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
3384  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
3385 
3386  return (7);
3387}
3388
3389# $_[0]: Chip to detect (0 = ADM1022, 1 = THMC50, 2 = ADM1028)
3390# $_[1]: A reference to the file descriptor to access this chip.
3391#        We may assume an i2c_set_slave_addr was already done.
3392# $_[2]: Address
3393# Returns: undef if not detected, (8) if detected.
3394# Registers used:
3395#   0x3e: Company ID
3396#   0x3f: Revision
3397#   0x40: Configuration
3398# Note: Detection overrules a previous LM78 or ADM9240 detection
3399sub adm1022_detect
3400{
3401  my $reg;
3402  my ($chip, $file,$addr) = @_;
3403  $reg = i2c_smbus_read_byte_data($file,0x3e);
3404  return unless ($chip == 0 and $reg == 0x41) or
3405                ($chip == 1 and $reg == 0x49) or
3406                ($chip == 2 and $reg == 0x41);
3407  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
3408  $reg = i2c_smbus_read_byte_data($file, 0x3f);
3409  return unless ($reg & 0xc0) == 0xc0;
3410  return if $chip == 0 and ($reg & 0xc0) != 0xc0;
3411  return if $chip == 2 and ($reg & 0xc0) == 0xc0;
3412  return (8);
3413}
3414
3415# $_[0]: Chip to detect (0 = ADM1025, 1 = NE1619)
3416# $_[1]: A reference to the file descriptor to access this chip.
3417#        We may assume an i2c_set_slave_addr was already done.
3418# $_[2]: Address
3419# Returns: undef if not detected, (8) if detected.
3420# Registers used:
3421#   0x3e: Company ID
3422#   0x3f: Revision
3423#   0x40: Configuration
3424# Note: Detection overrules a previous LM78 or ADM9240 detection
3425sub adm1025_detect
3426{
3427  my $reg;
3428  my ($chip, $file,$addr) = @_;
3429
3430  $reg = i2c_smbus_read_byte_data($file,0x3e);
3431  return if ($chip == 0) and ($reg != 0x41);
3432  return if ($chip == 1) and ($reg != 0xA1);
3433
3434  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
3435  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x20;
3436
3437  return (8);
3438}
3439
3440# $_[0]: Chip to detect (0 = ADM1026)
3441# $_[1]: A reference to the file descriptor to access this chip.
3442#        We may assume an i2c_set_slave_addr was already done.
3443# $_[2]: Address
3444# Returns: undef if not detected, (8) if detected.
3445# Registers used:
3446#   0x16: Company ID
3447#   0x17: Revision
3448sub adm1026_detect
3449{
3450  my $reg;
3451  my ($chip, $file,$addr) = @_;
3452  $reg = i2c_smbus_read_byte_data($file,0x16);
3453  return unless ($reg == 0x41);
3454  return unless (i2c_smbus_read_byte_data($file,0x17) & 0xf0) == 0x40;
3455  return (8);
3456}
3457
3458# $_[0]: Chip to detect (0 = ADM1024)
3459# $_[1]: A reference to the file descriptor to access this chip.
3460#        We may assume an i2c_set_slave_addr was already done.
3461# $_[2]: Address
3462# Returns: undef if not detected, (8) if detected.
3463# Registers used:
3464#   0x3e: Company ID
3465#   0x3f: Revision
3466#   0x40: Configuration
3467sub adm1024_detect
3468{
3469  my $reg;
3470  my ($chip, $file,$addr) = @_;
3471  $reg = i2c_smbus_read_byte_data($file,0x3e);
3472  return unless ($reg == 0x41);
3473  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
3474  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x10;
3475  return (8);
3476}
3477
3478# $_[0]: Chip to detect
3479#   (0 = ADM1021, 1 = ADM1021A/ADM1023, 2 = MAX1617, 3 = MAX1617A, 4 = THMC10,
3480#    5 = LM84, 6 = GL523, 7 = MC1066)
3481# $_[1]: A reference to the file descriptor to access this chip.
3482#        We may assume an i2c_set_slave_addr was already done.
3483# $_[2]: Address
3484# Returns: undef if not detected, 3 if simply detected, 5 if detected and
3485#          manufacturer ID matches, 7 if detected and manufacturer ID and
3486#          revision match
3487# Registers used:
3488#   0x04: Company ID (LM84 only)
3489#   0xfe: Company ID (all but LM84 and MAX1617)
3490#   0xff: Revision (ADM1021, ADM1021A/ADM1023 and MAX1617A)
3491#   0x02: Status
3492#   0x03: Configuration
3493#   0x04: Conversion rate
3494#   0x00-0x01, 0x05-0x08: Temperatures (MAX1617 and LM84)
3495# Note: Especially the MAX1617 has very bad detection; we give it a low
3496# confidence value.
3497sub adm1021_detect
3498{
3499  my ($chip, $file, $addr) = @_;
3500  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
3501  my $rev = i2c_smbus_read_byte_data($file, 0xff);
3502  my $conf = i2c_smbus_read_byte_data($file, 0x03);
3503  my $status = i2c_smbus_read_byte_data($file, 0x02);
3504  my $convrate = i2c_smbus_read_byte_data($file, 0x04);
3505
3506  # Check manufacturer IDs and product revisions when available
3507  return if $chip == 0 and $man_id != 0x41 ||
3508                          ($rev & 0xf0) != 0x00;
3509  return if $chip == 1 and $man_id != 0x41 ||
3510                          ($rev & 0xf0) != 0x30;
3511  return if $chip == 3 and $man_id != 0x4d ||
3512                           $rev != 0x01;
3513  return if $chip == 4 and $man_id != 0x49;
3514  return if $chip == 5 and $convrate != 0x00;
3515  return if $chip == 6 and $man_id != 0x23;
3516  return if $chip == 7 and $man_id != 0x54;
3517
3518  # Check unused bits
3519  if ($chip == 5) # LM84
3520  {
3521    return if ($status & 0xab) != 0;
3522    return if ($conf & 0x7f) != 0;
3523  }
3524  else
3525  {
3526    return if ($status & 0x03) != 0;
3527    return if ($conf & 0x3f) != 0;
3528    return if ($convrate & 0xf8) != 0;
3529  }
3530
3531  # Extra checks for MAX1617 and LM84, since those are often misdetected
3532  # We verify several assertions (6 for the MAX1617, 4 for the LM84) and
3533  # discard the chip if any fail. Note that these checks are not done
3534  # by the adm1021 driver.
3535  if ($chip == 2 || $chip == 5)
3536  {
3537    my $lte = i2c_smbus_read_byte_data($file, 0x00);
3538    my $rte = i2c_smbus_read_byte_data($file, 0x01);
3539    my $lhi = i2c_smbus_read_byte_data($file, 0x05);
3540    my $rhi = i2c_smbus_read_byte_data($file, 0x07);
3541    my $llo = i2c_smbus_read_byte_data($file, 0x06);
3542    my $rlo = i2c_smbus_read_byte_data($file, 0x08);
3543
3544    # If all registers hold the same value, it has to be a misdetection
3545    return if $lte == $rte and $lte == $lhi and $lte == $rhi
3546           and $lte == $llo and $lte == $rlo;
3547
3548    # Negative temperatures
3549    return if ($lte & 0x80) or ($rte & 0x80);
3550    # Negative high limits
3551    return if ($lhi & 0x80) or ($rhi & 0x80);
3552    # Low limits over high limits
3553    if ($chip != 5) # LM84 doesn't have low limits
3554    {
3555      $llo-=256 if ($llo & 0x80);
3556      $rlo-=256 if ($rlo & 0x80);
3557      return if ($llo > $lhi) or ($rlo > $rhi);
3558    }
3559  }
3560
3561  return 3 if ($chip == 2) or ($chip == 5);
3562  return 7 if $chip <= 3;
3563  return 5;
3564}
3565
3566# $_[0]: Address
3567# Returns: undef if not detected, (9) if detected.
3568# Note: It is already 99% certain this chip exists if we find the PCI
3569# entry. The exact address is encoded in PCI space.
3570sub sis5595_isa_detect
3571{
3572  my ($addr) = @_;
3573  my ($key,$adapter,$try,$local_try);
3574  my $found = 0;
3575  foreach $local_try (@pci_adapters) {
3576    if ($local_try->{procid} eq "Silicon Integrated Systems SIS5595") {
3577      $try = $local_try;
3578      $found = 1;
3579      last;
3580    }
3581  }
3582  return if not $found;
3583
3584  $found = 0;
3585  while ( ($key, $adapter) = each %pci_list) {
3586    if ((defined($adapter->{vendid}) and 
3587         $try->{vendid} == $adapter->{vendid} and
3588         $try->{devid} == $adapter->{devid} and
3589         $try->{func} == $adapter->{func}) or
3590        (! defined($adapter->{vendid}) and
3591         $adapter->{desc} =~ /$try->{procid}/ and
3592         $try->{func} == $adapter->{func})) {
3593      $found = 1;
3594      last;
3595    }
3596  }
3597  return if not $found;
3598
3599  return 9;
3600}
3601
3602# $_[0]: Address
3603# Returns: undef if not detected, (9) if detected.
3604# Note: It is already 99% certain this chip exists if we find the PCI
3605# entry. The exact address is encoded in PCI space.
3606sub via686a_isa_detect
3607{
3608  my ($addr) = @_;
3609  my ($key,$adapter,$try,$local_try);
3610  my $found = 0;
3611  foreach $local_try (@pci_adapters) {
3612    if ($local_try->{procid} eq "VIA Technologies VT82C686 Apollo ACPI") {
3613      $try = $local_try;
3614      $found = 1;
3615      last;
3616    }
3617  }
3618  return if not $found;
3619
3620  $found = 0;
3621  while ( ($key, $adapter) = each %pci_list) {
3622    if ((defined($adapter->{vendid}) and 
3623         $try->{vendid} == $adapter->{vendid} and
3624         $try->{devid} == $adapter->{devid} and
3625         $try->{func} == $adapter->{func}) or
3626        (! defined($adapter->{vendid}) and
3627         $adapter->{desc} =~ /$try->{procid}/ and
3628         $try->{func} == $adapter->{func})) {
3629      $found = 1;
3630      last;
3631    }
3632  }
3633  return if not $found;
3634
3635  return 9;
3636}
3637
3638# $_[0]: Address
3639# Returns: undef if not detected, (9) if detected.
3640# Note: It is already 99% certain this chip exists if we find the PCI
3641# entry. The exact address is encoded in PCI space.
3642sub via8231_isa_detect
3643{
3644  my ($addr) = @_;
3645  my ($key,$adapter,$try,$local_try);
3646  my $found = 0;
3647  foreach $local_try (@pci_adapters) {
3648    if ($local_try->{procid} eq "VIA Technologies VT8231 South Bridge") {
3649      $try = $local_try;
3650      $found = 1;
3651      last;
3652    }
3653  }
3654  return if not $found;
3655
3656  $found = 0;
3657  while ( ($key, $adapter) = each %pci_list) {
3658    if ((defined($adapter->{vendid}) and 
3659         $try->{vendid} == $adapter->{vendid} and
3660         $try->{devid} == $adapter->{devid} and
3661         $try->{func} == $adapter->{func}) or
3662        (! defined($adapter->{vendid}) and
3663         $adapter->{desc} =~ /$try->{procid}/ and
3664         $try->{func} == $adapter->{func})) {
3665      $found = 1;
3666      last;
3667    }
3668  }
3669  return if not $found;
3670
3671  return 9;
3672}
3673
3674# $_[0]: Chip to detect (0 = ..., 1 = ...)
3675# $_[1]: A reference to the file descriptor to access this chip.
3676#        We may assume an i2c_set_slave_addr was already done.
3677# $_[2]: Address
3678# Returns: undef if not detected, 8 if detected (tops LM78).
3679# Registers used:
3680#   0x00: Configuration
3681#   0x48: Full I2C Address
3682#   0x58: Mfr ID
3683# Note that this function is always called through a closure, so the
3684# arguments are shifted by one place.
3685sub ite_detect
3686{
3687  my $reg;
3688  my ($chip,$file,$addr) = @_;
3689  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
3690  return unless (i2c_smbus_read_byte_data($file,0x00) & 0x80) == 0x00;
3691  return unless i2c_smbus_read_byte_data($file,0x58) == 0x90;
3692  return (8);
3693}
3694
3695# $_[0]: Chip to detect (0 = ..., 1 = ...)
3696# $_[1]: Address
3697# Returns: undef if not detected, 8 if detected (tops LM78).
3698# Note: Only address 0x290 is scanned at this moment.
3699sub ite_isa_detect
3700{
3701  my ($chip,$addr) = @_ ;
3702  my $val = inb ($addr + 1);
3703  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
3704            inb ($addr + 7) != $val;
3705
3706  $val = inb($addr + 5) & 0x7f;
3707  outb($addr+5, ~$val & 0xff);
3708  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
3709    outb($addr+5,$val);
3710    return;
3711  }
3712  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
3713  return unless (&$readproc(0x00) & 0x80) == 0x00;
3714  my $reg = &$readproc(0x58);
3715  return unless ($reg == 0x90);
3716  return 8;
3717}
3718
3719
3720# $_[0]: Chip to detect (0 = ..., 1 = ...)
3721# $_[1]: ISA address
3722# $_[2]: I2C file handle
3723# $_[3]: I2C address
3724sub ite_alias_detect
3725{
3726  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
3727  my $i;
3728  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
3729  return 0 unless &$readproc(0x48) == $i2c_addr;
3730  for ($i = 0x2b; $i <= 0x3d; $i ++) {
3731    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
3732  }
3733  return 1;
3734}
3735
3736# $_[0]: Chip to detect (0 = SPD EEPROM, 1 = Sony Vaio EEPROM,
3737#                        2 = SPD EEPROM with Software Write Protect)
3738# $_[1]: A reference to the file descriptor to access this chip
3739# $_[2]: Address
3740# Returns: 8 for a memory eeprom (9 if write-protect register found),
3741#          4 to 9 for a Sony Vaio eeprom,
3742#          1 for an unknown eeprom (2 if write-protect register found)
3743# Registers used:
3744#   0-63: SPD Data and Checksum
3745#   0x80-0x83: Sony Vaio Data ("PCG-")
3746#   0xe2, 0xe5, 0xe8, 0xeb, Oxee: Sony Vaio Timestamp constant bytes.
3747#   0x1a-0x1c: Sony Vaio MAC address
3748# This detection function is a bit tricky; this is to workaround
3749# wrong misdetection messages that would else arise.
3750sub eeprom_detect
3751{
3752  my ($chip,$file,$addr) = @_;
3753  my $checksum = 0;
3754
3755  # Check the checksum for validity (works for most DIMMs and RIMMs)
3756  if ($chip != 1) {
3757          for (my $i = 0; $i <= 62; $i ++) {
3758            $checksum += i2c_smbus_read_byte_data($file,$i);
3759          }
3760          $checksum &= 255;
3761          $checksum -= i2c_smbus_read_byte_data($file,63);
3762  }     
3763  if ($chip == 0) {
3764        if($checksum == 0) {
3765                return 8;
3766        } else {
3767                return 1;
3768        }
3769  }     
3770  if ($chip == 2) {
3771        # check for 'shadow' write-protect register at 0x30-0x37
3772        # could be dangerous
3773        i2c_set_slave_addr($file,$addr - 0x20);
3774        if(i2c_smbus_write_quick($file,$SMBUS_WRITE) >= 0 &&
3775           i2c_smbus_read_byte_data($file,0x80) == -1) {
3776                i2c_set_slave_addr($file,$addr);
3777                if($checksum == 0) {
3778                        return (9, $addr - 0x20);
3779                } else {
3780                        return (2, $addr - 0x20);
3781                }
3782        }
3783        i2c_set_slave_addr($file,$addr);
3784        return;
3785  }
3786
3787  # Look for a Sony Vaio EEPROM ($chip == 1)
3788  my $vaioconf = 1;
3789  $vaioconf += 4
3790    if i2c_smbus_read_byte_data($file,0x80) == 0x50
3791    && i2c_smbus_read_byte_data($file,0x81) == 0x43
3792    && i2c_smbus_read_byte_data($file,0x82) == 0x47
3793    && i2c_smbus_read_byte_data($file,0x83) == 0x2d;
3794  $vaioconf += 5
3795    if i2c_smbus_read_byte_data($file,0xe2) == 0x2f
3796    && i2c_smbus_read_byte_data($file,0xe5) == 0x2f
3797    && i2c_smbus_read_byte_data($file,0xe8) == 0x20
3798    && i2c_smbus_read_byte_data($file,0xeb) == 0x3a
3799    && i2c_smbus_read_byte_data($file,0xee) == 0x3a;
3800  $vaioconf += 3
3801    if i2c_smbus_read_byte_data($file,0x1a) == 0x08
3802    && i2c_smbus_read_byte_data($file,0x1b) == 0x00
3803    && i2c_smbus_read_byte_data($file,0x1c) == 0x46;
3804  $vaioconf = 9
3805    if $vaioconf > 9;
3806
3807  if ($vaioconf > 1) {
3808    return $vaioconf;
3809  }
3810  return;
3811}
3812
3813# $_[0]: A reference to the file descriptor to access this chip.
3814#        We may assume an i2c_set_slave_addr was already done.
3815# $_[1]: Address
3816# Returns: undef if not detected, (1) if detected.
3817# Registers used:
3818#   0x00..0x07: DDC signature
3819#   0x08..0x7E: checksumed area
3820#   0x7F:       checksum
3821### commented out additional location checks for now - don't work?
3822sub ddcmonitor_detect
3823{
3824  my ($file,$addr) = @_;
3825  my $i;
3826###  for ($i = 0; $i < 8; $i ++) {
3827###    i2c_set_slave_addr \*FILE,$addr+$i or goto FAILURE;
3828    i2c_smbus_read_byte_data($file,0x00) == 0x00 or goto FAILURE;
3829    i2c_smbus_read_byte_data($file,0x01) == 0xFF or goto FAILURE;
3830    i2c_smbus_read_byte_data($file,0x02) == 0xFF or goto FAILURE;
3831    i2c_smbus_read_byte_data($file,0x03) == 0xFF or goto FAILURE;
3832    i2c_smbus_read_byte_data($file,0x04) == 0xFF or goto FAILURE;
3833    i2c_smbus_read_byte_data($file,0x05) == 0xFF or goto FAILURE;
3834    i2c_smbus_read_byte_data($file,0x06) == 0xFF or goto FAILURE;
3835    i2c_smbus_read_byte_data($file,0x07) == 0x00 or goto FAILURE;
3836###  }
3837###  i2c_set_slave_addr \*FILE,$addr or return;
3838  # Check the checksum for validity. We should do this for all addresses,
3839  # but it would be too slow.
3840  my $checksum = 0;
3841  for ($i = 0; $i <= 127; $i = $i + 1) {
3842    $checksum = $checksum + i2c_smbus_read_byte_data($file,$i);
3843  }
3844  $checksum=$checksum & 255;
3845  if ($checksum != 0) {
3846    # I have one such monitor...
3847    return (2,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
3848  }
3849  return (8,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
3850FAILURE:
3851  i2c_set_slave_addr \*FILE,$addr;
3852  return;
3853}
3854
3855# $_[0]: A reference to the file descriptor to access this chip.
3856#        We may assume an i2c_set_slave_addr was already done.
3857# $_[1]: Address
3858# Returns: undef if not detected, (8) if detected.
3859# Registers used:
3860#   0x00-0x02: Identification ('P','E','G' -> Pegasus ? :-)
3861sub fscpos_detect
3862{
3863  my ($file,$addr) = @_;
3864  # check the first 3 registers
3865  if (i2c_smbus_read_byte_data($file,0x00) != 0x50) {
3866        return;
3867  }
3868  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
3869        return;
3870  }
3871  if (i2c_smbus_read_byte_data($file,0x02) != 0x47) {
3872        return;
3873  }
3874  return (8);
3875}
3876
3877# $_[0]: A reference to the file descriptor to access this chip.
3878#        We may assume an i2c_set_slave_addr was already done.
3879# $_[1]: Address
3880# Returns: undef if not detected, (8) if detected.
3881# Registers used:
3882#   0x00-0x02: Identification ('S','C','Y')
3883sub fscscy_detect
3884{
3885  my ($file,$addr) = @_;
3886  # check the first 3 registers
3887  if (i2c_smbus_read_byte_data($file,0x00) != 0x53) {
3888        return;
3889  }
3890  if (i2c_smbus_read_byte_data($file,0x01) != 0x43) {
3891        return;
3892  }
3893  if (i2c_smbus_read_byte_data($file,0x02) != 0x59) {
3894        return;
3895  }
3896  return (8);
3897}
3898
3899# $_[0]: A reference to the file descriptor to access this chip.
3900#        We may assume an i2c_set_slave_addr was already done.
3901# $_[1]: Address
3902# Returns: undef if not detected, (8) if detected.
3903# Registers used:
3904#   0x00-0x02: Identification ('H','E','R')
3905sub fscher_detect
3906{
3907  my ($file,$addr) = @_;
3908  # check the first 3 registers
3909  if (i2c_smbus_read_byte_data($file,0x00) != 0x48) {
3910        return;
3911  }
3912  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
3913        return;
3914  }
3915  if (i2c_smbus_read_byte_data($file,0x02) != 0x52) {
3916        return;
3917  }
3918  return (8);
3919}
3920
3921# $_[0]: A reference to the file descriptor to access this chip.
3922#        We may assume an i2c_set_slave_addr was already done.
3923# $_[1]: Address
3924# Returns: undef if not detected, (7) if detected.
3925# Registers used:
3926#   0x3F: Revision ID
3927#   0x48: Address
3928#   0x4A, 0x4B, 0x4F, 0x57, 0x58: Reserved bits.
3929# We do not use 0x49's reserved bits on purpose. The register is named
3930# "VID4/Device ID" so it is doubtful bits 7-1 are really unused.
3931sub m5879_detect
3932{
3933  my ($file, $addr) = @_;
3934
3935  return
3936    unless i2c_smbus_read_byte_data($file, 0x3F) == 0x01;
3937 
3938  return
3939    unless i2c_smbus_read_byte_data($file, 0x48) == $addr;
3940 
3941  return
3942    unless (i2c_smbus_read_byte_data($file, 0x4A) & 0x06) == 0
3943       and (i2c_smbus_read_byte_data($file, 0x4B) & 0xFC) == 0
3944       and (i2c_smbus_read_byte_data($file, 0x4F) & 0xFC) == 0
3945       and (i2c_smbus_read_byte_data($file, 0x57) & 0xFE) == 0
3946       and (i2c_smbus_read_byte_data($file, 0x58) & 0xEF) == 0;
3947
3948  return (7);
3949}
3950
3951# $_[0]: A reference to the file descriptor to access this chip.
3952#        We may assume an i2c_set_slave_addr was already done.
3953# $_[1]: Address
3954# Returns: undef if not detected, 4 or 7 if detected
3955# Detection is based on the fact that the SAA1064 has only one readable
3956# register, and thus ignores the read address. This register can have value
3957# 0x80 (first read since power-up) or 0x00.
3958sub saa1064_detect
3959{
3960        my ($file,$addr) = @_;
3961        my $status = i2c_smbus_read_byte_data ($file, 0x00);
3962
3963        return if ($status & 0x7f) != 0x00;
3964
3965        for (my $i=0 ; $i<256; $i++) {
3966                return if i2c_smbus_read_byte_data ($file, $i) != 0x00;
3967        }
3968
3969        return 7
3970                if $status == 0x80;
3971        return 4;
3972}
3973
3974# $_[0]: A reference to the file descriptor to access this chip.
3975#        We may assume an i2c_set_slave_addr was already done.
3976# $_[1]: Address
3977# Returns: undef if not detected, 1 if detected
3978# Detection is rather difficult, since the PCA9540 has a single register.
3979# Fortunately, no other device is known to live at this address.
3980sub pca9540_detect
3981{
3982        my ($file, $addr) = @_;
3983        my $reg = i2c_smbus_read_byte($file);
3984
3985        return if ($reg & 0xf7);
3986        return if $reg != i2c_smbus_read_byte($file);
3987        return if $reg != i2c_smbus_read_byte($file);
3988        return if $reg != i2c_smbus_read_byte($file);
3989
3990        return 1;
3991}
3992
3993# $_[0]: A reference to the file descriptor to access this chip.
3994#        We may assume an i2c_set_slave_addr was already done.
3995# $_[1]: Address
3996# Returns: undef if not detected, 3 if detected
3997sub max6900_detect
3998{
3999        my ($file,$addr) = @_;
4000        my $reg;
4001       
4002        # SEC
4003        $reg = i2c_smbus_read_byte_data ($file, 0x81);
4004        return if
4005                ($reg & 0xF0) > 0x50 or
4006                ($reg & 0x0F) > 9;
4007
4008        # MIN
4009        $reg = i2c_smbus_read_byte_data ($file, 0x83);
4010        return if
4011                ($reg & 0xF0) > 0x50 or
4012                ($reg & 0x0F) > 9;
4013
4014        # HR
4015        $reg = i2c_smbus_read_byte_data ($file, 0x85);
4016        return if
4017                ($reg & 0x40) != 0x00 or
4018                ($reg & 0x0F) > 9;
4019
4020        # DATE
4021        $reg = i2c_smbus_read_byte_data ($file, 0x87);
4022        return if
4023                $reg == 0x00 or
4024                ($reg & 0xF0) > 0x30 or
4025                ($reg & 0x0F) > 9;
4026
4027        # MONTH
4028        $reg = i2c_smbus_read_byte_data ($file, 0x89);
4029        return if
4030                $reg == 0x00 or
4031                ($reg & 0xF0) > 0x10 or
4032                ($reg & 0x0F) > 9;
4033
4034        # DAY
4035        $reg = i2c_smbus_read_byte_data ($file, 0x8B);
4036        return if
4037                $reg == 0 or
4038                $reg > 7;
4039
4040        # YEAR
4041        $reg = i2c_smbus_read_byte_data ($file, 0x8D);
4042        return if
4043                ($reg & 0xF0) > 0x90 or
4044                ($reg & 0x0F) > 9;
4045
4046        # CONTROL
4047        $reg = i2c_smbus_read_byte_data ($file, 0x8F);
4048        return if
4049                ($reg & 0x7F) != 0x00;
4050
4051        # CENTURY
4052        $reg = i2c_smbus_read_byte_data ($file, 0x93);
4053        return if
4054                ($reg & 0xF0) > 0x90 or
4055                ($reg & 0x0F) > 9;
4056
4057        return 3;
4058}
4059
4060# $_[0]: A reference to the file descriptor to access this chip.
4061#        We may assume an i2c_set_slave_addr was already done.
4062# $_[1]: Address
4063# Returns: 1
4064# This is a placeholder so we get a report if any device responds
4065# to the SMBus Device Default Address (0x61), which is used for
4066# ARP in SMBus 2.0.
4067sub arp_detect
4068{
4069  return (1);
4070}
4071
4072# This checks for non-FFFF values for SpecInfo and Status.
4073# The address (0x09) is specified by the SMBus standard so it's likely
4074# that this really is a smart battery charger.
4075# $_[0]: A reference to the file descriptor to access this chip.
4076#        We may assume an i2c_set_slave_addr was already done.
4077# $_[1]: Address
4078# Returns: 5
4079sub smartbatt_chgr_detect
4080{
4081  my ($file,$addr) = @_;
4082  # check some registers
4083  if (i2c_smbus_read_word_data($file,0x11) == 0xffff) {
4084        return;
4085  }
4086  if (i2c_smbus_read_word_data($file,0x13) == 0xffff) {
4087        return;
4088  }
4089  return (5);
4090}
4091
4092# This checks for non-FFFF values for State and Info.
4093# The address (0x0a) is specified by the SMBus standard so it's likely
4094# that this really is a smart battery manager/selector.
4095# $_[0]: A reference to the file descriptor to access this chip.
4096#        We may assume an i2c_set_slave_addr was already done.
4097# $_[1]: Address
4098# Returns: 5
4099sub smartbatt_mgr_detect
4100{
4101  my ($file,$addr) = @_;
4102  # check some registers
4103  if (i2c_smbus_read_word_data($file,0x01) == 0xffff) {
4104        return;
4105  }
4106  if (i2c_smbus_read_word_data($file,0x04) == 0xffff) {
4107        return;
4108  }
4109  return (5);
4110}
4111
4112# This checks for non-FFFF values for temperature, voltage, and current.
4113# The address (0x0b) is specified by the SMBus standard so it's likely
4114# that this really is a smart battery.
4115# $_[0]: A reference to the file descriptor to access this chip.
4116#        We may assume an i2c_set_slave_addr was already done.
4117# $_[1]: Address
4118# Returns: 5
4119sub smartbatt_detect
4120{
4121  my ($file,$addr) = @_;
4122  # check some registers
4123  if (i2c_smbus_read_word_data($file,0x08) == 0xffff) {
4124        return;
4125  }
4126  if (i2c_smbus_read_word_data($file,0x09) == 0xffff) {
4127        return;
4128  }
4129  if (i2c_smbus_read_word_data($file,0x0a) == 0xffff) {
4130        return;
4131  }
4132  return (5);
4133}
4134
4135# Returns: 4
4136# These are simple detectors that only look for a register at the
4137# standard location. No writes are performed.
4138# For KCS, use the STATUS register. For SMIC, use the FLAGS register.
4139sub ipmi_kcs_detect
4140{
4141  return if inb (0x0ca3) == 0xff;
4142  return (4);
4143}
4144
4145sub ipmi_smic_detect
4146{
4147  return if inb (0x0cab) == 0xff;
4148  return (4);
4149}
4150
4151# $_[0]: Chip to detect (0 = W83L784R/AR, 1 = W83L785R)
4152# $_[1]: A reference to the file descriptor to access this chip.
4153# $_[2]: Address
4154# Returns: undef if not detected, 6 or 8 if detected
4155# Registers used:
4156#   0x40: Configuration
4157#   0x4a: Full I2C Address (not W83L785R)
4158#   0x4b: I2C addresses of emulated LM75 chips (not W83L785R)
4159#   0x4c: Winbond Vendor ID (Low Byte)
4160#   0x4d: Winbond Vendor ID (High Byte)
4161#   0x4e: Chip ID
4162# Note that this function is always called through a closure, so the
4163# arguments are shifted by one place.
4164sub w83l784r_detect
4165{
4166  my ($reg,@res);
4167  my ($chip,$file,$addr) = @_;
4168
4169  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4170  return if $chip == 0
4171    and i2c_smbus_read_byte_data($file,0x4a) != $addr;
4172  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
4173  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
4174  return if $chip == 0
4175    and i2c_smbus_read_byte_data($file,0x4e) != 0x50;
4176  return if $chip == 1
4177    and i2c_smbus_read_byte_data($file,0x4e) != 0x60;
4178
4179  $reg = i2c_smbus_read_byte_data($file,0x4b);
4180
4181  return 6 if $chip == 1; # W83L785R doesn't have subclients
4182 
4183  @res = (8);
4184  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08 ;
4185  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
4186  return @res;
4187}
4188
4189# $_[0]: Chip to detect (0 = W83L785TS-S)
4190# $_[1]: A reference to the file descriptor to access this chip.
4191#        We may assume an i2c_set_slave_addr was already done.
4192# $_[2]: Address
4193# Returns: undef if not detected, 8 if detected
4194# Registers used:
4195#   0x4C-4E: Mfr and Chip ID
4196# Note that this function is always called through a closure, so the
4197# arguments are shifted by one place.
4198sub w83l785ts_detect
4199{
4200  my ($chip,$file,$addr) = @_;
4201  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
4202  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
4203  return unless i2c_smbus_read_byte_data($file,0x4e) == 0x70;
4204  return (8);
4205}
4206
4207# $_[0]: Chip to detect. Always zero for now, but available for future use
4208#        if somebody finds a way to distinguish MAX6650 and MAX6651.
4209# $_[1]: A reference to the file descriptor to access this chip.
4210#        We may assume an i2c_set_slave_addr was already done.
4211# $_[2]: Address
4212# Returns: undef if not detected, 4 if detected.
4213#
4214# The max6650 has no device ID register. However, a few registers have
4215# spare bits, which are documented as being always zero on read. We read
4216# all of these registers check the spare bits. Any non-zero means this
4217# is not a max6650/1.
4218#
4219# The always zero bits are:
4220#   configuration byte register (0x02) - top 2 bits
4221#   gpio status register (0x14) - top 3 bits
4222#   alarm enable register (0x08) - top 3 bits
4223#   alarm status register (0x0A) - top 3 bits
4224#   tachometer count time register (0x16) - top 6 bits
4225sub max6650_detect
4226{
4227  my ($chip, $file) = @_;
4228  return if i2c_smbus_read_byte_data($file,0x16) & 0xFC;
4229  return if i2c_smbus_read_byte_data($file,0x0A) & 0xE0;
4230  return if i2c_smbus_read_byte_data($file,0x08) & 0xE0;
4231  return if i2c_smbus_read_byte_data($file,0x14) & 0xE0;
4232  return if i2c_smbus_read_byte_data($file,0x02) & 0xC0;
4233  return 4;
4234}
4235
4236
4237################
4238# MAIN PROGRAM #
4239################
4240
4241# $_[0]: reference to a list of chip hashes
4242sub print_chips_report 
4243{
4244  my ($listref) = @_;
4245  my $data;
4246 
4247  foreach $data (@$listref) {
4248    my $is_i2c = exists $data->{i2c_addr};
4249    my $is_isa = exists $data->{isa_addr};
4250    print "  * ";
4251    if ($is_i2c) {
4252      printf "Bus `%s' (%s)\n", $data->{i2c_adap}, $data->{i2c_algo};
4253      printf "    Busdriver `%s', I2C address 0x%02x", 
4254             $data->{i2c_driver}, $data->{i2c_addr};
4255      if (exists $data->{i2c_sub_addrs}) {
4256        print " (and";
4257        my $sub_addr;
4258        foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
4259          printf " 0x%02x",$sub_addr;
4260        }
4261        print ")"
4262      }
4263      print "\n";
4264    }
4265    if ($is_isa) {
4266      print "    " if  $is_i2c;
4267      if ($data->{isa_addr}) {
4268        printf "ISA bus address 0x%04x (Busdriver `i2c-isa')\n", 
4269               $data->{isa_addr};
4270      } else {
4271        printf "ISA bus, undetermined address (Busdriver `i2c-isa')\n"
4272      }
4273    }
4274    printf "    Chip `%s' (confidence: %d)\n",
4275           $data->{chipname},  $data->{conf};
4276  }
4277}
4278
4279# $_[0]: 1 if ISA bus is prefered, 0 for SMBus
4280# We build here an array adapters, indexed on the number the adapter has
4281# at this moment (we assume only loaded adapters are interesting at all;
4282# everything that got scanned also got loaded). Each entry is a reference
4283# to a hash containing:
4284#  driver: Name of the adapter driver
4285#  nr_now: Number of the bus now
4286#  nr_later: Number of the bus when the modprobes are done (not included if the
4287#        driver should not be loaded)
4288# A second array, called
4289sub generate_modprobes
4290{
4291  my ($prefer_isa) = @_;
4292
4293  my ($chip,$detection,$nr,$i,@optionlist,@probelist,$driver,$isa,$adap);
4294  my @adapters;
4295  my $modprobes = "";
4296  my $configfile = "";
4297
4298  # These are always needed
4299  $configfile .= "# I2C module options\n";
4300  $configfile .= "alias char-major-89 i2c-dev\n";
4301
4302  # Collect all loaded adapters
4303  # i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
4304  open INPUTFILE,"i2cdetect -l |" or die "Couldn't find i2cdetect program!!";
4305  while (<INPUTFILE>) {
4306    my ($dev_nr,$type,$adap,$algo) = /^i2c-(\S+)\s+(\S+)\s+(.*?)\s*\t\s*(.*?)\s+$/;
4307    next if ($type eq "dummy");
4308    $adapters[$dev_nr]->{driver} = find_adapter_driver($adap,$algo);
4309    $adapters[$dev_nr]->{adapname} = $adap;
4310    $adapters[$dev_nr]->{algoname} = $algo;
4311  }
4312  close INPUTFILE;
4313
4314  # Collect all adapters used
4315  $nr = 0;
4316  $isa = 0;
4317  $modprobes .= "# I2C adapter drivers\n";
4318  foreach $chip (@chips_detected) {
4319    foreach $detection (@{$chip->{detected}}) {
4320      # If there is more than one bus detected by a driver, they are
4321      # still all added. So we number them in the correct order
4322      if (exists $detection->{i2c_driver} and
4323          not exists $adapters[$detection->{i2c_devnr}]->{nr_later} and 
4324          not (exists $detection->{isa_addr} and $prefer_isa)) {
4325         foreach $adap (@adapters) {
4326           $adap->{nr_later} = $nr++ if $adap->{driver} eq $detection->{i2c_driver};
4327         }
4328      }
4329      if (exists $detection->{isa_addr} and
4330          not (exists $detection->{i2c_driver} and not $prefer_isa)) {
4331           $isa=1;
4332      }
4333    }
4334  }
4335
4336  for ($i = 0; $i < $nr; $i++) {
4337    foreach $adap (@adapters) {
4338      if ($adap->{driver} eq "UNKNOWN") {
4339        $modprobes .= "# modprobe unknown adapter ".$adap->{adapname}." using ". $adap->{algoname}."\n";
4340      } elsif ($adap->{driver} eq "DISABLED") {
4341        $modprobes .= "# modprobe disabled adapter ".$adap->{adapname}." using ". $adap->{algoname}."\n";
4342      } elsif ($adap->{driver} eq "to-be-written") {
4343        $modprobes .= "# no driver available for adapter ".$adap->{adapname}." using ". $adap->{algoname}."\n";
4344      } else {
4345        $modprobes .= "modprobe $adap->{driver}\n" if (defined($adap->{nr_later}) and $adap->{nr_later} == $i) and not $modprobes =~ /modprobe $adap->{driver}\n/;
4346      }
4347    }
4348  }
4349  $modprobes .= "modprobe i2c-isa\n" if ($isa);
4350
4351  # Now determine the chip probe lines
4352  $modprobes .= "# I2C chip drivers\n";
4353  foreach $chip (@chips_detected) {
4354    next if not @{$chip->{detected}};
4355    if ($chip->{driver} eq "to-be-written") {
4356      $modprobes .= "# no driver for $chip->{detected}[0]{chipname} yet, ask us for one!\n";
4357    } else {
4358      $modprobes .= "modprobe $chip->{driver}\n";
4359    }
4360    @optionlist = ();
4361    @probelist = ();
4362
4363    # Handle detects at addresses normally not probed
4364    foreach $detection (@{$chip->{detected}}) {
4365      push @probelist, $adapters[$detection->{i2c_devnr}]->{nr_later},
4366                       $detection->{i2c_addr}
4367           if exists $detection->{i2c_addr} and
4368              exists $detection->{i2c_extra};
4369      push @probelist, -1, $detection->{isa_addr}
4370           if exists $detection->{isa_addr} and
4371              exists $detection->{isa_extra};
4372    }
4373
4374    # Handle misdetects
4375    foreach $detection (@{$chip->{misdetected}}) {
4376      push @optionlist, $adapters[$detection->{i2c_devnr}]->{nr_later},
4377                       $detection->{i2c_addr}
4378           if exists $detection->{i2c_addr} and
4379              exists $adapters[$detection->{i2c_devnr}]->{nr_later};
4380      push @optionlist, -1, $detection->{isa_addr}
4381           if exists $detection->{isa_addr} and $isa;
4382    }
4383
4384    # Handle aliases
4385    foreach $detection (@{$chip->{detected}}) {
4386      if (exists $detection->{i2c_driver} and 
4387          exists $detection->{isa_addr} and
4388          exists $adapters[$detection->{i2c_devnr}]->{nr_later} and
4389          $isa) {
4390        if ($prefer_isa) {
4391          push @optionlist,$adapters[$detection->{i2c_devnr}]->{nr_later},
4392                           $detection->{i2c_addr};
4393        } else {
4394          push @optionlist, -1, $detection->{isa_addr}
4395        }
4396      }
4397    }
4398
4399    next if not (@probelist or @optionlist);
4400    $configfile .= "options $chip->{driver}";
4401    $configfile .= sprintf " ignore=%d,0x%02x",shift @optionlist, 
4402                                               shift @optionlist
4403                  if @optionlist;
4404    $configfile .= sprintf ",%d,0x%02x",shift @optionlist, shift @optionlist
4405                  while @optionlist;
4406    $configfile .= sprintf " probe=%d,0x%02x",shift @probelist,
4407                                              shift @probelist
4408                  if @probelist;
4409    $configfile .= sprintf ",%d,0x%02x",shift @probelist, shift @probelist
4410                  while @probelist;
4411    $configfile .= "\n";
4412  }
4413
4414  return ($modprobes,$configfile);
4415 
4416}
4417
4418# returns:
4419# 0, could not determine (can't read /dev/mem...)
4420# 1, safe system (VPD record not found)
4421# bios string (e.g. "INET32WW"), unsafe system
4422# VPD is documented here:
4423# http://www.pc.ibm.com/qtechinfo/MIGR-45120.html
4424sub vpd_bios_build_id
4425{
4426  my $pos = 0xF0000;
4427  my $found = 0;
4428  my $bbid;
4429
4430  return 0
4431    unless open MEM, '/dev/mem';
4432  binmode MEM;
4433  unless (seek MEM, $pos, SEEK_SET)
4434  {
4435    close MEM;
4436    return 0;
4437  }
4438  while ($pos <= 0xFFFD0 && !$found)
4439  {
4440    my $r = read(MEM, my $buf, 48);
4441    unless ($r == 48)
4442    {
4443      close MEM;
4444      return 0;
4445    }
4446    seek (MEM, -32, SEEK_CUR);
4447    my $len;
4448    if (substr($buf, 0, 5) eq "\xAA\x55VPD"
4449     && ord(substr($buf, 5, 1)) >= 0x30)
4450    {
4451      if (unpack('%8C*', substr($buf, 0x0D, 0x30-0x0D)) != 0)
4452      {
4453        printf " Bad VPD checksum (0x%02X)! Please report.\n",
4454                ord(substr($buf, 0x2F, 1));
4455      }
4456      $bbid = substr($buf, 13, 9);
4457      $bbid =~ s/[\x00 ]*$//; # right trim
4458      $found++;
4459    }
4460    $pos += 16;
4461  }
4462  close MEM;
4463
4464  return 1 unless $found;
4465  print " System vendor: IBM\n";
4466  print " BIOS version: $bbid\n";
4467  return "$bbid";
4468}
4469
4470# returns:
4471# 1 : the system is known to be safe
4472# 0 : the system safeness is unknown
4473# If the system is know to be unsafe (i.e. for now, IBM systems), never
4474#   return.
4475sub safe_system_vendor
4476{
4477  if ($> != 0)
4478  {
4479        print " As you are not root, we can't determine your system vendor.\n";
4480        return 0;
4481  }
4482
4483  my $vpd_bbid = vpd_bios_build_id();
4484
4485  return 0 if $vpd_bbid eq '0';
4486  return 1 if $vpd_bbid eq '1';
4487 
4488  print "Sorry, we won't let you go on. IBM systems are known to have\n".
4489        "serious problems with lm_sensors, resulting in hardware failures.\n".
4490        "For more information, see README.thinkpad or\n".
4491        "http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/README.thinkpad.\n\n".
4492        "We will be progressively updating our user-space tools so as to prevent\n".
4493        "the problem from occuring. Some kernel drivers will need updates too.\n".
4494        "This lock will be removed once everything is fixed and believed to be\n".
4495        "safe.\n\n";
4496
4497  exit;
4498}
4499
4500sub main
4501{
4502  my (@adapters,$res,$did_adapter_detection,$adapter);
4503
4504  initialize_conf;
4505  initialize_proc_pci;
4506  initialize_modules_list;
4507  initialize_kernel_version;
4508
4509  print "\nThis program will help you determine which I2C/SMBus modules you need to\n",
4510        "load to use lm_sensors most effectively. You need to have i2c and\n",
4511        "lm_sensors installed before running this program.\n";
4512  print "Also, you need to be `root', or at least have access to the $dev_i2c*\n",
4513        "files, for most things.\n";
4514  print "If you have patched your kernel and have some drivers built in, you can\n",
4515        "safely answer NO if asked to load some modules. In this case, things may\n",
4516        "seem a bit confusing, but they will still work.\n\n";
4517  print "It is generally safe and recommended to accept the default answers to all\n",
4518        "questions, unless you know what you're doing.\n\n";
4519
4520  unless (safe_system_vendor ())
4521  {
4522    print " IF THIS IS AN IBM THINKPAD, PRESS CTRL-C NOW!\n";
4523    print " IBM Thinkpads have a severely broken i2c/SMBus implementation, ";
4524    print "just scanning\n";
4525    print " the bus will break your Thinkpad forever!\n";
4526    print " If this is a non-Thinkpad IBM, we still suggest you press CTRL+C. We have\n";
4527    print " had users reporting system breakage on other IBM systems as well.\n\n";
4528  }
4529
4530  print " We can start with probing for (PCI) I2C or SMBus adapters.\n";
4531  print " You do not need any special privileges for this.\n";
4532  print " Do you want to probe now? (YES/no): ";
4533  @adapters = adapter_pci_detection
4534                        if ($did_adapter_detection = not <STDIN> =~ /\s*[Nn]/);
4535
4536  print "\n";
4537
4538  if (not $did_adapter_detection) {
4539    print "As you skipped adapter detection, we will only scan already loaded\n".
4540          "adapter modules.\n";
4541  } elsif ($> != 0) {
4542    print "As you are not root, we can't load adapter modules. We will only scan\n".
4543          "already loaded adapters.\n";
4544  } else {
4545    print "We will now try to load each adapter module in turn.\n";
4546    foreach $adapter (@adapters) {
4547      next if $adapter eq "DISABLED";
4548      if (exists($modules_list{$adapter})) {
4549        print "Module `$adapter' already loaded.\n";
4550      } else {
4551        print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
4552        unless (<STDIN> =~ /^\s*[Nn]/) {
4553          if (system ("modprobe", $adapter)) {
4554            print "Loading failed... skipping.\n";
4555            if ($adapter eq "rivatv") {
4556              print "** Note: rivatv module is available at http://rivatv.sourceforge.net/\n"; 
4557            }
4558          } else {
4559            print "Module loaded succesfully.\n";
4560          }
4561        }
4562      }
4563    }
4564  }
4565
4566  print "If you have undetectable or unsupported adapters, you can have them\n".
4567        "scanned by manually loading the modules before running this script.\n\n";
4568
4569  print " To continue, we need module `i2c-dev' to be loaded.\n";
4570  print " If it is built-in into your kernel, you can safely skip this.\n";
4571  if (exists($modules_list{"i2c-dev"})) {
4572    print "i2c-dev is already loaded.\n";
4573  } else {
4574    if ($> != 0) {
4575      print " i2c-dev is not loaded. As you are not root, we will just hope ",
4576            "you edited\n",
4577            " `$modules_conf' for automatic loading of\n",
4578            " this module. If not, you won't be able to open any $dev_i2c* file.\n";
4579    } else {
4580      print " i2c-dev is not loaded. Do you want to load it now? (YES/no): ";
4581      if (<STDIN> =~ /^\s*[Nn]/) {
4582        print " Well, you will know best. We will just hope you edited ",
4583              "`$modules_conf'\n",
4584              " for automatic loading of this module. If not,\n",
4585              " you won't be able to open any $dev_i2c* file (unless you",
4586              "have it built-in\n",
4587              " into your kernel)\n";
4588      } elsif (system "modprobe","i2c-dev") {
4589        print " Loading failed, expect problems later on.\n";
4590      } else {
4591        print " Module loaded succesfully.\n";
4592      }
4593    }
4594  }
4595
4596  print "\n We are now going to do the adapter probings. Some adapters may ",
4597        "hang halfway\n",
4598        " through; we can't really help that. Also, some chips will be double ",
4599        "detected;\n",
4600        " we choose the one with the highest confidence value in that case.\n",
4601        " If you found that the adapter hung after probing a certain address, ",
4602        "you can\n",
4603        " specify that address to remain unprobed. That ",
4604        "often\n",
4605        " includes address 0x69 (clock chip).\n";
4606
4607  my ($inp,@not_to_scan,$inp2);
4608  # i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
4609  open INPUTFILE,"i2cdetect -l |" or die "Couldn't find i2cdetect program!!";
4610  while (<INPUTFILE>) {
4611    my ($dev_nr,$type,$adap,$algo) = /^i2c-(\S+)\s+(\S+)\s+(.*?)\s*\t\s*(.*?)\s+$/;
4612    next if ($type eq "dummy");
4613    print "\n";
4614    print "Next adapter: $adap ($algo)\n";
4615    print "Do you want to scan it? (YES/no/selectively): ";
4616   
4617    $inp = <STDIN>;
4618    @not_to_scan=();
4619    if ($inp =~ /^\s*[Ss]/) {
4620      print "Please enter one or more addresses not to scan. Separate them ",
4621            "with comma's.\n",
4622            "You can specify a range by using dashes. Addresses may be ",
4623            "decimal (like 54)\n",
4624            "or hexadecimal (like 0x33).\n",
4625            "Addresses: ";
4626      $inp2 = <STDIN>;
4627      chop $inp2;
4628      @not_to_scan = parse_not_to_scan 0,0x7f,$inp2;
4629    }
4630    scan_adapter $dev_nr, $adap, $algo, find_adapter_driver($adap,$algo),
4631                 \@not_to_scan   unless $inp =~ /^\s*[Nn]/;
4632  }
4633
4634  print "\nSome chips are also accessible through the ISA bus. ISA probes are\n".
4635        "typically a bit more dangerous, as we have to write to I/O ports to do\n".
4636        "this. This is usually safe though.\n\n";
4637  if ($> != 0) {
4638    print "As you are not root, we shall skip this step.\n";
4639  } else {
4640    print "Do you want to scan the ISA bus? (YES/no): ";
4641    unless (<STDIN> =~ /^\s*n/i) {
4642      initialize_ioports();
4643      scan_isa_bus();
4644      close_ioports();
4645    }
4646  }
4647
4648  print "\nSome Super I/O chips may also contain sensors. Super I/O probes are\n".
4649        "typically a bit more dangerous, as we have to write to I/O ports to do\n".
4650        "this. This is usually safe though.\n\n";
4651  if ($> != 0) {
4652    print "As you are not root, we shall skip this step.\n";
4653  } else {
4654    print "Do you want to scan for Super I/O sensors? (YES/no): ";
4655    unless (<STDIN> =~ /^\s*n/i) {
4656      initialize_ioports();
4657      scan_superio(0x2e, 0x2f);
4658      print "\nDo you want to scan for secondary Super I/O sensors? (YES/no): ";
4659      unless (<STDIN> =~ /^\s*n/i) {
4660        scan_superio(0x4e, 0x4f);
4661      }
4662      close_ioports();
4663    }
4664  }
4665
4666  if(! @chips_detected) {
4667    print "\n Sorry, no chips were detected.\n",
4668        " Either your sensors are not supported, or they are\n",
4669        " connected to an I2C bus adapter that we do not support.\n",
4670        " See doc/FAQ, doc/lm_sensors-FAQ.html, or\n",
4671        " http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/doc/lm_sensors-FAQ.html\n",
4672        " (FAQ #4.24.3) for further information.\n",
4673        " If you find out what chips are on your board, see\n",
4674        " http://secure.netroedge.com/~lm78/newdrivers.html for driver status.\n";
4675    exit;
4676  }
4677
4678  print "\n Now follows a summary of the probes I have just done.\n";
4679  print " Just press ENTER to continue: ";
4680  <STDIN>;
4681
4682  my ($chip,$data);
4683  foreach $chip (@chips_detected) {
4684    print "\nDriver `$$chip{driver}' ";
4685    if (@{$$chip{detected}}) {
4686      if (@{$$chip{misdetected}}) {
4687        print "(should be inserted but causes problems):\n";
4688      } else {
4689        print "(should be inserted):\n";
4690      }
4691    } else {
4692      if (@{$$chip{misdetected}}) {
4693        print "(may not be inserted):\n";
4694      } else {
4695        print "(should not be inserted, but is harmless):\n";
4696      }
4697    }
4698    if (@{$$chip{detected}}) {
4699      print "  Detects correctly:\n";
4700      print_chips_report $chip->{detected};
4701    }
4702    if (@{$$chip{misdetected}}) {
4703      print "  Misdetects:\n";
4704      print_chips_report $chip->{misdetected};
4705    }
4706  }
4707
4708  print "\n\n",
4709        " I will now generate the commands needed to load the I2C modules.\n",
4710        " Sometimes, a chip is available both through the ISA bus and an ",
4711        "I2C bus.\n",
4712        " ISA bus access is faster, but you need to load an additional driver ",
4713        "module\n",
4714        " for it. If you have the choice, do you want to use the ISA bus or ",
4715        "the\n",
4716        " I2C/SMBus (ISA/smbus)? ";
4717  my $use_isa = not <STDIN> =~ /\s*[Ss]/;
4718     
4719  my ($modprobes,$configfile) = generate_modprobes $use_isa;
4720  print "\nTo make the sensors modules behave correctly, add these lines to\n",
4721        "$modules_conf:\n\n";
4722  print "#----cut here----\n";
4723  print $configfile;
4724  print "#----cut here----\n";
4725  print "\nTo load everything that is needed, add this to some /etc/rc* ",
4726        "file:\n\n";
4727  print "#----cut here----\n";
4728  print $modprobes;
4729  print "# sleep 2 # optional\n",
4730        "/usr/local/bin/sensors -s # recommended\n";
4731  print "#----cut here----\n";
4732  print "\nWARNING! If you have some things built into your kernel, the list above\n",
4733        "will contain too many modules. Skip the appropriate ones! You really should\n",
4734        "try these commands right now to make sure everything is working properly.\n",
4735        "Monitoring programs won't work until it's done.\n";
4736 
4737  my $have_sysconfig = -d '/etc/sysconfig';
4738  print "\nDo you want to generate /etc/sysconfig/lm_sensors? (".
4739    ($have_sysconfig?"YES/no":"yes/NO")."): ";
4740  if ($> != 0) {
4741    print "\nAs you are not root, we shall skip this step.\n";
4742  } else {
4743    $_ = <STDIN>;
4744    if (($have_sysconfig and not m/^\s*[Nn]/) or m/^\s*[Yy]/) {
4745      unless ($have_sysconfig) {
4746        mkdir '/etc/sysconfig', 0777
4747          or die "Sorry, can't create /etc/sysconfig ($!)?!?";
4748      }
4749      open(SYSCONFIG, ">/etc/sysconfig/lm_sensors")
4750        or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)?!?";
4751      print SYSCONFIG <<'EOT';
4752#    /etc/sysconfig/sensors - Defines modules loaded by /etc/rc.d/init.d/lm_sensors
4753#    Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>
4754#
4755#    This program is free software; you can redistribute it and/or modify
4756#    it under the terms of the GNU General Public License as published by
4757#    the Free Software Foundation; either version 2 of the License, or
4758#    (at your option) any later version.
4759#
4760#    This program is distributed in the hope that it will be useful,
4761#    but WITHOUT ANY WARRANTY; without even the implied warranty of
4762#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4763#    GNU General Public License for more details.
4764#
4765#    You should have received a copy of the GNU General Public License
4766#    along with this program; if not, write to the Free Software
4767#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4768#
4769#
4770# See also the lm_sensors homepage at:
4771#     http://www2.lm-sensors.nu/~lm78/index.html
4772#
4773# This file is used by /etc/rc.d/init.d/lm_sensors and defines the modules to
4774# be loaded/unloaded. This file is sourced into /etc/rc.d/init.d/lm_sensors.
4775#
4776# The format of this file is a shell script that simply defines the modules
4777# in order as normal variables with the special names:
4778#    MODULE_0, MODULE_1, MODULE_2, etc.
4779#
4780# List the modules that are to be loaded for your system
4781#
4782EOT
4783      print SYSCONFIG
4784       "# Generated by sensors-detect on " . scalar localtime() . "\n";
4785      my @modules = grep /^modprobe /, split "\n", $modprobes;
4786      my $i = 0;
4787      my $sysconfig = "";
4788      foreach (@modules) {
4789        s/^modprobe //;
4790        $sysconfig .= "MODULE_$i=$_\n";
4791        $i++;
4792      }
4793      print SYSCONFIG $sysconfig;
4794      close(SYSCONFIG);
4795      print "Copy prog/init/lm_sensors.init to /etc/rc.d/init.d/lm_sensors\n";
4796      print "for initialization at boot time.\n";
4797    }
4798  }
4799}
4800
4801main;
Note: See TracBrowser for help on using the browser.