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

Revision 4170, 165.8 KB (checked in by ruik, 7 years ago)

Fix the links to status/supported pages.

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