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

Revision 2558, 147.6 KB (checked in by mds, 9 years ago)

add support for ICH6 and 6300ESB (backport of 2.6 patch)

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