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

Revision 2779, 152.0 KB (checked in by khali, 9 years ago)

Detect the nForce2 Ultra 400 and the nForce3 Pro150 SMBus devices.

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