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

Revision 2596, 148.8 KB (checked in by khali, 9 years ago)

Fix PCA9540 detection.

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