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

Revision 2372, 139.0 KB (checked in by khali, 9 years ago)

Drop support of undetectable adapters.

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