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

Revision 4055, 166.5 KB (checked in by khali, 7 years ago)

sensors-detect: Add nForce4 MCP04, MCP51 and MCP55 detection

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