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

Revision 4210, 167.9 KB (checked in by khali, 7 years ago)

Move Super-I/O registers comment where it belongs.

  • 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 => "SMSC DME1737",
1335       driver => "to-be-written",
1336       i2c_addrs => [0x2c..0x2e],
1337       i2c_detect => sub { dme1737_detect(@_); },
1338     },
1339     {
1340       name => "Fintek F75111R/RG/N (GPIO)",
1341       driver => "to-be-written",
1342       i2c_addrs => [0x4e], # 0x37 not probed
1343       i2c_detect => sub { fintek_detect(1, @_); },
1344     },
1345     {
1346       name => "Fintek F75121R/F75122R/RG (VID+GPIO)",
1347       driver => "to-be-written",
1348       i2c_addrs => [0x4e], # 0x37 not probed
1349       i2c_detect => sub { fintek_detect(2, @_); },
1350     },
1351     {
1352       name => "Fintek F75373S/SG",
1353       driver => "to-be-written",
1354       i2c_addrs => [0x2d..0x2e],
1355       i2c_detect => sub { fintek_detect(3, @_); },
1356     },
1357     {
1358       name => "Fintek F75375S/SP",
1359       driver => "to-be-written",
1360       i2c_addrs => [0x2d..0x2e],
1361       i2c_detect => sub { fintek_detect(4, @_); },
1362     },
1363     {
1364       name => "Fintek F75387SG/RG",
1365       driver => "to-be-written",
1366       i2c_addrs => [0x2d..0x2e],
1367       i2c_detect => sub { fintek_detect(5, @_); },
1368     },
1369     {
1370       name => "Fintek F75383S/M",
1371       driver => "to-be-written",
1372       i2c_addrs => [0x4c],
1373       i2c_detect => sub { fintek_detect(6, @_); },
1374     },
1375     {
1376       name => "Fintek F75384S/M",
1377       driver => "to-be-written",
1378       i2c_addrs => [0x4d],
1379       i2c_detect => sub { fintek_detect(6, @_); },
1380     },
1381     {
1382       name => "Fintek custom power control IC",
1383       driver => "to-be-written",
1384       i2c_addrs => [0x2f],
1385       i2c_detect => sub { fintek_detect(7, @_); },
1386     },
1387     {
1388       name => "AMD K8 thermal sensors",
1389       driver => "k8temp",
1390       isa_addrs => [ 0 ],
1391       isa_detect => sub { k8temp_pci_detect(); },
1392     },
1393     {
1394       name => "Philips Semiconductors SAA1064",
1395       driver => "saa1064",
1396       i2c_addrs => [0x38..0x3b],
1397       i2c_detect => sub { saa1064_detect(@_); },
1398     },
1399     {
1400       name => "Philips Semiconductors PCA9540",
1401       driver => "pca9540",
1402       i2c_addrs => [0x70],
1403       i2c_detect => sub { pca9540_detect(@_); },
1404     },
1405     {
1406       name => "Philips Semiconductors PCA9556",
1407       driver => "to-be-written",
1408       i2c_addrs => [0x18..0x1f],
1409       i2c_detect => sub { pca9556_detect(@_); },
1410     },
1411     {
1412       name => "Maxim MAX6900",
1413       driver => "to-be-written",
1414       i2c_addrs => [0x50],
1415       i2c_detect => sub { max6900_detect(@_); },
1416     },
1417     {
1418       name => "SMBus 2.0 ARP-Capable Device",
1419       driver => "not-a-sensor",
1420       i2c_addrs => [0x61],
1421       i2c_detect => sub { arp_detect(@_); },
1422     },
1423     {
1424       name => "IPMI BMC KCS",
1425       driver => "bmcsensors",
1426       isa_addrs => [ 0x0ca0 ],
1427       isa_detect => sub { ipmi_kcs_detect(@_); },
1428     },
1429     {
1430       name => "IPMI BMC SMIC",
1431       driver => "bmcsensors",
1432       isa_addrs => [ 0x0ca8 ],
1433       isa_detect => sub { ipmi_smic_detect(@_); },
1434     },
1435     {
1436       name => "Smart Battery Charger",
1437       driver => "to-be-written",
1438       i2c_addrs => [0x09],
1439       i2c_detect => sub { smartbatt_chgr_detect(@_); },
1440     },
1441     {
1442       name => "Smart Battery Manager/Selector",
1443       driver => "to-be-written",
1444       i2c_addrs => [0x0a],
1445       i2c_detect => sub { smartbatt_mgr_detect(@_); },
1446     },
1447     {
1448       name => "Smart Battery",
1449       driver => "smartbatt",
1450       i2c_addrs => [0x0b],
1451       i2c_detect => sub { smartbatt_detect(@_); },
1452     },
1453);
1454
1455# Special case chip information goes here and would be included in
1456# the chip_special_cases routine below
1457use vars qw($chip_kern24_w83791d $chip_kern26_w83791d);
1458$chip_kern24_w83791d = {
1459        name => "Winbond W83791D",
1460        driver => "w83781d",
1461        i2c_addrs => [0x2c..0x2f],
1462        i2c_detect => sub { w83781d_detect(7, @_); },
1463};
1464
1465$chip_kern26_w83791d = {
1466        name => "Winbond W83791D",
1467        driver => "w83791d",
1468        i2c_addrs => [0x2c..0x2f],
1469        i2c_detect => sub { w83781d_detect(7, @_); },
1470};
1471
1472# This is a list of all recognized superio chips.
1473# Each entry must have the following fields:
1474#  name: The full chip name
1475#  driver: The driver name (without .o extension). Put in
1476#      "to-be-written" if it is not yet available.
1477#      Put in "not-a-sensor" if the chip doesn't have hardware monitoring
1478#      capabilities (listing such chips here removes the need of manual
1479#      lookup when people report them).
1480#  devid: The device ID(s) we have to match (base device)
1481#  devid_mask (optional): Bitmask to apply before checking the device ID
1482#  logdev: The logical device containing the sensors
1483#  alias_detect (optional): For chips which can be both on the ISA and the
1484#      I2C bus, a function which detectes whether two entries are the same.
1485#      The function should take three parameters: The ISA address, the
1486#      I2C bus number, and the I2C address.
1487# Entries are grouped by family. Each family entry has the following fields:
1488#  family: The family name
1489#  guess (optional): Typical logical device address. This lets us do
1490#      generic probing if we fail to recognize the chip.
1491#  enter: The password sequence to write to the address register
1492#  chips: Array of chips
1493@superio_ids = (
1494  {
1495    family => "ITE",
1496    guess => 0x290,
1497    enter =>
1498    {
1499      0x2e => [0x87, 0x01, 0x55, 0x55],
1500      0x4e => [0x87, 0x01, 0x55, 0xaa],
1501    },
1502    chips =>
1503    [
1504      {
1505        name => "ITE IT8702F Super IO Sensors",
1506        driver => "to-be-written",
1507        devid => 0x8702,
1508        logdev => 0x04,
1509      },
1510      {
1511        name => "ITE IT8705F Super IO Sensors",
1512        driver => "it87",
1513        devid => 0x8705,
1514        logdev => 0x04,
1515      },
1516      {
1517        name => "ITE IT8712F Super IO Sensors",
1518        driver => "it87",
1519        devid => 0x8712,
1520        logdev => 0x04,
1521        alias_detect => sub { ite_alias_detect(0, @_); },
1522      },
1523      {
1524        name => "ITE IT8716F Super IO Sensors",
1525        driver => "it87",
1526        devid => 0x8716,
1527        logdev => 0x04,
1528      },
1529      {
1530        name => "ITE IT8718F Super IO Sensors",
1531        driver => "it87",
1532        devid => 0x8718,
1533        logdev => 0x04,
1534      },
1535    ],
1536  },
1537  {
1538    family => "National Semiconductor",
1539    enter =>
1540    {
1541      0x2e => [],
1542      0x4e => [],
1543    },
1544    chips =>
1545    [
1546      {
1547        name => "Nat. Semi. PC87351 Super IO Fan Sensors",
1548        driver => "to-be-written",
1549        devid => 0xe2,
1550        logdev => 0x08,
1551      },
1552      {
1553        name => "Nat. Semi. PC87360 Super IO Fan Sensors",
1554        driver => "pc87360",
1555        devid => 0xe1,
1556        logdev => 0x09,
1557      },
1558      {
1559        name => "Nat. Semi. PC87363 Super IO Fan Sensors",
1560        driver => "pc87360",
1561        devid => 0xe8,
1562        logdev => 0x09,
1563      },
1564      {
1565        name => "Nat. Semi. PC87364 Super IO Fan Sensors",
1566        driver => "pc87360",
1567        devid => 0xe4,
1568        logdev => 0x09,
1569      },
1570      {
1571        name => "Nat. Semi. PC87365 Super IO Fan Sensors",
1572        driver => "pc87360",
1573        devid => 0xe5,
1574        logdev => 0x09,
1575      },
1576      {
1577        name => "Nat. Semi. PC87365 Super IO Voltage Sensors",
1578        driver => "pc87360",
1579        devid => 0xe5,
1580        logdev => 0x0d,
1581      },
1582      {
1583        name => "Nat. Semi. PC87365 Super IO Thermal Sensors",
1584        driver => "pc87360",
1585        devid => 0xe5,
1586        logdev => 0x0e,
1587      },
1588      {
1589        name => "Nat. Semi. PC87366 Super IO Fan Sensors",
1590        driver => "pc87360",
1591        devid => 0xe9,
1592        logdev => 0x09,
1593      },
1594      {
1595        name => "Nat. Semi. PC87366 Super IO Voltage Sensors",
1596        driver => "pc87360",
1597        devid => 0xe9,
1598        logdev => 0x0d,
1599      },
1600      {
1601        name => "Nat. Semi. PC87366 Super IO Thermal Sensors",
1602        driver => "pc87360",
1603        devid => 0xe9,
1604        logdev => 0x0e,
1605      },
1606      {
1607        name => "Nat. Semi. PC87372 Super IO Fan Sensors",
1608        driver => "to-be-written",
1609        devid => 0xf0,
1610        logdev => 0x09,
1611      },
1612      {
1613        name => "Nat. Semi. PC87373 Super IO Fan Sensors",
1614        driver => "to-be-written",
1615        devid => 0xf3,
1616        logdev => 0x09,
1617      },
1618      {
1619        name => "Nat. Semi. PC87591 Super IO",
1620        driver => "to-be-written",
1621        devid => 0xec,
1622        logdev => 0x0f,
1623      },
1624      {
1625        name => "Nat. Semi. PC87371 Super IO",
1626        driver => "not-a-sensor",
1627        devid => 0xd0,
1628      },
1629      {
1630        name => "Nat. Semi. PC97371 Super IO",
1631        driver => "not-a-sensor",
1632        devid => 0xdf,
1633      },
1634      {
1635        name => "Nat. Semi. PC8739x Super IO",
1636        driver => "not-a-sensor",
1637        devid => 0xea,
1638      },
1639      {
1640        name => "Nat. Semi. PC8741x Super IO",
1641        driver => "not-a-sensor",
1642        devid => 0xee,
1643      },
1644      {
1645        name => "Nat. Semi. PC87427 Super IO Fan Sensors",
1646        driver => "pc87427",
1647        devid => 0xf2,
1648        logdev => 0x09,
1649      },
1650      {
1651        name => "Nat. Semi. PC87427 Super IO Health Sensors",
1652        driver => "to-be-written",
1653        devid => 0xf2,
1654        logdev => 0x14,
1655      },
1656    ],
1657  },
1658  {
1659    family => "SMSC",
1660    enter =>
1661    {
1662      0x2e => [0x55],
1663      0x4e => [0x55],
1664    },
1665    chips =>
1666    [
1667      {
1668        name => "SMSC LPC47B27x Super IO Fan Sensors",
1669        driver => "smsc47m1",
1670        devid => 0x51,
1671        logdev => 0x0a,
1672      },
1673      {
1674        name => "SMSC LPC47M10x/112/13x Super IO Fan Sensors",
1675        driver => "smsc47m1",
1676        devid => 0x59,
1677        logdev => 0x0a,
1678      },
1679      {
1680        name => "SMSC LPC47M14x Super IO Fan Sensors",
1681        driver => "smsc47m1",
1682        devid => 0x5f,
1683        logdev => 0x0a,
1684      },
1685      {
1686        name => "SMSC LPC47M15x/192/997 Super IO Fan Sensors",
1687        driver => "smsc47m1",
1688        devid => 0x60,
1689        logdev => 0x0a,
1690      },
1691      {
1692        name => "SMSC LPC47S42x Super IO Fan Sensors",
1693        driver => "to-be-written",
1694        devid => 0x57,
1695        logdev => 0x0a,
1696      },
1697      {
1698        name => "SMSC LPC47S45x Super IO Fan Sensors",
1699        driver => "to-be-written",
1700        devid => 0x62,
1701        logdev => 0x0a,
1702      },
1703      {
1704        name => "SMSC LPC47M172 Super IO Fan Sensors",
1705        driver => "to-be-written",
1706        devid => 0x14,
1707        logdev => 0x0a,
1708      },
1709      {
1710        name => "SMSC LPC47M182 Super IO Fan Sensors",
1711        driver => "to-be-written",
1712        devid => 0x74,
1713        logdev => 0x0a,
1714      },
1715      {
1716        name => "SMSC LPC47B397-NC Super IO",
1717        driver => "smsc47b397",
1718        devid => 0x6f,
1719        logdev => 0x08,
1720      },
1721      {
1722        name => "SMSC SCH5307-NS Super IO",
1723        driver => "smsc47b397",
1724        devid => 0x81,
1725        logdev => 0x08,
1726      },
1727      {
1728        name => "SMSC LPC47M584-NC Super IO",
1729        # No datasheet
1730        devid => 0x76,
1731      },
1732      {
1733        name => "SMSC DME1737 Super IO",
1734        # Hardware monitoring features are accessed on the SMBus
1735        driver => "not-a-sensor",
1736        devid => 0x78,
1737      },
1738    ],
1739  },
1740  {
1741    family => "VIA/Winbond/Fintek",
1742    guess => 0x290,
1743    enter =>
1744    {
1745      0x2e => [0x87, 0x87],
1746      0x4e => [0x87, 0x87],
1747    },
1748    chips =>
1749    [
1750      {
1751        name => "VIA VT1211 Super IO Sensors",
1752        driver => "vt1211",
1753        devid => 0x3c,
1754        logdev => 0x0b,
1755        alias_detect => sub { vt1211_alias_detect(0, @_); },
1756      },
1757      {
1758        name => "Winbond W83627HF Super IO Sensors",
1759        driver => "w83627hf",
1760        devid => 0x52,
1761        logdev => 0x0b,
1762      },
1763      {
1764        name => "Winbond W83627THF Super IO Sensors",
1765        driver => "w83627hf",
1766        devid => 0x82,
1767        logdev => 0x0b,
1768      },
1769      {
1770        name => "Winbond W83637HF Super IO Sensors",
1771        driver => "w83627hf",
1772        devid => 0x70,
1773        logdev => 0x0b,
1774      },
1775      {
1776        name => "Winbond W83687THF Super IO Sensors",
1777        driver => "w83627hf",
1778        devid => 0x85,
1779        logdev => 0x0b,
1780      },
1781      {
1782        name => "Winbond W83697HF Super IO Sensors",
1783        driver => "w83627hf",
1784        devid => 0x60,
1785        logdev => 0x0b,
1786      },
1787      {
1788        name => "Winbond W83697SF/UF Super IO PWM",
1789        driver => "to-be-written",
1790        devid => 0x68,
1791        logdev => 0x0b,
1792      },
1793      {
1794        name => "Winbond W83627EHF/EHG Super IO Sensors",
1795        driver => "w83627ehf",
1796        # W83627EHF datasheet says 0x886x but 0x8853 was seen, thus the
1797        # broader mask. W83627EHG was seen with ID 0x8863.
1798        devid => 0x8840,
1799        devid_mask => 0xFFC0,
1800        logdev => 0x0b,
1801        alias_detect => sub { w83781d_alias_detect(9, @_); },
1802      },
1803      {
1804        name => "Winbond W83627DHG Super IO Sensors",
1805        driver => "w83627ehf",
1806        devid => 0xA020,
1807        devid_mask => 0xFFF0,
1808        logdev => 0x0b,
1809        alias_detect => sub { w83781d_alias_detect(10, @_); },
1810      },
1811      {
1812        name => "Winbond W83L517D Super IO",
1813        driver => "not-a-sensor",
1814        devid => 0x61,
1815      },
1816      {
1817        name => "Fintek F71805F/FG Super IO Sensors",
1818        driver => "f71805f",
1819        devid => 0x0406,
1820        logdev => 0x04,
1821      },
1822      {
1823        name => "Fintek F71872F/FG Super IO Sensors",
1824        driver => "f71805f",
1825        devid => 0x0341,
1826        logdev => 0x04,
1827      },
1828      {
1829        name => "Fintek F81218D Super IO",
1830        driver => "not-a-sensor",
1831        devid => 0x0206,
1832      },
1833      {
1834        name => "EPoX EP1308 Super IO",
1835        driver => "to-be-written",
1836        devid => 0x0541,
1837        logdev => 0x04,
1838      },
1839    ],
1840  },
1841);
1842
1843#######################
1844# AUXILIARY FUNCTIONS #
1845#######################
1846
1847sub swap_bytes
1848{
1849  return (($_[0] & 0xff00) >> 8) + (($_[0] & 0x00ff) << 8)
1850}
1851
1852# $_[0] is the sought value
1853# @_[1..] is the list to seek in
1854# Returns: 0 on failure, 1 if found.
1855# Note: Every use of this sub probably indicates the use of the wrong
1856#       datastructure
1857sub contains
1858{
1859  my $sought = shift;
1860  foreach (@_) {
1861    return 1 if $sought eq $_;
1862  }
1863  return 0;
1864}
1865
1866sub parse_not_to_scan
1867{
1868  my ($min,$max,$to_parse) = @_;
1869  my @ranges = split /\s*,\s*/, $to_parse;
1870  my @res;
1871  my $range;
1872  foreach $range (@ranges) {
1873    my ($start,$end) = split /\s*-s*/, $range;
1874    $start = oct $start if $start =~ /^0/;
1875    if (defined $end) {
1876      $end = oct $end if $end =~ /^0/;
1877      $start = $min if $start < $min;
1878      $end = $max if $end > $max;
1879      push @res, ($start+0..$end+0);
1880    } else {
1881      push @res, $start+0 if $start >= $min and $start <= $max;
1882    }
1883  }
1884  return sort { $a <=> $b } @res;
1885}
1886
1887# @_[0]: Reference to list 1
1888# @_[1]: Reference to list 2
1889# Result: 0 if they have no elements in common, 1 if they have
1890# Elements must be numeric.
1891sub any_list_match
1892{
1893  my ($list1,$list2) = @_;
1894  my ($el1,$el2);
1895  foreach $el1 (@$list1) {
1896    foreach $el2 (@$list2) {
1897      return 1 if $el1 == $el2;
1898    }
1899  }
1900  return 0;
1901}
1902
1903###################
1904# I/O port access #
1905###################
1906
1907sub initialize_ioports
1908{
1909  sysopen (IOPORTS, "/dev/port", O_RDWR)
1910    or die "/dev/port: $!\n";
1911  binmode IOPORTS;
1912}
1913
1914sub close_ioports
1915{
1916  close (IOPORTS)
1917    or print "Warning: $!\n";
1918}
1919
1920# $_[0]: port to read
1921# Returns: -1 on failure, read value on success.
1922sub inb
1923{
1924  my ($res,$nrchars);
1925  sysseek IOPORTS, $_[0], 0 or return -1;
1926  $nrchars = sysread IOPORTS, $res, 1;
1927  return -1 if not defined $nrchars or $nrchars != 1;
1928  $res = unpack "C",$res ;
1929  return $res;
1930}
1931
1932# $_[0]: port to write
1933# $_[1]: value to write
1934# Returns: -1 on failure, 0 on success.
1935sub outb
1936{
1937  if ($_[1] > 0xff)
1938  {
1939    my ($package, $filename, $line, $sub) = caller(1);
1940    print "\n*** Called outb with value=$_[1] from line $line\n",
1941          "*** (in $sub). PLEASE REPORT!\n",
1942          "*** Terminating.\n";
1943    exit(-1);
1944  }
1945  my $towrite = pack "C", $_[1];
1946  sysseek IOPORTS, $_[0], 0 or return -1;
1947  my $nrchars = syswrite IOPORTS, $towrite, 1;
1948  return -1 if not defined $nrchars or $nrchars != 1;
1949  return 0;
1950}
1951
1952# $_[0]: Address register
1953# $_[1]: Data register
1954# $_[2]: Register to read
1955# Returns: read value
1956sub isa_read_byte
1957{
1958  outb $_[0],$_[2];
1959  return inb $_[1];
1960}
1961
1962# $_[0]: Address register
1963# $_[1]: Data register
1964# $_[2]: Register to write
1965# $_[3}: Value to write
1966# Returns: nothing
1967sub isa_write_byte
1968{
1969  outb $_[0],$_[2];
1970  outb $_[1],$_[3];
1971}
1972
1973#################
1974# AUTODETECTION #
1975#################
1976
1977use vars qw($modules_conf $dev_i2c $sysfs_root);
1978
1979sub initialize_conf
1980{
1981  my $use_devfs = 0;
1982  open(local *INPUTFILE, "/proc/mounts") or die "Can't access /proc/mounts!";
1983  local $_;
1984  while (<INPUTFILE>) {
1985    if (m@^\w+ /dev devfs @) {
1986      $use_devfs = 1;
1987      $dev_i2c = '/dev/i2c/';
1988    }
1989    if (m@^\S+ (/\w+) sysfs @) {
1990      $sysfs_root = $1;
1991    }
1992  }
1993  close INPUTFILE;
1994
1995  my $use_udev = 0;
1996  if (open(*INPUTFILE, '/etc/udev/udev.conf')) {
1997    while (<INPUTFILE>) {
1998      if (m/^\s*udev_db\s*=\s*\"([^"]*)\"/ || m/^\s*udev_db\s*=\s*(\S+)/) {
1999        if (-e $1) {
2000          $use_udev = 1;
2001          $dev_i2c = '/dev/i2c-';
2002        }
2003        last;
2004      }
2005    }
2006    close INPUTFILE;
2007  }
2008 
2009  if (!$use_udev) {
2010    # Try some known default udev db locations, just in case
2011    if (-e '/dev/.udev.tdb' || -e '/dev/.udev'
2012     || -e '/dev/.udevdb') {
2013      $use_udev = 1;
2014      $dev_i2c = '/dev/i2c-';
2015    }
2016  }
2017
2018  if (-f '/etc/modules.conf') {
2019    $modules_conf = '/etc/modules.conf';
2020  } elsif (-f '/etc/conf.modules') {
2021    $modules_conf = '/etc/conf.modules';
2022  } else { # default
2023    $modules_conf = '/etc/modules.conf';
2024  }
2025
2026  if (!($use_devfs || $use_udev)) {
2027    if (-c '/dev/i2c-0') {
2028      $dev_i2c = '/dev/i2c-';
2029    } else { # default
2030      print "No i2c device files found. Use prog/mkdev/mkdev.sh to create them.\n";
2031      exit -1;
2032    }
2033  }
2034}
2035
2036# [0] -> VERSION
2037# [1] -> PATCHLEVEL
2038# [2] -> SUBLEVEL
2039# [3] -> EXTRAVERSION
2040#
2041use vars qw(@kernel_version);
2042
2043sub initialize_kernel_version
2044{
2045  `uname -r` =~ /(\d+)\.(\d+)\.(\d+)(.*)/;
2046  @kernel_version = ($1, $2, $3, $4);
2047}
2048
2049sub kernel_version_at_least
2050{
2051  my ($vers, $plvl, $slvl) = @_;
2052  return 1 if ($kernel_version[0]  > $vers ||
2053                ($kernel_version[0] == $vers && 
2054                  ($kernel_version[1]  > $plvl || 
2055                    ($kernel_version[1] == $plvl && 
2056                      ($kernel_version[2] >= $slvl)))));
2057  return 0;
2058}
2059
2060# @cpu is a list of reference to hashes, one hash per CPU.
2061# Each entry has the following keys: vendor_id, cpu family, model,
2062# model name and stepping, directly taken from /proc/cpuinfo.
2063use vars qw(@cpu);
2064
2065sub initialize_cpu_list
2066{
2067  open(local *INPUTFILE, "/proc/cpuinfo") or die "Can't access /proc/cpuinfo!";
2068  local $_;
2069  my %entry;
2070  while (<INPUTFILE>) {
2071    if (m/^processor\s*:\s*(\d+)/) {
2072      push @cpu, \%entry if scalar keys(%entry); # Previous entry
2073      %entry = (); # New entry
2074      next;
2075    }
2076    if (m/^(vendor_id|cpu family|model|model name|stepping)\s*:\s*(.+)$/) {
2077      my $k = $1;
2078      my $v = $2;
2079      $v =~ s/\s+/ /g;  # Merge multiple spaces
2080      $v =~ s/ $//;     # Trim trailing space
2081      $entry{$k} = $v;
2082      next;
2083    }
2084  }
2085  push @cpu, \%entry if scalar keys(%entry); # Last entry
2086  close INPUTFILE;
2087}
2088
2089###########
2090# MODULES #
2091###########
2092
2093use vars qw(%modules_list %modules_supported);
2094
2095sub initialize_modules_list
2096{
2097  open(local *INPUTFILE, "/proc/modules") or return;
2098  local $_;
2099  while (<INPUTFILE>) {
2100    tr/_/-/;
2101    $modules_list{$1} = 1 if m/^(\S*)/;
2102  }
2103}
2104
2105sub initialize_modules_supported
2106{
2107  foreach my $chip (@chip_ids) {
2108    $modules_supported{$chip->{driver}}++;
2109  }
2110}
2111
2112#################
2113# SYSFS HELPERS #
2114#################
2115
2116# From a sysfs device path, return the driver name, or undef
2117sub sysfs_device_driver($)
2118{
2119  my $device = shift;
2120 
2121  my $link = readlink("$device/driver");
2122  return unless defined $link;
2123  return basename($link);
2124}
2125
2126# From a sysfs device path and an attribute name, return the attribute
2127# value, or undef
2128sub sysfs_device_attribute($$)
2129{
2130  my ($device, $attr) = @_;
2131  my $value;
2132
2133  open(local *FILE, "$device/$attr") or return;
2134  return unless defined($value = <FILE>);
2135  close(FILE);
2136
2137  chomp($value);
2138  return $value;
2139}
2140
2141##############
2142# PCI ACCESS #
2143##############
2144
2145use vars qw(%pci_list);
2146
2147# This function returns a list of hashes. Each hash has some PCI information:
2148# 'domain', 'bus', 'slot' and 'func' uniquely identify a PCI device in a
2149# computer; 'vendid' and 'devid' uniquely identify a type of device.
2150# 'class' lets us spot unknown SMBus adapters.
2151# This function is used when sysfs is available (Linux 2.6).
2152sub read_sys_dev_pci($)
2153{
2154  my $devices = shift;
2155  my ($dev, @pci_list);
2156
2157  opendir(local *DEVICES, "$devices")
2158    or die "$devices: $!";
2159
2160  while (defined($dev = readdir(DEVICES))) {
2161    my %record;
2162    next unless $dev =~
2163      m/^(?:([\da-f]+):)?([\da-f]+):([\da-f]+)\.([\da-f]+)$/;
2164
2165    $record{domain} = hex $1;
2166    $record{bus} = hex $2;
2167    $record{slot} = hex $3;
2168    $record{func} = hex $4;
2169
2170    $record{vendid} = oct sysfs_device_attribute("$devices/$dev", "vendor");
2171    $record{devid} = oct sysfs_device_attribute("$devices/$dev", "device");
2172    $record{class} = (oct sysfs_device_attribute("$devices/$dev", "class"))
2173                     >> 8;
2174
2175    push @pci_list, \%record;
2176  }
2177
2178  return \@pci_list;
2179}
2180
2181# This function returns a list of hashes. Each hash has some PCI information:
2182# 'bus', 'slot' and 'func' uniquely identify a PCI device in a computer;
2183# 'vendid' and 'devid' uniquely identify a type of device.
2184# This function is used when sysfs is not available (Linux 2.4).
2185sub read_proc_dev_pci
2186{
2187  my ($dfn, $vend, @pci_list);
2188  open(local *INPUTFILE, "/proc/bus/pci/devices")
2189    or die "/proc/bus/pci/devices: $!";
2190  local $_;
2191  while (<INPUTFILE>) {
2192    my %record;
2193    ($dfn, $vend) = map { hex } (split) [0..1];
2194    $record{bus} = $dfn >> 8;
2195    $record{slot} = ($dfn & 0xf8) >> 3;
2196    $record{func} = $dfn & 0x07;
2197    $record{vendid} = $vend >> 16;
2198    $record{devid} = $vend & 0xffff;
2199   
2200    push @pci_list, \%record;
2201  }
2202  return \@pci_list;
2203}
2204
2205sub initialize_proc_pci
2206{
2207  my $pci_list;
2208
2209  if (defined $sysfs_root) {
2210    $pci_list = read_sys_dev_pci("$sysfs_root/bus/pci/devices");
2211  } else {
2212    $pci_list = read_proc_dev_pci();
2213  }
2214
2215  # Note that we lose duplicate devices at this point, but we don't
2216  # really care. What matters to us is which unique devices are present,
2217  # not how many of each.
2218  %pci_list = map {
2219    sprintf("%04x:%04x", $_->{vendid}, $_->{devid}) => $_
2220  } @{$pci_list};
2221}
2222
2223#####################
2224# ADAPTER DETECTION #
2225#####################
2226
2227sub adapter_pci_detection_sis_96x
2228{
2229  my $driver="";
2230
2231  # first, determine which driver if any...
2232  if (kernel_version_at_least(2,6,0)) {
2233    if (exists $pci_list{"1039:0016"}) {
2234      $driver = "i2c-sis96x";
2235    } elsif (exists $pci_list{"1039:0008"}) {
2236      $driver = "i2c-sis5595";
2237    }
2238  } elsif (kernel_version_at_least(2,4,0)) {
2239    if (exists $pci_list{"1039:0008"}) {
2240      if ((exists $pci_list{"1039:0645"}) ||
2241          (exists $pci_list{"1039:0646"}) ||
2242          (exists $pci_list{"1039:0648"}) ||
2243          (exists $pci_list{"1039:0650"}) ||
2244          (exists $pci_list{"1039:0651"}) ||
2245          (exists $pci_list{"1039:0655"}) ||
2246          (exists $pci_list{"1039:0661"}) ||
2247          (exists $pci_list{"1039:0735"}) ||
2248          (exists $pci_list{"1039:0745"}) ||
2249          (exists $pci_list{"1039:0746"})) {
2250        $driver = "i2c-sis645";
2251      } else {
2252        $driver = "i2c-sis5595";
2253      }
2254    } elsif ((exists $pci_list{"1039:0016"}) ||
2255             (exists $pci_list{"1039:0018"})) {
2256      $driver = "i2c-sis645";
2257    }
2258  }
2259
2260  # then, add the appropriate entries to @pci_adapters
2261  if ($driver eq "i2c-sis5595") {
2262    push @pci_adapters, @pci_adapters_sis5595;
2263  } elsif ($driver eq "i2c-sis645") {
2264    push @pci_adapters, @pci_adapters_sis645;
2265  } elsif ($driver eq "i2c-sis96x") {
2266    push @pci_adapters, @pci_adapters_sis96x;
2267  }
2268}
2269
2270# Build and return a PCI device's bus ID
2271sub pci_busid($)
2272{
2273  my $device = shift;
2274  my $busid;
2275
2276  $busid = sprintf("\%02x:\%02x.\%x",
2277                   $device->{bus}, $device->{slot}, $device->{func});
2278  $busid = sprintf("\%04x:", $device->{domain}) . $busid
2279    if defined $device->{domain};
2280
2281  return $busid;
2282}
2283
2284sub adapter_pci_detection
2285{
2286  my ($key, $device, $try, @res, %smbus);
2287  print "Probing for PCI bus adapters...\n";
2288
2289  # Custom detection routine for some SiS chipsets
2290  adapter_pci_detection_sis_96x();
2291
2292  # Build a list of detected SMBus devices
2293  foreach $key (keys %pci_list) {
2294    $device = $pci_list{$key};
2295    $smbus{$key}++
2296      if exists $device->{class} && $device->{class} == 0x0c05; # SMBus
2297  }
2298
2299  # Loop over the known I2C/SMBus adapters
2300  foreach $try (@pci_adapters) {
2301    $key = sprintf("%04x:%04x", $try->{vendid}, $try->{devid});
2302    if (exists $pci_list{$key}) {
2303        $device = $pci_list{$key};
2304        printf "Use driver `\%s' for device \%s: \%s\n",
2305               $try->{driver}, pci_busid($device), $try->{procid};
2306        if ($try->{driver} eq "to-be-tested") {
2307          print "\nWe are currently looking for testers for this adapter!\n".
2308                "Please check http://www.lm-sensors.org/wiki/Devices\n".
2309                "and/or contact us if you want to help.\n\n";
2310          print "Continue... ";
2311          <STDIN>;
2312          print "\n";
2313        }
2314        push @res,$try->{driver};
2315
2316        # Delete from detected SMBus device list
2317        delete $smbus{$key};
2318    }
2319  }
2320
2321  # Now see if there are unknown SMBus devices left
2322  foreach $key (keys %smbus) {
2323    $device = $pci_list{$key};
2324    printf "Found unknown SMBus adapter \%04x:\%04x at \%s.\n",
2325           $device->{vendid}, $device->{devid}, pci_busid($device);
2326  }
2327 
2328  if (! @res) {
2329    print "Sorry, no known PCI bus adapters found.\n";
2330  }
2331  return @res;
2332}
2333
2334# $_[0]: Adapter description as found in /proc/bus/i2c
2335sub find_adapter_driver
2336{
2337  my $adapter;
2338  for $adapter (@pci_adapters) {
2339    return $adapter->{driver}
2340      if (exists $adapter->{match} && $_[0] =~ $adapter->{match});
2341  }
2342  return "UNKNOWN";
2343}
2344
2345#############################
2346# I2C AND SMBUS /DEV ACCESS #
2347#############################
2348
2349# This should really go into a separate module/package.
2350
2351# These are copied from <linux/i2c-dev.h>
2352
2353use constant IOCTL_I2C_SLAVE    => 0x0703;
2354use constant IOCTL_I2C_FUNCS    => 0x0705;
2355use constant IOCTL_I2C_SMBUS    => 0x0720;
2356
2357use constant SMBUS_READ         => 1;
2358use constant SMBUS_WRITE        => 0;
2359
2360use constant SMBUS_QUICK        => 0;
2361use constant SMBUS_BYTE         => 1;
2362use constant SMBUS_BYTE_DATA    => 2;
2363use constant SMBUS_WORD_DATA    => 3;
2364
2365use constant I2C_FUNC_SMBUS_QUICK       => 0x00010000;
2366use constant I2C_FUNC_SMBUS_READ_BYTE   => 0x00020000;
2367
2368# Get the i2c adapter's functionalities
2369# $_[0]: Reference to an opened filehandle
2370# Returns: -1 on failure, functionality bitfield on success.
2371sub i2c_get_funcs($)
2372{
2373  my $file = shift;
2374  my $funcs;
2375
2376  ioctl $file, IOCTL_I2C_FUNCS, $funcs='' or return -1;
2377  $funcs = unpack "L", $funcs;
2378
2379  return $funcs;
2380}
2381
2382# Select the device to communicate with through its address.
2383# $_[0]: Reference to an opened filehandle
2384# $_[1]: Address to select
2385# Returns: 0 on failure, 1 on success.
2386sub i2c_set_slave_addr
2387{
2388  my ($file,$addr) = @_;
2389  ioctl $file, IOCTL_I2C_SLAVE, $addr or return 0;
2390  return 1;
2391}
2392
2393# i2c_smbus_access is based upon the corresponding C function (see
2394# <linux/i2c-dev.h>). You should not need to call this directly.
2395# Exact calling conventions are intricate; read i2c-dev.c if you really need
2396# to know.
2397# $_[0]: Reference to an opened filehandle
2398# $_[1]: SMBUS_READ for reading, SMBUS_WRITE for writing
2399# $_[2]: Command (usually register number)
2400# $_[3]: Transaction kind (SMBUS_BYTE, SMBUS_BYTE_DATA, etc.)
2401# $_[4]: Reference to an array used for input/output of data
2402# Returns: 0 on failure, 1 on success.
2403# Note that we need to get back to Integer boundaries through the 'x2'
2404# in the pack. This is very compiler-dependent; I wish there was some other
2405# way to do this.
2406sub i2c_smbus_access
2407{
2408  my ($file,$read_write,$command,$size,$data) = @_;
2409  my $data_array = pack "C32", @$data;
2410  my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
2411  ioctl $file, IOCTL_I2C_SMBUS, $ioctl_data or return 0;
2412  @{$_[4]} = unpack "C32",$data_array;
2413  return 1;
2414}
2415
2416# $_[0]: Reference to an opened filehandle
2417# $_[1]: Either 0 or 1
2418# Returns: -1 on failure, the 0 on success.
2419sub i2c_smbus_write_quick
2420{
2421  my ($file,$value) = @_;
2422  my @data;
2423  i2c_smbus_access $file, $value, 0, SMBUS_QUICK, \@data
2424         or return -1;
2425  return 0;
2426}
2427
2428# $_[0]: Reference to an opened filehandle
2429# Returns: -1 on failure, the read byte on success.
2430sub i2c_smbus_read_byte
2431{
2432  my ($file) = @_;
2433  my @data;
2434  i2c_smbus_access $file, SMBUS_READ, 0, SMBUS_BYTE, \@data
2435         or return -1;
2436  return $data[0];
2437}
2438
2439# $_[0]: Reference to an opened filehandle
2440# $_[1]: Command byte (usually register number)
2441# Returns: -1 on failure, the read byte on success.
2442sub i2c_smbus_read_byte_data
2443{
2444  my ($file,$command) = @_;
2445  my @data;
2446  i2c_smbus_access $file, SMBUS_READ, $command, SMBUS_BYTE_DATA, \@data
2447         or return -1;
2448  return $data[0];
2449}
2450 
2451# $_[0]: Reference to an opened filehandle
2452# $_[1]: Command byte (usually register number)
2453# Returns: -1 on failure, the read word on success.
2454# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2455# this.
2456sub i2c_smbus_read_word_data
2457{
2458  my ($file,$command) = @_;
2459  my @data;
2460  i2c_smbus_access $file, SMBUS_READ, $command, SMBUS_WORD_DATA, \@data
2461         or return -1;
2462  return $data[0] + 256 * $data[1];
2463}
2464
2465# $_[0]: Reference to an opened filehandle
2466# $_[1]: Address
2467# $_[2]: Functionalities of this i2c adapter
2468# Returns: 1 on successful probing, 0 else.
2469# This function is meant to prevent AT24RF08 corruption and write-only
2470# chips locks. This is done by choosing the best probing method depending
2471# on the address range.
2472sub i2c_probe($$$)
2473{
2474  my ($file, $addr, $funcs) = @_;
2475  my $data = [];
2476  if (($addr >= 0x50 && $addr <= 0x5F)
2477   || ($addr >= 0x30 && $addr <= 0x37)) {
2478    # This covers all EEPROMs we know of, including page protection addresses.
2479    # Note that some page protection addresses will not reveal themselves with
2480    # this, because they ack on write only, but this is probably better since
2481    # some EEPROMs write-protect themselves permanently on almost any write to
2482    # their page protection address.
2483    return 0 unless ($funcs & I2C_FUNC_SMBUS_READ_BYTE);
2484    return i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE, $data);
2485  } else {
2486    return 0 unless ($funcs & I2C_FUNC_SMBUS_QUICK);
2487    return i2c_smbus_access($file, SMBUS_WRITE, 0, SMBUS_QUICK, $data);
2488  }
2489}
2490
2491####################
2492# ADAPTER SCANNING #
2493####################
2494
2495use vars qw(@chips_detected);
2496
2497# We will build a complicated structure @chips_detected here, being:
2498# A list of
2499#  references to hashes
2500#    with field 'driver', being a string with the driver name for this chip;
2501#    with field 'detected'
2502#      being a reference to a list of
2503#        references to hashes of type 'detect_data';
2504#    with field 'misdetected'
2505#      being a reference to a list of
2506#        references to hashes of type 'detect_data'
2507
2508# Type detect_data:
2509# A hash
2510#   with field 'i2c_adap' containing an adapter string as appearing
2511#        in /proc/bus/i2c (if this is an I2C detection)
2512#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
2513#       adapter (if this is an I2C detection)
2514#  with field 'i2c_driver', containing the driver name for this adapter
2515#       (if this is an I2C detection)
2516#  with field 'i2c_addr', containing the I2C address of the detection;
2517#       (if this is an I2C detection)
2518#  with field 'i2c_sub_addrs', containing a reference to a list of
2519#       other I2C addresses (if this is an I2C detection)
2520#  with field 'isa_addr' containing the ISA address this chip is on
2521#       (if this is an ISA detection)
2522#  with field 'conf', containing the confidence level of this detection
2523#  with field 'chipname', containing the chip name
2524
2525# This adds a detection to the above structure. We do no alias detection
2526# here; so you should do ISA detections *after* all I2C detections.
2527# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
2528# In all normal cases, it should be all right.
2529# $_[0]: chip driver
2530# $_[1]: reference to data hash
2531# Returns: Nothing
2532sub add_i2c_to_chips_detected
2533{
2534  my ($chipdriver,$datahash) = @_;
2535  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2536      $main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs,
2537      $do_not_add);
2538
2539  # First determine where the hash has to be added.
2540  for ($i = 0; $i < @chips_detected; $i++) {
2541    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2542  }
2543  if ($i == @chips_detected) {
2544    push @chips_detected, { driver => $chipdriver,
2545                            detected => [],
2546                            misdetected => [] };
2547  }
2548  $new_detected_ref = $chips_detected[$i]->{detected};
2549  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2550
2551  # Find out whether our new entry should go into the detected or the
2552  # misdetected list. We compare all i2c addresses; if at least one matches,
2553  # but our conf value is lower, we assume this is a misdetect.
2554  @hash_addrs = ($datahash->{i2c_addr});
2555  push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
2556       if exists $datahash->{i2c_sub_addrs};
2557  $put_in_detected = 1;
2558  $do_not_add = 0;
2559  FIND_LOOP:
2560  foreach $main_entry (@chips_detected) {
2561    foreach $detected_entry (@{$main_entry->{detected}}) {
2562      @entry_addrs = ($detected_entry->{i2c_addr});
2563      push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
2564               if exists $detected_entry->{i2c_sub_addrs};
2565      if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
2566          any_list_match \@entry_addrs, \@hash_addrs) {
2567        if ($detected_entry->{conf} >= $datahash->{conf}) {
2568          $put_in_detected = 0;
2569        }
2570        if ($chipdriver eq $main_entry->{driver}) {
2571          $do_not_add = 1;
2572        }
2573        last FIND_LOOP;
2574      }
2575    }
2576  }
2577
2578  if ($put_in_detected) {
2579    # Here, we move all entries from detected to misdetected which
2580    # match at least in one main or sub address. This may not be the
2581    # best idea to do, as it may remove detections without replacing
2582    # them with second-best ones. Too bad.
2583    # (Khali 2003-09-13) If the driver is the same, the "misdetected"
2584    # entry is simply deleted; failing to do so cause the configuration
2585    # lines generated later to look very confusing (the driver will
2586    # be told to ignore valid addresses).
2587    @hash_addrs = ($datahash->{i2c_addr});
2588    push @hash_addrs, @{$datahash->{i2c_sub_addrs}} 
2589         if exists $datahash->{i2c_sub_addrs};
2590    foreach $main_entry (@chips_detected) {
2591      $detected_ref = $main_entry->{detected};
2592      $misdetected_ref = $main_entry->{misdetected};
2593      for ($i = @$detected_ref-1; $i >=0; $i--) {
2594        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
2595        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
2596             if exists $detected_ref->[$i]->{i2c_sub_addrs};
2597        if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} and
2598            any_list_match \@entry_addrs, \@hash_addrs) {
2599          push @$misdetected_ref,$detected_ref->[$i]
2600            unless $chipdriver eq $main_entry->{driver};
2601          splice @$detected_ref, $i, 1;
2602        }
2603      }
2604    }
2605
2606    # Now add the new entry to detected
2607    push @$new_detected_ref, $datahash;
2608  } else {
2609    # No hard work here
2610    push @$new_misdetected_ref, $datahash
2611      unless $do_not_add;
2612  }
2613}
2614
2615# This adds a detection to the above structure. We also do alias detection
2616# here; so you should do ISA detections *after* all I2C detections.
2617# $_[0]: alias detection function
2618# $_[1]: chip driver
2619# $_[2]: reference to data hash
2620# Returns: 0 if it is not an alias, datahash reference if it is.
2621sub add_isa_to_chips_detected
2622{
2623  my ($alias_detect,$chipdriver,$datahash) = @_;
2624  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2625      $main_entry,$isalias);
2626
2627  # First determine where the hash has to be added.
2628  $isalias=0;
2629  for ($i = 0; $i < @chips_detected; $i++) {
2630    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2631  }
2632  if ($i == @chips_detected) {
2633    push @chips_detected, { driver => $chipdriver,
2634                            detected => [],
2635                            misdetected => [] };
2636  }
2637  $new_detected_ref = $chips_detected[$i]->{detected};
2638  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2639
2640  # Now, we are looking for aliases. An alias can only be the same chiptype.
2641  # If an alias is found in the misdetected list, we add the new information
2642  # and terminate this function. If it is found in the detected list, we
2643  # still have to check whether another chip has claimed this ISA address.
2644  # So we remove the old entry from the detected list and put it in datahash.
2645
2646  # Misdetected alias detection:
2647  for ($i = 0; $i < @$new_misdetected_ref; $i++) {
2648    if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
2649        not exists $new_misdetected_ref->[$i]->{isa_addr} and
2650        defined $alias_detect and
2651        $new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2652      open(local *FILE, "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}") or
2653        print("Can't open $dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2654        next;
2655      binmode FILE;
2656      i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{i2c_addr} or
2657           print("Can't set I2C address for ",
2658                 "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2659           next;
2660      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2661                          $new_misdetected_ref->[$i]->{i2c_addr})) {
2662        $new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2663        return $new_misdetected_ref->[$i]; 
2664      }
2665    }
2666  }
2667
2668  # Detected alias detection:
2669  for ($i = 0; $i < @$new_detected_ref; $i++) {
2670    if (exists $new_detected_ref->[$i]->{i2c_addr} and
2671        not exists $new_detected_ref->[$i]->{isa_addr} and
2672        defined $alias_detect and
2673        $new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2674      open(local *FILE, "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}") or
2675        print("Can't open $dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2676        next;
2677      binmode FILE;
2678      i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{i2c_addr} or
2679           print("Can't set I2C address for ",
2680                 "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2681           next;
2682      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2683                          $new_detected_ref->[$i]->{i2c_addr})) {
2684        $new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2685        ($datahash) = splice (@$new_detected_ref, $i, 1);
2686        $isalias=1;
2687        last;
2688      }
2689    }
2690  }
2691
2692
2693  # Find out whether our new entry should go into the detected or the
2694  # misdetected list. We only compare main isa_addr here, of course.
2695  # (Khali 2004-05-12) If the driver is the same, the "misdetected"
2696  # entry is simply deleted; same we do for I2C chips.
2697  foreach $main_entry (@chips_detected) {
2698    $detected_ref = $main_entry->{detected};
2699    $misdetected_ref = $main_entry->{misdetected};
2700    for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
2701      if (exists $detected_ref->[$i]->{isa_addr} and
2702          $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
2703        if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
2704          push @$new_misdetected_ref, $datahash
2705            unless $main_entry->{driver} eq $chipdriver;
2706        } else {
2707          push @$misdetected_ref,$detected_ref->[$i]
2708            unless $main_entry->{driver} eq $chipdriver;
2709          splice @$detected_ref, $i,1;
2710          push @$new_detected_ref, $datahash;
2711        }
2712        if ($isalias) {
2713          return $datahash;
2714        } else {
2715          return 0;
2716        }
2717      }
2718    }
2719  }
2720
2721  # Not found? OK, put it in the detected list
2722  push @$new_detected_ref, $datahash;
2723  if ($isalias) {
2724    return $datahash;
2725  } else {
2726    return 0;
2727  }
2728}
2729
2730# $_[0]: The number of the adapter to scan
2731# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
2732# $_[2]: The driver of the adapter
2733# @_[3]: Addresses not to scan (array reference)
2734sub scan_adapter
2735{
2736  my ($adapter_nr, $adapter_name, $adapter_driver, $not_to_scan) = @_;
2737  my ($funcs, $chip, $addr, $conf, @chips, $new_hash, $other_addr);
2738
2739  # As we modify it, we need a copy
2740  my @not_to_scan = @$not_to_scan;
2741
2742  open(local *FILE, "$dev_i2c$adapter_nr") or 
2743    (print "Can't open $dev_i2c$adapter_nr\n"), return;
2744  binmode FILE;
2745
2746  # Can we probe this adapter?
2747  $funcs = i2c_get_funcs(\*FILE);
2748  if ($funcs < 0) {
2749    print "Adapter failed to provide its functionalities, skipping.\n";
2750    return;
2751  }
2752  if (!($funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) {
2753    print "Adapter cannot be probed, skipping.\n";
2754    return;
2755  }
2756  if (~$funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE)) {
2757    print "Adapter doesn't support all probing functions.\n",
2758          "Some addresses won't be probed.\n";
2759  }
2760
2761  # Now scan each address in turn
2762  foreach $addr (0x03..0x77) {
2763    # As the not_to_scan list is sorted, we can check it fast
2764    if (@not_to_scan and $not_to_scan[0] == $addr) {
2765      shift @not_to_scan;
2766      next;
2767    }
2768
2769    if (!i2c_set_slave_addr(\*FILE, $addr)) {
2770      # If the address is busy, in Linux 2.6 we can find out which driver
2771      # is using it, and we assume it is the right one. In Linux 2.4 we
2772      # just give up and warn the user.
2773      my ($device, $driver);
2774      if (defined($sysfs_root)) {
2775        $device = sprintf("$sysfs_root/bus/i2c/devices/\%d-\%04x",
2776                             $adapter_nr, $addr);
2777        $driver = sysfs_device_driver($device);
2778      }
2779      if (defined($driver)) {
2780        $new_hash = {
2781          conf => 6, # Arbitrary confidence
2782          i2c_addr => $addr,
2783          chipname => sysfs_device_attribute($device, "name") || "unknown",
2784          i2c_adap => $adapter_name,
2785          i2c_driver => $adapter_driver,
2786          i2c_devnr => $adapter_nr,
2787        };
2788
2789        printf "Client found at address 0x\%02x\n", $addr;
2790        printf "Handled by driver `\%s' (already loaded), chip type `\%s'\n",
2791               $driver, $new_hash->{chipname};
2792
2793        # Only add it to the list if this is something we would have
2794        # detected, else we end up with random i2c chip drivers listed
2795        # (for example media/video drivers.)
2796        if (exists $modules_supported{$driver}) {
2797          add_i2c_to_chips_detected($driver, $new_hash);
2798        } else {
2799          print "    (note: this is probably NOT a sensor chip!)\n";
2800        }   
2801      } else {
2802        printf("Client at address 0x%02x can not be probed - ".
2803               "unload all client drivers first!\n", $addr);
2804      }
2805      next;
2806    }
2807
2808    next unless i2c_probe(\*FILE, $addr, $funcs);
2809    printf "Client found at address 0x%02x\n",$addr;
2810
2811    foreach $chip (@chip_ids) {
2812      if (exists $chip->{i2c_addrs} and contains $addr, @{$chip->{i2c_addrs}}) {
2813        printf("\%-60s", sprintf("Probing for `\%s'... ", $chip->{name}));
2814        if (($conf,@chips) = &{$chip->{i2c_detect}} (\*FILE ,$addr)) {
2815          print "Success!\n",
2816                "    (confidence $conf, driver `$chip->{driver}')";
2817          if (@chips) {
2818            print ", other addresses:";
2819            @chips = sort @chips;
2820            foreach $other_addr (sort @chips) {
2821              printf(" 0x%02x",$other_addr);
2822            }
2823          }
2824          printf "\n";
2825          $new_hash = { conf => $conf,
2826                        i2c_addr => $addr,
2827                        chipname => $chip->{name},
2828                        i2c_adap => $adapter_name,
2829                        i2c_driver => $adapter_driver,
2830                        i2c_devnr => $adapter_nr,
2831                      };
2832          if (@chips) {
2833            my @chips_copy = @chips;
2834            $new_hash->{i2c_sub_addrs} = \@chips_copy;
2835          }
2836          add_i2c_to_chips_detected $chip->{driver}, $new_hash;
2837        } else {
2838          print "No\n";
2839        }
2840      }
2841    }
2842  }
2843}
2844
2845sub scan_isa_bus
2846{
2847  my ($chip,$addr,$conf);
2848  foreach $chip (@chip_ids) {
2849    next if not exists $chip->{isa_addrs} or not exists $chip->{isa_detect};
2850    foreach $addr (@{$chip->{isa_addrs}}) {
2851      printf("\%-60s", sprintf("Probing for `\%s'\%s... ", $chip->{name},
2852                               $addr ? sprintf(" at 0x\%x", $addr) : ''));
2853      $conf = &{$chip->{isa_detect}} ($addr);
2854      print("No\n"), next if not defined $conf;
2855      print "Success!\n";
2856      printf "    (confidence %d, driver `%s')\n", $conf, $chip->{driver};
2857      my $new_hash = { conf => $conf,
2858                       isa_addr => $addr,
2859                       chipname => $chip->{name}
2860                     };
2861      $new_hash = add_isa_to_chips_detected $chip->{alias_detect},$chip->{driver},
2862                                            $new_hash;
2863      if ($new_hash) {
2864        printf "    Alias of the chip on I2C bus `%s', address 0x%04x\n",
2865                        $new_hash->{i2c_adap},$new_hash->{i2c_addr};
2866      }
2867    }
2868  }
2869}
2870
2871use vars qw(%superio);
2872
2873# The following are taken from the PNP ISA spec (so it's supposed
2874# to be common to all Super I/O chips):
2875#  devidreg: The device ID register(s)
2876#  logdevreg: The logical device register
2877#  actreg: The activation register within the logical device
2878#  actmask: The activation bit in the activation register
2879#  basereg: The I/O base register within the logical device
2880%superio = (
2881  devidreg => 0x20,
2882  logdevreg => 0x07,
2883  actreg => 0x30,
2884  actmask => 0x01,
2885  basereg => 0x60,
2886);
2887
2888sub exit_superio
2889{
2890  my ($addrreg, $datareg) = @_;
2891
2892  # Some chips (SMSC, Winbond) want this
2893  outb($addrreg, 0xaa);
2894
2895  # Return to "Wait For Key" state (PNP-ISA spec)
2896  outb($addrreg, 0x02);
2897  outb($datareg, 0x02);
2898}
2899
2900# Guess if an unknown Super-I/O chip has sensors
2901sub guess_superio_ld($$$)
2902{
2903  my ($addrreg, $datareg, $typical_addr) = @_;
2904  my ($oldldn, $ldn, $addr);
2905
2906  # Save logical device number
2907  outb($addrreg, $superio{logdevreg});
2908  $oldldn = inb($datareg);
2909
2910  for ($ldn = 0; $ldn < 16; $ldn++) {
2911    # Select logical device
2912    outb($addrreg, $superio{logdevreg});
2913    outb($datareg, $ldn);
2914
2915    # Read base I/O address
2916    outb($addrreg, $superio{basereg});
2917    $addr = inb($datareg) << 8;
2918    outb($addrreg, $superio{basereg} + 1);
2919    $addr |= inb($datareg);
2920    next unless ($addr & 0xfff8) == $typical_addr;
2921
2922    printf "    (logical device \%X has address 0x\%x, could be sensors)\n",
2923           $ldn, $addr;
2924    last;
2925  }
2926
2927  # Be nice, restore original logical device
2928  outb($addrreg, $superio{logdevreg});
2929  outb($datareg, $oldldn);
2930}
2931
2932sub probe_superio($$$)
2933{
2934  my ($addrreg, $datareg, $chip) = @_;
2935  my ($val, $addr);
2936
2937  printf "\%-60s",  "Found `$chip->{name}'";
2938
2939  # Does it have hardware monitoring capabilities?
2940  if (!exists $chip->{driver}) {
2941    print "\n    (no information available)\n";
2942    return;
2943  }
2944  if ($chip->{driver} eq "not-a-sensor") {
2945    print "\n    (no hardware monitoring capabilities)\n";
2946    return;
2947  }
2948
2949  # Switch to the sensor logical device
2950  outb($addrreg, $superio{logdevreg});
2951  outb($datareg, $chip->{logdev});
2952
2953  # Check the activation register
2954  outb($addrreg, $superio{actreg});
2955  $val = inb($datareg);
2956  if (!($val & $superio{actmask})) {
2957    print "\n    (but not activated)\n";
2958    return;
2959  }
2960
2961  # Get the IO base register
2962  outb($addrreg, $superio{basereg});
2963  $addr = inb($datareg);
2964  outb($addrreg, $superio{basereg} + 1);
2965  $addr = ($addr << 8) | inb($datareg);
2966  if ($addr == 0) {
2967    print "\n    (but no address specified)\n";
2968    return;
2969  }
2970  print "Success!\n";
2971  printf "    (address 0x\%x, driver `%s')\n", $addr, $chip->{driver};
2972  my $new_hash = { conf => 9,
2973                   isa_addr => $addr,
2974                   chipname => $chip->{name}
2975                 };
2976  add_isa_to_chips_detected $chip->{alias_detect},$chip->{driver},
2977                                        $new_hash;
2978}
2979
2980sub scan_superio
2981{
2982  my ($addrreg, $datareg) = @_;
2983  my ($val, $found);
2984
2985  printf("Probing for Super-I/O at 0x\%x/0x\%x\n", $addrreg, $datareg);
2986
2987  FAMILY:
2988  foreach my $family (@superio_ids) {
2989    printf("\%-60s", "Trying family `$family->{family}'... ");
2990# write the password
2991    foreach $val (@{$family->{enter}->{$addrreg}}) {
2992      outb($addrreg, $val);
2993    }
2994# did it work?
2995    outb($addrreg, $superio{devidreg});
2996    $val = inb($datareg);
2997    outb($addrreg, $superio{devidreg} + 1);
2998    $val = ($val << 8) | inb($datareg);
2999    if ($val == 0x0000 || $val == 0xffff) {
3000      print "No\n";
3001      next FAMILY;
3002    }
3003    print "Yes\n";
3004
3005    $found = 0;
3006    foreach my $chip (@{$family->{chips}}) {
3007      if (($chip->{devid} > 0xff && ($val & ($chip->{devid_mask} || 0xffff)) == $chip->{devid})
3008       || ($chip->{devid} <= 0xff && ($val >> 8) == $chip->{devid})) {
3009        probe_superio($addrreg, $datareg, $chip);
3010        $found++;
3011      }
3012    }
3013
3014    if (!$found) {
3015      printf("Found unknown chip with ID 0x%04x\n", $val);
3016      # Guess if a logical device could correspond to sensors
3017      guess_superio_ld($addrreg, $datareg, $family->{guess})
3018        if defined $family->{guess};
3019    }
3020
3021    exit_superio($addrreg, $datareg);
3022  }
3023}
3024
3025
3026##################
3027# CHIP DETECTION #
3028##################
3029
3030# This routine allows you to select which chips are optionally added to the
3031# chip detection list. The most common use is to allow for different chip
3032# detection/drivers based on different linux kernels
3033# This routine follows the pattern of the SiS adapter special cases
3034sub chip_special_cases
3035{
3036        # Based on the kernel, add the appropriate chip structure to the
3037        # chip_ids detection list
3038        if (kernel_version_at_least(2, 6, 0)) {
3039                push @chip_ids, $chip_kern26_w83791d;
3040        } else {
3041                push @chip_ids, $chip_kern24_w83791d;
3042        }
3043}
3044
3045# Each function returns a confidence value. The higher this value, the more
3046# sure we are about this chip. A Winbond W83781D, for example, will be
3047# detected as a LM78 too; but as the Winbond detection has a higher confidence
3048# factor, you should identify it as a Winbond.
3049
3050# Each function returns a list. The first element is the confidence value;
3051# Each element after it is an SMBus address. In this way, we can detect
3052# chips with several SMBus addresses. The SMBus address for which the
3053# function was called is never returned.
3054
3055# If there are devices which get confused if they are only read from, then
3056# this program will surely confuse them. But we guarantee never to write to
3057# any of these devices.
3058
3059
3060# $_[0]: A reference to the file descriptor to access this chip.
3061#        We may assume an i2c_set_slave_addr was already done.
3062# $_[1]: Address
3063# Returns: undef if not detected, (7) if detected.
3064# Registers used: 0x58
3065sub mtp008_detect
3066{
3067  my ($file,$addr) = @_;
3068  return if (i2c_smbus_read_byte_data($file,0x58)) != 0xac;
3069  return (8);
3070}
3071 
3072# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3073# $_[1]: A reference to the file descriptor to access this chip.
3074#        We may assume an i2c_set_slave_addr was already done.
3075# $_[2]: Address
3076# Returns: undef if not detected, (6) if detected.
3077# Registers used:
3078#   0x40: Configuration
3079#   0x48: Full I2C Address
3080#   0x49: Device ID
3081# Note that this function is always called through a closure, so the
3082# arguments are shifted by one place.
3083sub lm78_detect
3084{
3085  my $reg;
3086  my ($chip,$file,$addr) = @_;
3087  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
3088  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
3089  $reg = i2c_smbus_read_byte_data($file,0x49);
3090  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
3091                    ($chip == 1 and $reg == 0x40) or
3092                    ($chip == 2 and ($reg & 0xfe) == 0xc0);
3093  return (6);
3094}
3095
3096# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3097# $_[1]: Address
3098# Returns: undef if not detected, 6 if detected.
3099# Note: Only address 0x290 is scanned at this moment.
3100sub lm78_isa_detect
3101{
3102  my ($chip,$addr) = @_ ;
3103  my $val = inb ($addr + 1);
3104  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
3105            inb ($addr + 7) != $val;
3106
3107  $val = inb($addr + 5) & 0x7f;
3108  outb($addr + 5, ~$val & 0xff);
3109  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
3110    outb($addr+5,$val);
3111    return;
3112  }
3113  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
3114  return unless (&$readproc(0x40) & 0x80) == 0x00;
3115  my $reg = &$readproc(0x49);
3116  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
3117                ($chip == 1 and $reg == 0x40) or
3118                ($chip == 2 and ($reg & 0xfe) == 0xc0);
3119
3120  # Explicitely prevent misdetection of Winbond chips
3121  $reg = &$readproc(0x4f);
3122  return if $reg == 0xa3 || $reg == 0x5c;
3123
3124  # Explicitely prevent misdetection of ITE chips
3125  $reg = &$readproc(0x58);
3126  return if $reg == 0x90;
3127
3128  return 6;
3129}
3130
3131
3132# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3133# $_[1]: ISA address
3134# $_[2]: I2C file handle
3135# $_[3]: I2C address
3136sub lm78_alias_detect
3137{
3138  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
3139  my $i;
3140  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
3141  return 0 unless &$readproc(0x48) == $i2c_addr;
3142  for ($i = 0x2b; $i <= 0x3d; $i ++) {
3143    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
3144  }
3145  return 1;
3146}
3147
3148# $_[0]: A reference to the file descriptor to access this chip.
3149#        We assume an i2c_set_slave_addr was already done.
3150# $_[1]: Address
3151# Returns: undef if not detected, 3 or 6 if detected;
3152#   6 means that the temperatures make sense;
3153#   3 means that the temperatures look strange;
3154# Registers used:
3155#   0x00: Temperature
3156#   0x01: Configuration
3157#   0x02: Hysteresis
3158#   0x03: Overtemperature Shutdown
3159#   0x04-0x07: No registers
3160# The first detection step is based on the fact that the LM75 has only
3161# four registers, and cycles addresses over 8-byte boundaries. We use the
3162# 0x04-0x07 addresses (unused) to improve the reliability. These are not
3163# real registers and will always return the last returned value. This isn't
3164# documented.
3165# Note that register 0x00 may change, so we can't use the modulo trick on it.
3166sub lm75_detect
3167{
3168  my $i;
3169  my ($file,$addr) = @_;
3170  my $cur = i2c_smbus_read_word_data($file,0x00);
3171  my $cur_varies = 0;
3172  my $conf = i2c_smbus_read_byte_data($file,0x01);
3173
3174  my $hyst = i2c_smbus_read_word_data($file,0x02);
3175  return if i2c_smbus_read_word_data($file,0x04) != $hyst;
3176  return if i2c_smbus_read_word_data($file,0x05) != $hyst;
3177  return if i2c_smbus_read_word_data($file,0x06) != $hyst;
3178  return if i2c_smbus_read_word_data($file,0x07) != $hyst;
3179
3180  my $os = i2c_smbus_read_word_data($file,0x03);
3181  return if i2c_smbus_read_word_data($file,0x04) != $os;
3182  return if i2c_smbus_read_word_data($file,0x05) != $os;
3183  return if i2c_smbus_read_word_data($file,0x06) != $os;
3184  return if i2c_smbus_read_word_data($file,0x07) != $os;
3185
3186  for ($i = 0x00; $i < 0xff; $i += 8) {
3187    return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf;
3188    return if i2c_smbus_read_word_data($file, $i + 0x02) != $hyst;
3189    return if i2c_smbus_read_word_data($file, $i + 0x04) != $hyst;
3190    return if i2c_smbus_read_word_data($file, $i + 0x05) != $hyst;
3191    return if i2c_smbus_read_word_data($file, $i + 0x06) != $hyst;
3192    return if i2c_smbus_read_word_data($file, $i + 0x07) != $hyst;
3193    return if i2c_smbus_read_word_data($file, $i + 0x03) != $os;
3194    return if i2c_smbus_read_word_data($file, $i + 0x04) != $os;
3195    return if i2c_smbus_read_word_data($file, $i + 0x05) != $os;
3196    return if i2c_smbus_read_word_data($file, $i + 0x06) != $os;
3197    return if i2c_smbus_read_word_data($file, $i + 0x07) != $os;
3198        $cur_varies = 1
3199      if (! $cur_varies) and
3200        i2c_smbus_read_word_data($file, $i) != $cur;
3201  }
3202
3203  # All registers hold the same value, obviously a misdetection
3204  return if (! $cur_varies) and $conf == ($cur & 0xff) and $cur == $hyst
3205    and $cur == $os;
3206
3207  $cur = swap_bytes($cur);
3208  $hyst = swap_bytes($hyst);
3209  $os = swap_bytes($os);
3210  # Unused bits
3211  return if ($conf & 0xe0);
3212
3213  $cur = $cur >> 8;
3214  $hyst = $hyst >> 8;
3215  $os = $os >> 8;
3216  # Most probable value ranges
3217  return 6 if $cur <= 100 and ($hyst >= 10 && $hyst <= 125)
3218    and ($os >= 20 && $os <= 127) and $hyst < $os;
3219  return 3;
3220}
3221
3222# $_[0]: A reference to the file descriptor to access this chip.
3223#        We assume an i2c_set_slave_addr was already done.
3224# $_[1]: Address
3225# Returns: undef if not detected, 3 or 6 if detected;
3226#   6 means that the temperatures make sense;
3227#   3 means that the temperatures look strange;
3228# Registers used:
3229#   0x00: Temperature
3230#   0x01: Configuration
3231#   0x02: Hysteresis
3232#   0x03: Overtemperature Shutdown
3233#   0x04: Low limit
3234#   0x05: High limit
3235#   0x04-0x07: No registers
3236# The first detection step is based on the fact that the LM77 has only
3237# six registers, and cycles addresses over 8-byte boundaries. We use the
3238# 0x06-0x07 addresses (unused) to improve the reliability. These are not
3239# real registers and will always return the last returned value. This isn't
3240# documented.
3241# Note that register 0x00 may change, so we can't use the modulo trick on it.
3242sub lm77_detect
3243{
3244  my $i;
3245  my ($file,$addr) = @_;
3246  my $cur = i2c_smbus_read_word_data($file,0x00);
3247  my $cur_varies = 0;
3248  my $conf = i2c_smbus_read_byte_data($file,0x01);
3249  my $hyst = i2c_smbus_read_word_data($file,0x02);
3250  my $os = i2c_smbus_read_word_data($file,0x03);
3251
3252  my $low = i2c_smbus_read_word_data($file,0x04);
3253  return if i2c_smbus_read_word_data($file,0x06) != $low;
3254  return if i2c_smbus_read_word_data($file,0x07) != $low;
3255
3256  my $high = i2c_smbus_read_word_data($file,0x05);
3257  return if i2c_smbus_read_word_data($file,0x06) != $high;
3258  return if i2c_smbus_read_word_data($file,0x07) != $high;
3259
3260  for ($i = 0x00; $i < 0xff; $i += 8) {
3261    return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf;
3262    return if i2c_smbus_read_word_data($file, $i + 0x02) != $hyst;
3263    return if i2c_smbus_read_word_data($file, $i + 0x03) != $os;
3264    return if i2c_smbus_read_word_data($file, $i + 0x04) != $low;
3265    return if i2c_smbus_read_word_data($file, $i + 0x06) != $low;
3266    return if i2c_smbus_read_word_data($file, $i + 0x07) != $low;
3267    return if i2c_smbus_read_word_data($file, $i + 0x05) != $high;
3268    return if i2c_smbus_read_word_data($file, $i + 0x06) != $high;
3269    return if i2c_smbus_read_word_data($file, $i + 0x07) != $high;
3270    $cur_varies = 1
3271      if (! $cur_varies) and
3272        i2c_smbus_read_word_data($file, $i) != $cur;
3273  }
3274
3275  # All registers hold the same value, obviously a misdetection
3276  return if (! $cur_varies) and $conf == ($cur & 0xff) and $cur == $hyst
3277    and $cur == $os and $cur == $low and $cur == $high;
3278
3279  $cur = swap_bytes($cur);
3280  $os = swap_bytes($os);
3281  $hyst = swap_bytes($hyst);
3282  $low = swap_bytes($low);
3283  $high = swap_bytes($high);
3284  # Unused bits
3285  return if ($conf & 0xe0)
3286    or (($cur >> 12) != 0 && ($cur >> 12) != 0xf)
3287    or (($hyst >> 12) != 0 && ($hyst >> 12) != 0xf)
3288    or (($os >> 12) != 0 && ($os >> 12) != 0xf)
3289    or (($low >> 12) != 0 && ($low >> 12) != 0xf)
3290    or (($high >> 12) != 0 && ($high >> 12) != 0xf);
3291
3292  $cur /= 16;
3293  $hyst /= 16;
3294  $os /= 16;
3295  $high /= 16;
3296  $low /= 16;
3297
3298  # Most probable value ranges
3299  return 6 if $cur <= 100 and $hyst <= 40
3300    and ($os >= 20 && $os <= 127) and ($high >= 20 && $high <= 127);
3301  return 3;
3302}
3303
3304# $_[0]: Chip to detect (0 = LM92, 1 = LM76, 2 = MAX6633/MAX6634/MAX6635)
3305# $_[1]: A reference to the file descriptor to access this chip.
3306#        We may assume an i2c_set_slave_addr was already done.
3307# $_[2]: Address
3308# Returns: undef if not detected, 2 or 4 if detected;
3309# Registers used:
3310#   0x01: Configuration (National Semiconductor only)
3311#   0x02: Hysteresis
3312#   0x03: Critical Temp
3313#   0x04: Low Limit
3314#   0x05: High Limit
3315#   0x07: Manufacturer ID (LM92 only)
3316# One detection step is based on the fact that the LM92 and clones have a
3317# limited number of registers, which cycle modulo 16 address values.
3318# Note that register 0x00 may change, so we can't use the modulo trick on it.
3319sub lm92_detect
3320{
3321  my ($chip, $file, $addr) = @_;
3322
3323  my $conf = i2c_smbus_read_byte_data($file, 0x01);
3324  my $hyst = i2c_smbus_read_word_data($file, 0x02);
3325  my $crit = i2c_smbus_read_word_data($file, 0x03);
3326  my $low = i2c_smbus_read_word_data($file, 0x04);
3327  my $high = i2c_smbus_read_word_data($file, 0x05);
3328
3329  return if $chip == 0
3330        and i2c_smbus_read_word_data($file, 0x07) != 0x0180;
3331 
3332  return if ($chip == 0 || $chip == 1)
3333        and ($conf & 0xE0);
3334
3335  for (my $i = 0; $i < 8; $i++) {
3336    return if i2c_smbus_read_byte_data($file, $i*16+0x01) != $conf;
3337    return if i2c_smbus_read_word_data($file, $i*16+0x02) != $hyst;
3338    return if i2c_smbus_read_word_data($file, $i*16+0x03) != $crit;
3339    return if i2c_smbus_read_word_data($file, $i*16+0x04) != $low;
3340    return if i2c_smbus_read_word_data($file, $i*16+0x05) != $high;
3341  }
3342 
3343  foreach my $temp ($hyst, $crit, $low, $high) {
3344    return if $chip == 2 and ($temp & 0x7F00);
3345    return if $chip != 2 and ($temp & 0x0700);
3346  }
3347
3348  return 4 if $chip == 0;
3349  return 2;
3350}
3351 
3352# $_[0]: A reference to the file descriptor to access this chip.
3353#        We may assume an i2c_set_slave_addr was already done.
3354# $_[1]: Address
3355# Returns: undef if not detected, 3 if detected
3356# Registers used:
3357#   0xAA: Temperature
3358#   0xA1: High limit
3359#   0xA2: Low limit
3360#   0xAC: Configuration
3361# Detection is weak. We check if bit 4 (NVB) is clear, because it is
3362# unlikely to be set (would mean that EEPROM is currently being accessed).
3363# Temperature checkings will hopefully prevent LM75 or other chips from
3364# being detected as a DS1621.
3365sub ds1621_detect
3366{
3367  my $i;
3368  my ($file,$addr) = @_;
3369  my $temp = i2c_smbus_read_word_data($file,0xAA);
3370  my $high = i2c_smbus_read_word_data($file,0xA1);
3371  my $low = i2c_smbus_read_word_data($file,0xA2);
3372  return if ($temp | $high | $low) & 0x7F00;
3373  my $conf = i2c_smbus_read_byte_data($file,0xAC);
3374  return if ($temp == 0 && $high == 0 && $low == 0 && $conf == 0);
3375  return 3 if ($conf & 0x10) == 0x00;
3376  return;
3377}
3378
3379# $_[0]: A reference to the file descriptor to access this chip.
3380#        We may assume an i2c_set_slave_addr was already done.
3381# $_[1]: Address
3382# Returns: undef if not detected, 1 to 3 if detected.
3383# Registers used:
3384#   0x00: Configuration register
3385#   0x02: Interrupt state register
3386#   0x2a-0x3d: Limits registers
3387# This one is easily misdetected since it doesn't provide identification
3388# registers. So we have to use some tricks:
3389#   - 6-bit addressing, so limits readings modulo 0x40 should be unchanged
3390#   - positive temperature limits
3391#   - limits order correctness
3392# Hopefully this should limit the rate of false positives, without increasing
3393# the rate of false negatives.
3394# Thanks to Lennard Klein for testing on a non-LM80 chip, which was
3395# previously misdetected, and isn't anymore. For reference, it scored
3396# a final confidence of 0, and changing from strict limit comparisons
3397# to loose comparisons did not change the score.
3398sub lm80_detect
3399{
3400  my ($i,$reg);
3401  my ($file,$addr) = @_;
3402
3403  return if (i2c_smbus_read_byte_data($file,0x00) & 0x80) != 0;
3404  return if (i2c_smbus_read_byte_data($file,0x02) & 0xc0) != 0;
3405
3406  for ($i = 0x2a; $i <= 0x3d; $i++) {
3407    $reg = i2c_smbus_read_byte_data($file,$i);
3408    return if i2c_smbus_read_byte_data($file,$i+0x40) != $reg;
3409    return if i2c_smbus_read_byte_data($file,$i+0x80) != $reg;
3410    return if i2c_smbus_read_byte_data($file,$i+0xc0) != $reg;
3411  }
3412 
3413  # Refine a bit by checking wether limits are in the correct order
3414  # (min<max for voltages, hyst<max for temperature). Since it is still
3415  # possible that the chip is an LM80 with limits not properly set,
3416  # a few "errors" are tolerated.
3417  my $confidence = 0;
3418  for ($i = 0x2a; $i <= 0x3a; $i++) {
3419    $confidence++
3420      if i2c_smbus_read_byte_data($file,$i) < i2c_smbus_read_byte_data($file,$i+1);
3421  }
3422  # hot temp<OS temp
3423  $confidence++
3424    if i2c_smbus_read_byte_data($file,0x38) < i2c_smbus_read_byte_data($file,0x3a);
3425
3426  # Negative temperature limits are unlikely.
3427  for ($i = 0x3a; $i <= 0x3d; $i++) {
3428    $confidence++ if (i2c_smbus_read_byte_data($file,$i) & 0x80) == 0;
3429  }
3430
3431  # $confidence is between 0 and 14
3432  $confidence = ($confidence >> 1) - 4;
3433  # $confidence is now between -4 and 3
3434
3435  return unless $confidence > 0;
3436
3437  return $confidence;
3438}
3439
3440# $_[0]: Chip to detect
3441#   (0 = LM82/LM83)
3442# $_[1]: A reference to the file descriptor to access this chip.
3443#        We may assume an i2c_set_slave_addr was already done.
3444# $_[2]: Address
3445# Returns: undef if not detected, 4 to 8 if detected.
3446# Registers used:
3447#   0x02: Status 1
3448#   0x03: Configuration
3449#   0x04: Company ID of LM84
3450#   0x35: Status 2
3451#   0xfe: Manufacturer ID
3452#   0xff: Chip ID / die revision
3453# We can use the LM84 Company ID register because the LM83 and the LM82 are
3454# compatible with the LM84.
3455# The LM83 chip ID is missing from the datasheet and was contributed by
3456# Magnus Forsstrom: 0x03.
3457# At least some revisions of the LM82 seem to be repackaged LM83, so they
3458# have the same chip ID, and temp2/temp4 will be stuck in "OPEN" state.
3459# For this reason, we don't even try to distinguish between both chips.
3460# Thanks to Ben Gardner for reporting.
3461sub lm83_detect
3462{
3463  my ($chip, $file) = @_;
3464  return if i2c_smbus_read_byte_data($file,0xfe) != 0x01;
3465  my $chipid = i2c_smbus_read_byte_data($file,0xff);
3466  return if $chipid != 0x01 && $chipid != 0x03;
3467
3468  my $confidence = 4;
3469  $confidence++
3470    if (i2c_smbus_read_byte_data($file,0x02) & 0xa8) == 0x00;
3471  $confidence++
3472    if (i2c_smbus_read_byte_data($file,0x03) & 0x41) == 0x00;
3473  $confidence++
3474    if i2c_smbus_read_byte_data($file,0x04) == 0x00;
3475  $confidence++
3476    if (i2c_smbus_read_byte_data($file,0x35) & 0x48) == 0x00;
3477
3478  return $confidence;
3479}
3480
3481# $_[0]: Chip to detect
3482#   (0 = LM90, 1=LM89/LM99, 2=LM86, 3=ADM1032, 4=MAX6657/MAX6658/MAX6659,
3483#    5 = ADT7461)
3484# $_[1]: A reference to the file descriptor to access this chip.
3485#        We may assume an i2c_set_slave_addr was already done.
3486# $_[2]: Address
3487# Returns: undef if not detected, 4, 6 or 8 if detected.
3488#   The Maxim chips have a low confidence value (4)
3489#   because they don't have a die revision register.
3490# Registers used:
3491#   0x03: Configuration
3492#   0x04: Conversion rate
3493#   0xfe: Manufacturer ID
3494#   0xff: Chip ID / die revision
3495sub lm90_detect
3496{
3497  my ($chip, $file, $addr) = @_;
3498  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
3499  my $cid = i2c_smbus_read_byte_data($file, 0xff);
3500  my $conf = i2c_smbus_read_byte_data($file, 0x03);
3501  my $rate = i2c_smbus_read_byte_data($file, 0x04);
3502
3503  if ($chip == 0) {
3504    return if ($conf & 0x2a) != 0;
3505    return if $rate > 0x09;
3506    return if $mid != 0x01;     # National Semiconductor
3507    return 8 if $cid == 0x21;   # LM90
3508    return 6 if ($cid & 0x0f) == 0x20;
3509  }
3510  if ($chip == 1) {
3511    return if ($conf & 0x2a) != 0;
3512    return if $rate > 0x09;
3513    return if $mid != 0x01;     # National Semiconductor
3514    return 8 if $addr == 0x4c and $cid == 0x31; # LM89/LM99
3515    return 8 if $addr == 0x4d and $cid == 0x34; # LM89-1/LM99-1
3516    return 6 if ($cid & 0x0f) == 0x30;
3517  }
3518  if ($chip == 2) {
3519    return if ($conf & 0x2a) != 0;
3520    return if $rate > 0x09;
3521    return if $mid != 0x01;     # National Semiconductor
3522    return 8 if $cid == 0x11;   # LM86
3523    return 6 if ($cid & 0xf0) == 0x10;
3524  }
3525  if ($chip == 3) {
3526    return if ($conf & 0x3f) != 0;
3527    return if $rate > 0x0a;
3528    return if $mid != 0x41;     # Analog Devices
3529    return 8 if ($cid & 0xf0) == 0x40; # ADM1032
3530  }
3531  if ($chip == 4) {
3532    return if ($conf & 0x1f) != ($mid & 0x0f); # No low nibble,
3533                                               # returns previous low nibble
3534    return if $rate > 0x09;
3535    return if $mid != 0x4d;     # Maxim
3536    return if $cid != 0x4d;     # No register, returns previous value
3537    return 4;
3538  }
3539  if ($chip == 5) {
3540    return if ($conf & 0x1b) != 0;
3541    return if $rate > 0x0a;
3542    return if $mid != 0x41;     # Analog Devices
3543    return 8 if $cid == 0x61;   # ADT7461
3544  }
3545  return;
3546}
3547
3548# $_[0]: Chip to detect
3549#   (1 = LM63, 2 = F75363SG)
3550# $_[1]: A reference to the file descriptor to access this chip.
3551#        We may assume an i2c_set_slave_addr was already done.
3552# $_[2]: Address (unused)
3553# Returns: undef if not detected, 8 if detected.
3554# Registers used:
3555#   0xfe: Manufacturer ID
3556#   0xff: Chip ID / die revision
3557#   0x03: Configuration (two or three unused bits)
3558#   0x16: Alert mask (two or three unused bits)
3559#   0x03-0x0e: Mirrored registers (five pairs)
3560sub lm63_detect
3561{
3562  my ($chip, $file, $addr) = @_;
3563
3564  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
3565  my $cid = i2c_smbus_read_byte_data($file, 0xff);
3566  my $conf = i2c_smbus_read_byte_data($file, 0x03);
3567  my $mask = i2c_smbus_read_byte_data($file, 0x16);
3568
3569  if ($chip == 1) {
3570    return if $mid != 0x01    # National Semiconductor
3571           || $cid != 0x41;   # LM63
3572    return if ($conf & 0x18) != 0x00
3573           || ($mask & 0xa4) != 0xa4;
3574  } elsif ($chip == 2) {
3575    return if $mid != 0x23    # Fintek
3576           || $cid != 0x20;   # F75363SG
3577    return if ($conf & 0x1a) != 0x00
3578           || ($mask & 0x84) != 0x00; 
3579  }
3580
3581  # For compatibility with the LM86, some registers are mirrored
3582  # to alternative locations
3583  return if $conf != i2c_smbus_read_byte_data($file, 0x09);
3584  foreach my $i (0x04, 0x05, 0x07, 0x08) {
3585    return if i2c_smbus_read_byte_data($file, $i)
3586           != i2c_smbus_read_byte_data($file, $i+6);
3587  }
3588
3589  return 8;
3590}
3591
3592# $_[0]: Chip to detect
3593#   (0 = ADM1029)
3594# $_[1]: A reference to the file descriptor to access this chip.
3595#        We may assume an i2c_set_slave_addr was already done.
3596# $_[2]: Address
3597# Returns: undef if not detected, 3 to 9 if detected.
3598# Registers used:
3599#   0x02, 0x03: Fan support
3600#   0x05: GPIO config
3601#   0x07, 0x08, 0x09: Fan config
3602#   0x0d: Manufacturer ID
3603#   0x0e: Chip ID / die revision
3604sub adm1029_detect
3605{
3606  my ($chip, $file, $addr) = @_;
3607  my $mid = i2c_smbus_read_byte_data($file, 0x0d);
3608  my $cid = i2c_smbus_read_byte_data($file, 0x0e);
3609  my $fansc = i2c_smbus_read_byte_data($file, 0x02);
3610  my $fanss = i2c_smbus_read_byte_data($file, 0x03);
3611  my $gpio = i2c_smbus_read_byte_data($file, 0x05);
3612  my $fanas = i2c_smbus_read_byte_data($file, 0x07);
3613  my $fanhps = i2c_smbus_read_byte_data($file, 0x08);
3614  my $fanfs = i2c_smbus_read_byte_data($file, 0x09);
3615  my $confidence = 3;
3616
3617  if ($chip == 0) {
3618    return if $mid != 0x41;     # Analog Devices
3619    $confidence++ if ($cid & 0xF0) == 0x00; # ADM1029
3620    $confidence+=2 if ($fansc & 0xFC) == 0x00
3621                   && ($fanss & 0xFC) == 0x00;
3622    $confidence+=2 if ($fanas & 0xFC) == 0x00
3623                   && ($fanhps & 0xFC) == 0x00
3624                   && ($fanfs & 0xFC) == 0x00;
3625    $confidence++ if ($gpio & 0x80) == 0x00;
3626    return $confidence;
3627  }
3628  return;
3629}
3630
3631# $_[0]: Chip to detect
3632#   (0 = ADM1030, 1=ADM1031)
3633# $_[1]: A reference to the file descriptor to access this chip.
3634#        We may assume an i2c_set_slave_addr was already done.
3635# $_[2]: Address
3636# Returns: undef if not detected, 3 to 7 (ADM1031) or 9 (ADM1030)
3637#          if detected.
3638# Registers used:
3639#   0x01: Config 2
3640#   0x03: Status 2
3641#   0x0d, 0x0e, 0x0f: Temperature offsets
3642#   0x22: Fan speed config
3643#   0x3d: Chip ID
3644#   0x3e: Manufacturer ID
3645#   0x3f: Die revision
3646sub adm1031_detect
3647{
3648  my ($chip, $file, $addr) = @_;
3649  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3650  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3651  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3652  my $conf2 = i2c_smbus_read_byte_data($file, 0x01);
3653  my $stat2 = i2c_smbus_read_byte_data($file, 0x03);
3654  my $fsc = i2c_smbus_read_byte_data($file, 0x22);
3655  my $lto = i2c_smbus_read_byte_data($file, 0x0d);
3656  my $r1to = i2c_smbus_read_byte_data($file, 0x0e);
3657  my $r2to = i2c_smbus_read_byte_data($file, 0x0f);
3658  my $confidence = 3;
3659
3660  if ($chip == 0) {
3661    return if $mid != 0x41;     # Analog Devices
3662    return if $cid != 0x30;     # ADM1030
3663    $confidence++ if ($drev & 0x70) == 0x00;
3664    $confidence++ if ($conf2 & 0x4A) == 0x00;
3665    $confidence++ if ($stat2 & 0x3F) == 0x00;
3666    $confidence++ if ($fsc & 0xF0) == 0x00;
3667    $confidence++ if ($lto & 0x70) == 0x00;
3668    $confidence++ if ($r1to & 0x70) == 0x00;
3669    return $confidence;
3670  }
3671  if ($chip == 1) {
3672    return if $mid != 0x41;     # Analog Devices
3673    return if $cid != 0x31;     # ADM1031
3674    $confidence++ if ($drev & 0x70) == 0x00;
3675    $confidence++ if ($lto & 0x70) == 0x00;
3676    $confidence++ if ($r1to & 0x70) == 0x00;
3677    $confidence++ if ($r2to & 0x70) == 0x00;
3678    return $confidence;
3679  }
3680  return;
3681}
3682
3683# $_[0]: Chip to detect
3684#   (0 = ADM1033, 1 = ADM1034)
3685# $_[1]: A reference to the file descriptor to access this chip.
3686# $_[2]: Address (unused)
3687# Returns: undef if not detected, 4 or 6 if detected.
3688# Registers used:
3689#   0x3d: Chip ID
3690#   0x3e: Manufacturer ID
3691#   0x3f: Die revision
3692sub adm1034_detect
3693{
3694  my ($chip, $file, $addr) = @_;
3695  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3696  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3697  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3698
3699  if ($chip == 0) {
3700    return if $mid != 0x41;     # Analog Devices
3701    return if $cid != 0x33;     # ADM1033
3702    return if ($drev & 0xf8) != 0x00;
3703    return 6 if $drev == 0x02;
3704    return 4;
3705  }
3706  if ($chip == 1) {
3707    return if $mid != 0x41;     # Analog Devices
3708    return if $cid != 0x34;     # ADM1034
3709    return if ($drev & 0xf8) != 0x00;
3710    return 6 if $drev == 0x02;
3711    return 4;
3712  }
3713  return
3714}
3715
3716# $_[0]: Chip to detect
3717#   (0 = ADT7467/ADT7468, 1 = ADT7476, 2 = ADT7462, 3 = ADT7466,
3718#    4 = ADT7470)
3719# $_[1]: A reference to the file descriptor to access this chip.
3720#        We may assume an i2c_set_slave_addr was already done.
3721# $_[2]: Address
3722# Returns: undef if not detected, 5 or 7 if detected.
3723# Registers used:
3724#   0x3d: Chip ID
3725#   0x3e: Manufacturer ID
3726#   0x3f: Die revision
3727sub adt7467_detect
3728{
3729  my ($chip, $file, $addr) = @_;
3730  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3731  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3732  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3733
3734  if ($chip == 0) {
3735    return if $mid != 0x41;     # Analog Devices
3736    return if $cid != 0x68;     # ADT7467
3737    return if ($drev & 0xf0) != 0x70;
3738    return 7 if ($drev == 0x71 || $drev == 0x72);
3739    return 5;
3740  }
3741  if ($chip == 1) {
3742    return if $mid != 0x41;     # Analog Devices
3743    return if $cid != 0x76;     # ADT7476
3744    return if ($drev & 0xf0) != 0x60;
3745    return 7 if ($drev == 0x69);
3746    return 5;
3747  }
3748  if ($chip == 2) {
3749    return if $mid != 0x41;     # Analog Devices
3750    return if $cid != 0x62;     # ADT7462
3751    return if ($drev & 0xf0) != 0x00;
3752    return 7 if ($drev == 0x04);
3753    return 5;
3754  }
3755  if ($chip == 3) {
3756    return if $mid != 0x41;     # Analog Devices
3757    return if $cid != 0x66;     # ADT7466
3758    return if ($drev & 0xf0) != 0x00;
3759    return 7 if ($drev == 0x02);
3760    return 5;
3761  }
3762  if ($chip == 4) {
3763    return if $mid != 0x41;     # Analog Devices
3764    return if $cid != 0x70;     # ADT7470
3765    return if ($drev & 0xf0) != 0x00;
3766    return 7 if ($drev == 0x00);
3767    return 5;
3768  }
3769  return
3770}
3771
3772# $_[0]: Chip to detect
3773#   (0 = ADT7473, 1 = ADT7475)
3774# $_[1]: A reference to the file descriptor to access this chip.
3775# $_[2]: Address (unused)
3776# Returns: undef if not detected, 5 if detected.
3777# Registers used:
3778#   0x3d: Chip ID
3779#   0x3e: Manufacturer ID
3780sub adt7473_detect
3781{
3782  my ($chip, $file, $addr) = @_;
3783  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3784  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3785
3786  if ($chip == 0) {
3787    return if $mid != 0x41;     # Analog Devices
3788    return if $cid != 0x73;     # ADT7473
3789    return 5;
3790  }
3791  if ($chip == 1) {
3792    return if $mid != 0x41;     # Analog Devices
3793    return if $cid != 0x75;     # ADT7475
3794    return 5;
3795  }
3796  return
3797}
3798
3799# $_[0]: Vendor to check for
3800#   (0x01 = National Semi, 0x41 = Analog Dev, 0x5c = SMSC)
3801# $_[1]: A reference to the file descriptor to access this chip.
3802# #_[2]: Base address.
3803# Returns: undef if not detected, (7) or (8) if detected.
3804# Registers used: 0x3e == Vendor register.
3805#                 0x3d == Device ID register (Analog Devices only).
3806#                 0x3f == Version/Stepping register.
3807# Constants used: 0x01 == National Semiconductor Vendor Id.
3808#                 0x41 == Analog Devices Vendor Id.
3809#                 0x5c == SMSC Vendor Id.
3810#                 0x60 == Version number. The lower 4 stepping
3811#                         bits are masked and ignored.
3812sub lm85_detect
3813{
3814  my ($vendor,$file,$addr) = @_;
3815  return if (i2c_smbus_read_byte_data($file,0x3e)) != $vendor ;
3816  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) != 0x60;
3817
3818  if ($vendor == 0x41) # Analog Devices
3819  {
3820    return if i2c_smbus_read_byte_data($file, 0x3d) != 0x27;
3821    return (8);
3822  }
3823
3824  return (7);
3825}
3826
3827# $_[0]: A reference to the file descriptor to access this chip.
3828#        We may assume an i2c_set_slave_addr was already done.
3829# $_[1]: Address
3830# Returns: undef if not detected, (7) if detected.
3831# Registers used: 0x3E, 0x3F
3832#        Assume lower 2 bits of reg 0x3F are for revisions.
3833sub lm87_detect
3834{
3835  my ($file,$addr) = @_;
3836  return if (i2c_smbus_read_byte_data($file,0x3e)) != 0x02;
3837  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xfc) != 0x04;
3838  return (7);
3839}
3840 
3841# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S,
3842#                        3 = W83627HF, 4 = AS99127F (rev.1),
3843#                        5 = AS99127F (rev.2), 6 = ASB100, 7 = W83791D,
3844#                        8 = W83792D, 9 = W83627EHF 10 = W83627DHG)
3845# $_[1]: A reference to the file descriptor to access this chip.
3846#        We may assume an i2c_set_slave_addr was already done.
3847# $_[2]: Address
3848# Returns: undef if not detected, (8,addr1,addr2) if detected, but only
3849#          if the LM75 chip emulation is enabled.
3850# Registers used:
3851#   0x48: Full I2C Address
3852#   0x4a: I2C addresses of emulated LM75 chips
3853#   0x4e: Vendor ID byte selection, and bank selection
3854#   0x4f: Vendor ID
3855#   0x58: Device ID (only when in bank 0)
3856# Note: Fails if the W8378xD is not in bank 0!
3857# Note: Detection overrules a previous LM78 detection
3858# Note: Asus chips do not have their I2C address at register 0x48?
3859#       AS99127F rev.1 and ASB100 have 0x00, confirmation wanted for
3860#       AS99127F rev.2.
3861sub w83781d_detect
3862{
3863  my ($reg1,$reg2,@res);
3864  my ($chip,$file,$addr) = @_;
3865
3866  return unless (i2c_smbus_read_byte_data($file,0x48) == $addr)
3867    or ($chip >= 4 && $chip <= 6);
3868
3869  $reg1 = i2c_smbus_read_byte_data($file,0x4e);
3870  $reg2 = i2c_smbus_read_byte_data($file,0x4f);
3871  if ($chip == 4) { # Asus AS99127F (rev.1)
3872    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or 
3873                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x12);
3874  } elsif ($chip == 6) { # Asus ASB100
3875    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0x94) or 
3876                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x06);
3877  } else { # Winbond and Asus AS99127F (rev.2)
3878    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
3879                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
3880  }
3881
3882  return unless ($reg1 & 0x07) == 0x00;
3883
3884  $reg1 = i2c_smbus_read_byte_data($file,0x58);
3885  return if $chip == 0 and ($reg1 != 0x10 && $reg1 != 0x11);
3886  return if $chip == 1 and  $reg1 != 0x30;
3887  return if $chip == 2 and  $reg1 != 0x40;
3888  return if $chip == 3 and  $reg1 != 0x21;
3889  return if $chip == 4 and  $reg1 != 0x31;
3890  return if $chip == 5 and  $reg1 != 0x31;
3891  return if $chip == 6 and  $reg1 != 0x31;
3892  return if $chip == 7 and  $reg1 != 0x71;
3893  return if $chip == 8 and  $reg1 != 0x7a;
3894  return if $chip == 9 and  $reg1 != 0xa1;
3895  return if $chip == 10 and  $reg1 != 0xa2;
3896  $reg1 = i2c_smbus_read_byte_data($file,0x4a);
3897  # Default address is 0x2d
3898  @res = ($addr != 0x2d) ? (7) : (8);
3899  return @res if $chip == 9; # No subclients
3900  push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08;
3901  push @res, (($reg1 & 0x70) >> 4) + 0x48 unless ($reg1 & 0x80 or $chip == 2);
3902  return @res;
3903}
3904 
3905# $_[0]: Chip to detect (0 = W83793)
3906# $_[1]: A reference to the file descriptor to access this chip.
3907# $_[2]: Address
3908# Returns: undef if not detected
3909#          6 if detected and bank different from 0
3910#          (8,addr1,addr2) if detected, band is 0 and LM75 chip emulation
3911#          is enabled
3912# Registers used:
3913#   0x0b: Full I2C Address
3914#   0x0c: I2C addresses of emulated LM75 chips
3915#   0x00: Vendor ID byte selection, and bank selection(Bank 0,1,2)
3916#   0x0d: Vendor ID(Bank 0,1,2)
3917#   0x0e: Device ID(Bank 0,1,2)
3918sub w83793_detect
3919{
3920  my ($bank, $reg, @res);
3921  my ($chip, $file, $addr) = @_;
3922
3923  $bank = i2c_smbus_read_byte_data($file, 0x00);
3924  $reg = i2c_smbus_read_byte_data($file, 0x0d);
3925
3926  return unless (($bank & 0x80) == 0x00 and $reg == 0xa3) or 
3927                (($bank & 0x80) == 0x80 and $reg == 0x5c);
3928
3929  $reg = i2c_smbus_read_byte_data($file, 0x0e);
3930  return if $chip == 0 and $reg != 0x7b;
3931
3932# If bank 0 is selected, we can do more checks
3933  return 6 unless ($bank & 0x07) == 0;
3934  $reg = i2c_smbus_read_byte_data($file, 0x0b);
3935  return unless ($reg == ($addr << 1));
3936
3937  $reg = i2c_smbus_read_byte_data($file, 0x0c);
3938  @res = (8);
3939  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08;
3940  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
3941  return @res;
3942}
3943
3944# $_[0]: A reference to the file descriptor to access this chip.
3945#        We assume an i2c_set_slave_addr was already done.
3946# $_[1]: Address
3947# Returns: undef if not detected, 3 if detected
3948# Registers used:
3949#   0x48: Full I2C Address
3950#   0x4e: Vendor ID byte selection
3951#   0x4f: Vendor ID
3952#   0x58: Device ID
3953# Note that the datasheet was useless and this detection routine
3954# is based on dumps we received from users. Also, the W83781SD is *NOT*
3955# a hardware monitoring chip as far as we know, but we still want to
3956# detect it so that people won't keep reporting it as an unknown chip
3957# we should investigate about.
3958sub w83791sd_detect
3959{
3960  my ($file, $addr) = @_;
3961  my ($reg1, $reg2);
3962
3963  return unless (i2c_smbus_read_byte_data($file, 0x48) == $addr);
3964
3965  $reg1 = i2c_smbus_read_byte_data($file, 0x4e);
3966  $reg2 = i2c_smbus_read_byte_data($file, 0x4f);
3967  return unless (!($reg1 & 0x80) && $reg2 == 0xa3)
3968             || (($reg1 & 0x80) && $reg2 == 0x5c);
3969
3970  $reg1 = i2c_smbus_read_byte_data($file, 0x58);
3971  return unless $reg1 == 0x72;
3972
3973  return 3;
3974}
3975
3976# $_[0]: Chip to detect (0 = ASM58, 1 = AS2K129R, 2 = ???)
3977# $_[1]: A reference to the file descriptor to access this chip
3978# $_[2]: Address (unused)
3979# Returns: undef if not detected, 5 if detected
3980# Registers used:
3981#   0x4e: Vendor ID high byte
3982#   0x4f: Vendor ID low byte
3983#   0x58: Device ID
3984# Note: The values were given by Alex van Kaam, we don't have datasheets
3985#       to confirm.
3986sub mozart_detect
3987{
3988  my ($vid,$dev);
3989  my ($chip,$file,$addr) = @_;
3990
3991  $vid = (i2c_smbus_read_byte_data($file,0x4e) << 8)
3992       +  i2c_smbus_read_byte_data($file,0x4f);
3993  $dev = i2c_smbus_read_byte_data($file,0x58);
3994
3995  return if ($chip == 0) and ($dev != 0x56 || $vid != 0x9436);
3996  return if ($chip == 1) and ($dev != 0x56 || $vid != 0x9406);
3997  return if ($chip == 2) and ($dev != 0x10 || $vid != 0x5ca3);
3998
3999  return 5;
4000}
4001
4002# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF,
4003#                        9 = W83627EHF 10 = W83627DHG)
4004# $_[1]: ISA address
4005# $_[2]: I2C file handle
4006# $_[3]: I2C address
4007sub w83781d_alias_detect
4008{
4009  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
4010  my $i;
4011  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
4012  return 0 unless &$readproc(0x48) == $i2c_addr;
4013  for ($i = 0x2b; $i <= 0x3d; $i ++) {
4014    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
4015  }
4016  return 1;
4017}
4018
4019# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF)
4020# $_[1]: Address
4021# Returns: undef if not detected, (8) if detected.
4022sub w83781d_isa_detect
4023{
4024  my ($chip,$addr) = @_ ;
4025  my ($reg1,$reg2);
4026  my $val = inb ($addr + 1);
4027  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
4028            inb ($addr + 7) != $val;
4029
4030  $val = inb($addr + 5) & 0x7f;
4031  outb($addr+5, ~$val & 0xff);
4032  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
4033    outb($addr+5,$val);
4034    return;
4035  }
4036
4037  my $read_proc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
4038  $reg1 = &$read_proc(0x4e);
4039  $reg2 = &$read_proc(0x4f);
4040  return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
4041                (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
4042  return unless ($reg1 & 0x07) == 0x00;
4043  $reg1 = &$read_proc(0x58);
4044  return if $chip == 0 and  ($reg1 & 0xfe) != 0x10;
4045  return if $chip == 1 and  ($reg1 & 0xfe) != 0x30;
4046  return if $chip == 3 and  ($reg1 & 0xfe) != 0x20;
4047
4048  return 8;
4049}
4050
4051# $_[0]: Chip to detect (0 = Revision 0x00, 1 = Revision 0x80)
4052# $_[1]: A reference to the file descriptor to access this chip.
4053#        We may assume an i2c_set_slave_addr was already done.
4054# $_[2]: Address
4055# Returns: undef if not detected, (6) if detected.
4056# Registers used:
4057#   0x00: Device ID
4058#   0x01: Revision ID
4059#   0x03: Configuration
4060# Mediocre detection
4061sub gl518sm_detect
4062{
4063  my $reg;
4064  my ($chip,$file,$addr) = @_;
4065  return unless i2c_smbus_read_byte_data($file,0x00) == 0x80;
4066  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
4067  $reg = i2c_smbus_read_byte_data($file,0x01);
4068  return unless ($chip == 0 and $reg == 0x00) or
4069                ($chip == 1 and $reg == 0x80);
4070  return (6);
4071}
4072
4073# $_[0]: A reference to the file descriptor to access this chip.
4074#        We may assume an i2c_set_slave_addr was already done.
4075# $_[1]: Address
4076# Returns: undef if not detected, (5) if detected.
4077# Registers used:
4078#   0x00: Device ID
4079#   0x01: Revision ID
4080#   0x03: Configuration
4081# Mediocre detection
4082sub gl520sm_detect
4083{
4084  my ($file,$addr) = @_;
4085  return unless i2c_smbus_read_byte_data($file,0x00) == 0x20;
4086  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
4087  # The line below must be better checked before I dare to use it.
4088  # return unless i2c_smbus_read_byte_data($file,0x01) == 0x00;
4089  return (5);
4090}
4091
4092# $_[0]: A reference to the file descriptor to access this chip.
4093#        We may assume an i2c_set_slave_addr was already done.
4094# $_[1]: Address
4095# Returns: undef if not detected, (5) if detected.
4096# Registers used:
4097#   0x00: Device ID
4098# Mediocre detection
4099sub gl525sm_detect
4100{
4101  my ($file,$addr) = @_;
4102  return unless i2c_smbus_read_byte_data($file,0x00) == 0x25;
4103  return (5);
4104}
4105
4106# $_[0]: Chip to detect (0 = ADM9240, 1 = DS1780, 2 = LM81)
4107# $_[1]: A reference to the file descriptor to access this chip.
4108#        We may assume an i2c_set_slave_addr was already done.
4109# $_[2]: Address
4110# Returns: undef if not detected, (7) if detected.
4111# Registers used:
4112#   0x3e: Company ID
4113#   0x40: Configuration
4114#   0x48: Full I2C Address
4115# Note: Detection overrules a previous LM78 detection
4116sub adm9240_detect
4117{
4118  my $reg;
4119  my ($chip, $file,$addr) = @_;
4120  $reg = i2c_smbus_read_byte_data($file,0x3e);
4121  return unless ($chip == 0 and $reg == 0x23) or
4122                ($chip == 1 and $reg == 0xda) or
4123                ($chip == 2 and $reg == 0x01);
4124  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4125  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
4126 
4127  return (7);
4128}
4129
4130# $_[0]: Chip to detect (0 = ADM1022, 1 = THMC50, 2 = ADM1028)
4131# $_[1]: A reference to the file descriptor to access this chip.
4132#        We may assume an i2c_set_slave_addr was already done.
4133# $_[2]: Address
4134# Returns: undef if not detected, (8) if detected.
4135# Registers used:
4136#   0x3e: Company ID
4137#   0x3f: Revision
4138#   0x40: Configuration
4139# Note: Detection overrules a previous LM78 or ADM9240 detection
4140sub adm1022_detect
4141{
4142  my $reg;
4143  my ($chip, $file,$addr) = @_;
4144  $reg = i2c_smbus_read_byte_data($file,0x3e);
4145  return unless ($chip == 0 and $reg == 0x41) or
4146                ($chip == 1 and $reg == 0x49) or
4147                ($chip == 2 and $reg == 0x41);
4148  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4149  $reg = i2c_smbus_read_byte_data($file, 0x3f);
4150  return unless ($reg & 0xc0) == 0xc0;
4151  return if $chip == 0 and ($reg & 0xc0) != 0xc0;
4152  return if $chip == 2 and ($reg & 0xc0) == 0xc0;
4153  return (8);
4154}
4155
4156# $_[0]: Chip to detect (0 = ADM1025, 1 = NE1619)
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
4165#   0x41: Status 1
4166#   0x42: Status 2
4167# Note: Detection overrules a previous LM78 or ADM9240 detection
4168sub adm1025_detect
4169{
4170  my $reg;
4171  my ($chip, $file,$addr) = @_;
4172
4173  $reg = i2c_smbus_read_byte_data($file,0x3e);
4174  return if ($chip == 0) and ($reg != 0x41);
4175  return if ($chip == 1) and ($reg != 0xA1);
4176
4177  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4178  return unless (i2c_smbus_read_byte_data($file,0x41) & 0xC0) == 0x00;
4179  return unless (i2c_smbus_read_byte_data($file,0x42) & 0xBC) == 0x00;
4180  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x20;
4181
4182  return (8);
4183}
4184
4185# $_[0]: Chip to detect (0 = ADM1026)
4186# $_[1]: A reference to the file descriptor to access this chip.
4187#        We may assume an i2c_set_slave_addr was already done.
4188# $_[2]: Address
4189# Returns: undef if not detected, (8) if detected.
4190# Registers used:
4191#   0x16: Company ID
4192#   0x17: Revision
4193sub adm1026_detect
4194{
4195  my $reg;
4196  my ($chip, $file,$addr) = @_;
4197  $reg = i2c_smbus_read_byte_data($file,0x16);
4198  return unless ($reg == 0x41);
4199  return unless (i2c_smbus_read_byte_data($file,0x17) & 0xf0) == 0x40;
4200  return (8);
4201}
4202
4203# $_[0]: Chip to detect (0 = ADM1024)
4204# $_[1]: A reference to the file descriptor to access this chip.
4205#        We may assume an i2c_set_slave_addr was already done.
4206# $_[2]: Address
4207# Returns: undef if not detected, (8) if detected.
4208# Registers used:
4209#   0x3e: Company ID
4210#   0x3f: Revision
4211#   0x40: Configuration
4212sub adm1024_detect
4213{
4214  my $reg;
4215  my ($chip, $file,$addr) = @_;
4216  $reg = i2c_smbus_read_byte_data($file,0x3e);
4217  return unless ($reg == 0x41);
4218  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4219  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x10;
4220  return (8);
4221}
4222
4223# $_[0]: Chip to detect
4224#   (0 = ADM1021, 1 = ADM1021A/ADM1023, 2 = MAX1617, 3 = MAX1617A, 4 = THMC10,
4225#    5 = LM84, 6 = GL523, 7 = MC1066)
4226# $_[1]: A reference to the file descriptor to access this chip.
4227#        We may assume an i2c_set_slave_addr was already done.
4228# $_[2]: Address
4229# Returns: undef if not detected, 3 if simply detected, 5 if detected and
4230#          manufacturer ID matches, 7 if detected and manufacturer ID and
4231#          revision match
4232# Registers used:
4233#   0x04: Company ID (LM84 only)
4234#   0xfe: Company ID (all but LM84 and MAX1617)
4235#   0xff: Revision (ADM1021, ADM1021A/ADM1023 and MAX1617A)
4236#   0x02: Status
4237#   0x03: Configuration
4238#   0x04: Conversion rate
4239#   0x00-0x01, 0x05-0x08: Temperatures (MAX1617 and LM84)
4240# Note: Especially the MAX1617 has very bad detection; we give it a low
4241# confidence value.
4242sub adm1021_detect
4243{
4244  my ($chip, $file, $addr) = @_;
4245  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
4246  my $rev = i2c_smbus_read_byte_data($file, 0xff);
4247  my $conf = i2c_smbus_read_byte_data($file, 0x03);
4248  my $status = i2c_smbus_read_byte_data($file, 0x02);
4249  my $convrate = i2c_smbus_read_byte_data($file, 0x04);
4250
4251  # Check manufacturer IDs and product revisions when available
4252  return if $chip == 0 and $man_id != 0x41 ||
4253                          ($rev & 0xf0) != 0x00;
4254  return if $chip == 1 and $man_id != 0x41 ||
4255                          ($rev & 0xf0) != 0x30;
4256  return if $chip == 3 and $man_id != 0x4d ||
4257                           $rev != 0x01;
4258  return if $chip == 4 and $man_id != 0x49;
4259  return if $chip == 5 and $convrate != 0x00;
4260  return if $chip == 6 and $man_id != 0x23;
4261  return if $chip == 7 and $man_id != 0x54;
4262
4263  # Check unused bits
4264  if ($chip == 5) # LM84
4265  {
4266    return if ($status & 0xab) != 0;
4267    return if ($conf & 0x7f) != 0;
4268  }
4269  else
4270  {
4271    return if ($status & 0x03) != 0;
4272    return if ($conf & 0x3f) != 0;
4273    return if ($convrate & 0xf8) != 0;
4274  }
4275
4276  # Extra checks for MAX1617 and LM84, since those are often misdetected
4277  # We verify several assertions (6 for the MAX1617, 4 for the LM84) and
4278  # discard the chip if any fail. Note that these checks are not done
4279  # by the adm1021 driver.
4280  if ($chip == 2 || $chip == 5)
4281  {
4282    my $lte = i2c_smbus_read_byte_data($file, 0x00);
4283    my $rte = i2c_smbus_read_byte_data($file, 0x01);
4284    my $lhi = i2c_smbus_read_byte_data($file, 0x05);
4285    my $rhi = i2c_smbus_read_byte_data($file, 0x07);
4286    my $llo = i2c_smbus_read_byte_data($file, 0x06);
4287    my $rlo = i2c_smbus_read_byte_data($file, 0x08);
4288
4289    # If all registers hold the same value, it has to be a misdetection
4290    return if $lte == $rte and $lte == $lhi and $lte == $rhi
4291           and $lte == $llo and $lte == $rlo;
4292
4293    # Negative temperatures
4294    return if ($lte & 0x80) or ($rte & 0x80);
4295    # Negative high limits
4296    return if ($lhi & 0x80) or ($rhi & 0x80);
4297    # Low limits over high limits
4298    if ($chip != 5) # LM84 doesn't have low limits
4299    {
4300      $llo-=256 if ($llo & 0x80);
4301      $rlo-=256 if ($rlo & 0x80);
4302      return if ($llo > $lhi) or ($rlo > $rhi);
4303    }
4304  }
4305
4306  return 3 if ($chip == 2) or ($chip == 5);
4307  return 7 if $chip <= 3;
4308  return 5;
4309}
4310
4311# $_[0]: Chip to detect
4312#   (0 = MAX1619)
4313# $_[1]: A reference to the file descriptor to access this chip.
4314#        We may assume an i2c_set_slave_addr was already done.
4315# $_[2]: Address
4316# Returns: undef if not detected, 7 if detected
4317# Registers used:
4318#   0xfe: Company ID
4319#   0xff: Device ID
4320#   0x02: Status
4321#   0x03: Configuration
4322#   0x04: Conversion rate
4323sub max1619_detect
4324{
4325  my ($chip, $file, $addr) = @_;
4326  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
4327  my $dev_id = i2c_smbus_read_byte_data($file, 0xff);
4328  my $conf = i2c_smbus_read_byte_data($file, 0x03);
4329  my $status = i2c_smbus_read_byte_data($file, 0x02);
4330  my $convrate = i2c_smbus_read_byte_data($file, 0x04);
4331
4332  return if $man_id != 0x4D
4333    or $dev_id != 0x04
4334    or ($conf & 0x03)
4335    or ($status & 0x61)
4336    or $convrate >= 8;
4337
4338  return 7;
4339}
4340
4341# $_[0]: A reference to the file descriptor to access this chip.
4342# $_[1]: Address (unused)
4343# Returns: undef if not detected, 6 if detected.
4344# Registers used:
4345#   0x28: User ID
4346#   0x29: User ID2
4347#   0x2A: Version ID
4348
4349sub ite_overclock_detect
4350{
4351  my ($file, $addr) = @_;
4352
4353  my $uid1 = i2c_smbus_read_byte_data($file, 0x28);
4354  my $uid2 = i2c_smbus_read_byte_data($file, 0x29);
4355  return if $uid1 != 0x83
4356         || $uid2 != 0x12;
4357
4358  return 6;
4359}
4360
4361# $_[0]: Chip to detect (0 = IT8712F)
4362# $_[1]: A reference to the file descriptor to access this chip.
4363#        We may assume an i2c_set_slave_addr was already done.
4364# $_[2]: Address
4365# Returns: undef if not detected, 7 or 8 if detected (tops LM78).
4366# Registers used:
4367#   0x00: Configuration
4368#   0x48: Full I2C Address
4369#   0x58: Mfr ID
4370#   0x5b: Device ID (not on IT8705)
4371# Note that this function is always called through a closure, so the
4372# arguments are shifted by one place.
4373sub ite_detect
4374{
4375  my $reg;
4376  my ($chip,$file,$addr) = @_;
4377  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
4378  return unless (i2c_smbus_read_byte_data($file, 0x00) & 0x90) == 0x10;
4379  return unless i2c_smbus_read_byte_data($file,0x58) == 0x90;
4380  return if $chip == 0 and i2c_smbus_read_byte_data($file,0x5b) != 0x12;
4381  return (7 + ($addr == 0x2d));
4382}
4383
4384
4385# $_[0]: Chip to detect (0 = IT8712F)
4386# $_[1]: ISA address
4387# $_[2]: I2C file handle
4388# $_[3]: I2C address
4389sub ite_alias_detect
4390{
4391  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
4392  my $i;
4393  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
4394  return 0 unless &$readproc(0x48) == $i2c_addr;
4395  for ($i = 0x30; $i <= 0x45; $i++) {
4396    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
4397  }
4398  return 1;
4399}
4400
4401# $_[0]: Chip to detect (0 = SPD EEPROM, 1 = Sony Vaio EEPROM,
4402#                        2 = SPD EEPROM with Software Write Protect)
4403# $_[1]: A reference to the file descriptor to access this chip
4404# $_[2]: Address
4405# Returns: 8 for a memory eeprom (9 if write-protect register found),
4406#          4 to 9 for a Sony Vaio eeprom,
4407#          1 for an unknown eeprom (2 if write-protect register found)
4408# Registers used:
4409#   0-63: SPD Data and Checksum
4410#   0x80-0x83: Sony Vaio Data ("PCG-")
4411#   0xe2, 0xe5, 0xe8, 0xeb, Oxee: Sony Vaio Timestamp constant bytes.
4412#   0x1a-0x1c: Sony Vaio MAC address
4413# This detection function is a bit tricky; this is to workaround
4414# wrong misdetection messages that would else arise.
4415sub eeprom_detect
4416{
4417  my ($chip,$file,$addr) = @_;
4418  my $checksum = 0;
4419
4420  # Check the checksum for validity (works for most DIMMs and RIMMs)
4421  if ($chip != 1) {
4422          for (my $i = 0; $i <= 62; $i ++) {
4423            $checksum += i2c_smbus_read_byte_data($file,$i);
4424          }
4425          $checksum &= 255;
4426          $checksum -= i2c_smbus_read_byte_data($file,63);
4427  }     
4428  if ($chip == 0) {
4429        if($checksum == 0) {
4430                return 8;
4431        } else {
4432                return 1;
4433        }
4434  }     
4435  if ($chip == 2) {
4436        # check for 'shadow' write-protect register at 0x30-0x37
4437        # could be dangerous
4438        i2c_set_slave_addr($file,$addr - 0x20);
4439        if(i2c_smbus_write_quick($file, SMBUS_WRITE) >= 0 &&
4440           i2c_smbus_read_byte_data($file,0x80) == -1) {
4441                i2c_set_slave_addr($file,$addr);
4442                if($checksum == 0) {
4443                        return (9, $addr - 0x20);
4444                } else {
4445                        return (2, $addr - 0x20);
4446                }
4447        }
4448        i2c_set_slave_addr($file,$addr);
4449        return;
4450  }
4451
4452  # Look for a Sony Vaio EEPROM ($chip == 1)
4453  my $vaioconf = 1;
4454  $vaioconf += 4
4455    if i2c_smbus_read_byte_data($file,0x80) == 0x50
4456    && i2c_smbus_read_byte_data($file,0x81) == 0x43
4457    && i2c_smbus_read_byte_data($file,0x82) == 0x47
4458    && i2c_smbus_read_byte_data($file,0x83) == 0x2d;
4459  $vaioconf += 5
4460    if i2c_smbus_read_byte_data($file,0xe2) == 0x2f
4461    && i2c_smbus_read_byte_data($file,0xe5) == 0x2f
4462    && i2c_smbus_read_byte_data($file,0xe8) == 0x20
4463    && i2c_smbus_read_byte_data($file,0xeb) == 0x3a
4464    && i2c_smbus_read_byte_data($file,0xee) == 0x3a;
4465  $vaioconf += 3
4466    if i2c_smbus_read_byte_data($file,0x1a) == 0x08
4467    && i2c_smbus_read_byte_data($file,0x1b) == 0x00
4468    && i2c_smbus_read_byte_data($file,0x1c) == 0x46;
4469  $vaioconf = 9
4470    if $vaioconf > 9;
4471
4472  if ($vaioconf > 1) {
4473    return $vaioconf;
4474  }
4475  return;
4476}
4477
4478# $_[0]: A reference to the file descriptor to access this chip.
4479#        We may assume an i2c_set_slave_addr was already done.
4480# $_[1]: Address
4481# Returns: undef if not detected, (1) if detected.
4482# Registers used:
4483#   0x00..0x07: DDC signature
4484#   0x08..0x7E: checksumed area
4485#   0x7F:       checksum
4486sub ddcmonitor_detect
4487{
4488  my ($file,$addr) = @_;
4489  my $i;
4490
4491  return unless
4492    i2c_smbus_read_byte_data($file,0x00) == 0x00 and
4493    i2c_smbus_read_byte_data($file,0x01) == 0xFF and
4494    i2c_smbus_read_byte_data($file,0x02) == 0xFF and
4495    i2c_smbus_read_byte_data($file,0x03) == 0xFF and
4496    i2c_smbus_read_byte_data($file,0x04) == 0xFF and
4497    i2c_smbus_read_byte_data($file,0x05) == 0xFF and
4498    i2c_smbus_read_byte_data($file,0x06) == 0xFF and
4499    i2c_smbus_read_byte_data($file,0x07) == 0x00;
4500
4501  # Check the checksum for validity.
4502  my $checksum = 0;
4503  for ($i = 0; $i <= 127; $i = $i + 1) {
4504    $checksum = $checksum + i2c_smbus_read_byte_data($file,$i);
4505  }
4506  $checksum=$checksum & 255;
4507  if ($checksum != 0) {
4508    # I have one such monitor...
4509    return (2,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
4510  }
4511  return (8,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
4512}
4513
4514# $_[0]: A reference to the file descriptor to access this chip.
4515#        We may assume an i2c_set_slave_addr was already done.
4516# $_[1]: Address
4517# Returns: undef if not detected, (8) if detected.
4518# Registers used:
4519#   0x00-0x02: Identification ('P','E','G' -> Pegasus ? :-)
4520sub fscpos_detect
4521{
4522  my ($file,$addr) = @_;
4523  # check the first 3 registers
4524  if (i2c_smbus_read_byte_data($file,0x00) != 0x50) {
4525        return;
4526  }
4527  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
4528        return;
4529  }
4530  if (i2c_smbus_read_byte_data($file,0x02) != 0x47) {
4531        return;
4532  }
4533  return (8);
4534}
4535
4536# $_[0]: A reference to the file descriptor to access this chip.
4537#        We may assume an i2c_set_slave_addr was already done.
4538# $_[1]: Address
4539# Returns: undef if not detected, (8) if detected.
4540# Registers used:
4541#   0x00-0x02: Identification ('S','C','Y')
4542sub fscscy_detect
4543{
4544  my ($file,$addr) = @_;
4545  # check the first 3 registers
4546  if (i2c_smbus_read_byte_data($file,0x00) != 0x53) {
4547        return;
4548  }
4549  if (i2c_smbus_read_byte_data($file,0x01) != 0x43) {
4550        return;
4551  }
4552  if (i2c_smbus_read_byte_data($file,0x02) != 0x59) {
4553        return;
4554  }
4555  return (8);
4556}
4557
4558# $_[0]: A reference to the file descriptor to access this chip.
4559#        We may assume an i2c_set_slave_addr was already done.
4560# $_[1]: Address
4561# Returns: undef if not detected, (8) if detected.
4562# Registers used:
4563#   0x00-0x02: Identification ('H','E','R')
4564sub fscher_detect
4565{
4566  my ($file,$addr) = @_;
4567  # check the first 3 registers
4568  if (i2c_smbus_read_byte_data($file,0x00) != 0x48) {
4569        return;
4570  }
4571  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
4572        return;
4573  }
4574  if (i2c_smbus_read_byte_data($file,0x02) != 0x52) {
4575        return;
4576  }
4577  return (8);
4578}
4579
4580# $_[0]: A reference to the file descriptor to access this chip.
4581#        We assume an i2c_set_slave_addr was already done.
4582# $_[1]: Address (unused)
4583# Returns: undef if not detected, 5 if detected.
4584# Registers used:
4585#   0x3E: Manufacturer ID
4586#   0x3F: Version/Stepping
4587sub lm93_detect
4588{
4589  my $file = shift;
4590  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x01
4591            and i2c_smbus_read_byte_data($file, 0x3F) == 0x73;
4592  return 5;
4593}
4594
4595# $_[0]: A reference to the file descriptor to access this chip.
4596#        We may assume an i2c_set_slave_addr was already done.
4597# $_[1]: Address
4598# Returns: undef if not detected, (7) if detected.
4599# Registers used:
4600#   0x3F: Revision ID
4601#   0x48: Address
4602#   0x4A, 0x4B, 0x4F, 0x57, 0x58: Reserved bits.
4603# We do not use 0x49's reserved bits on purpose. The register is named
4604# "VID4/Device ID" so it is doubtful bits 7-1 are really unused.
4605sub m5879_detect
4606{
4607  my ($file, $addr) = @_;
4608
4609  return
4610    unless i2c_smbus_read_byte_data($file, 0x3F) == 0x01;
4611 
4612  return
4613    unless i2c_smbus_read_byte_data($file, 0x48) == $addr;
4614 
4615  return
4616    unless (i2c_smbus_read_byte_data($file, 0x4A) & 0x06) == 0
4617       and (i2c_smbus_read_byte_data($file, 0x4B) & 0xFC) == 0
4618       and (i2c_smbus_read_byte_data($file, 0x4F) & 0xFC) == 0
4619       and (i2c_smbus_read_byte_data($file, 0x57) & 0xFE) == 0
4620       and (i2c_smbus_read_byte_data($file, 0x58) & 0xEF) == 0;
4621
4622  return (7);
4623}
4624
4625# $_[0]: A reference to the file descriptor to access this chip.
4626#        We assume an i2c_set_slave_addr was already done.
4627# $_[1]: Address
4628# Returns: undef if not detected, 5 or 6 if detected.
4629# Registers used:
4630#   0x3E: Manufacturer ID
4631#   0x3F: Version/Stepping
4632#   0x47: VID (3 reserved bits)
4633#   0x49: VID4 (7 reserved bits)
4634sub smsc47m192_detect
4635{
4636  my ($file, $addr) = @_;
4637  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x55
4638           and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF0) == 0x20
4639           and (i2c_smbus_read_byte_data($file, 0x47) & 0x70) == 0x00
4640           and (i2c_smbus_read_byte_data($file, 0x49) & 0xFE) == 0x80;
4641  return ($addr == 0x2d ? 6 : 5);
4642}
4643
4644# $_[0]: A reference to the file descriptor to access this chip.
4645#        We assume an i2c_set_slave_addr was already done.
4646# $_[1]: Address
4647# Returns: undef if not detected, 5 or 6 if detected.
4648# Registers used:
4649#   0x3E: Manufacturer ID
4650#   0x3F: Version/Stepping
4651#   0x40: Configuration (2 reserved bits)
4652#   0x42: Interrupt Status 2 (1 reserved bit)
4653#   0x43: VID (2 reserved bits)
4654sub dme1737_detect
4655{
4656  my ($file, $addr) = @_;
4657  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x55
4658           and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF8) == 0x88
4659           and (i2c_smbus_read_byte_data($file, 0x40) & 0xC4) == 0x04
4660           and (i2c_smbus_read_byte_data($file, 0x42) & 0x02) == 0x00
4661           and (i2c_smbus_read_byte_data($file, 0x43) & 0xC0) == 0x00;
4662  return ($addr == 0x2e ? 6 : 5);
4663}
4664
4665# $_[0]: Chip to detect
4666#   (1 = F75111R/RG/N, 2 = F75121R/F75122R/RG, 3 = F75373S/SG,
4667#    4 = F75375S/SP, 5 = F75387SG/RG, 6 = F75383M/S/F75384M/S,
4668#    7 = custom power control IC)
4669# $_[1]: A reference to the file descriptor to access this chip.
4670#        We assume an i2c_set_slave_addr was already done.
4671# $_[2]: Address (unused)
4672# Returns: undef if not detected, 7 if detected.
4673# Registers used:
4674#   0x5A-0x5B: Chip ID
4675#   0x5D-0x5E: Vendor ID
4676sub fintek_detect
4677{
4678  my ($chip, $file, $addr) = @_;
4679  my $chipid = (i2c_smbus_read_byte_data($file, 0x5A) << 8)
4680             | i2c_smbus_read_byte_data($file, 0x5B);
4681  my $vendid = (i2c_smbus_read_byte_data($file, 0x5D) << 8)
4682             | i2c_smbus_read_byte_data($file, 0x5E);
4683
4684  return unless $vendid == 0x1934; # Fintek ID
4685
4686  if ($chip == 1) { # F75111R/RG/N
4687    return unless $chipid == 0x0300;
4688  } elsif ($chip == 2) { # F75121R/F75122R/RG
4689    return unless $chipid == 0x0301;
4690  } elsif ($chip == 3) { # F75373S/SG
4691    return unless $chipid == 0x0204;
4692  } elsif ($chip == 4) { # F75375S/SP
4693    return unless $chipid == 0x0306;
4694  } elsif ($chip == 5) { # F75387SG/RG
4695    return unless $chipid == 0x0410;
4696  } elsif ($chip == 6) { # F75383M/S/F75384M/S
4697    # The datasheet has 0x0303, but Fintek say 0x0413 is also possible
4698    return unless $chipid == 0x0303 || $chipid == 0x0413;
4699  } elsif ($chip == 7) { # custom power control IC
4700    return unless $chipid == 0x0302;
4701  }
4702
4703  return 7;
4704}
4705
4706# $_[0]: A reference to the file descriptor to access this chip.
4707#        We may assume an i2c_set_slave_addr was already done.
4708# $_[1]: Address
4709# Returns: undef if not detected, 4 or 7 if detected
4710# Detection is based on the fact that the SAA1064 has only one readable
4711# register, and thus ignores the read address. This register can have value
4712# 0x80 (first read since power-up) or 0x00.
4713sub saa1064_detect
4714{
4715        my ($file,$addr) = @_;
4716        my $status = i2c_smbus_read_byte_data ($file, 0x00);
4717
4718        return if ($status & 0x7f) != 0x00;
4719
4720        for (my $i=0 ; $i<256; $i++) {
4721                return if i2c_smbus_read_byte_data ($file, $i) != 0x00;
4722        }
4723
4724        return 7
4725                if $status == 0x80;
4726        return 4;
4727}
4728
4729# $_[0]: A reference to the file descriptor to access this chip.
4730#        We may assume an i2c_set_slave_addr was already done.
4731# $_[1]: Address
4732# Returns: undef if not detected, 1 if detected
4733# Detection is rather difficult, since the PCA9540 has a single register.
4734# Fortunately, no other device is known to live at this address.
4735sub pca9540_detect
4736{
4737        my ($file, $addr) = @_;
4738        my $reg = i2c_smbus_read_byte($file);
4739
4740        return if ($reg & 0xfa);
4741        return if $reg != i2c_smbus_read_byte($file);
4742        return if $reg != i2c_smbus_read_byte($file);
4743        return if $reg != i2c_smbus_read_byte($file);
4744
4745        return 1;
4746}
4747
4748# $_[0]: A reference to the file descriptor to access this chip.
4749#        We assume an i2c_set_slave_addr was already done.
4750# $_[1]: Address (unused)
4751# Returns: undef if not detected, 1 if detected
4752# Detection is rather difficult, since the PCA9556 only has 4 registers
4753# and no unused bit. We use the fact that the registers cycle over
4754# 4 addresses boundaries, and the logic rules between registers.
4755sub pca9556_detect
4756{
4757        my ($file, $addr) = @_;
4758        my $input = i2c_smbus_read_byte_data($file, 0x00);
4759        my $output = i2c_smbus_read_byte_data($file, 0x01);
4760        my $invert = i2c_smbus_read_byte_data($file, 0x02);
4761        my $config = i2c_smbus_read_byte_data($file, 0x03);
4762
4763        # Pins configured for output (config = 0) must obey the following
4764        # rule: input = output ^ invert
4765
4766        return unless ($input & ~$config) == (($output ^ $invert) & ~$config);
4767
4768        for (my $i = 5; $i < 254 ; $i+=4) {
4769                return unless i2c_smbus_read_byte_data($file, $i) == $output;
4770                return unless i2c_smbus_read_byte_data($file, $i+1) == $invert;
4771                return unless i2c_smbus_read_byte_data($file, $i+2) == $config;
4772        }
4773
4774        return 1;
4775}
4776
4777# $_[0]: A reference to the file descriptor to access this chip.
4778#        We may assume an i2c_set_slave_addr was already done.
4779# $_[1]: Address
4780# Returns: undef if not detected, 3 if detected
4781sub max6900_detect
4782{
4783        my ($file,$addr) = @_;
4784        my $reg;
4785       
4786        # SEC
4787        $reg = i2c_smbus_read_byte_data ($file, 0x81);
4788        return if
4789                ($reg & 0xF0) > 0x50 or
4790                ($reg & 0x0F) > 9;
4791
4792        # MIN
4793        $reg = i2c_smbus_read_byte_data ($file, 0x83);
4794        return if
4795                ($reg & 0xF0) > 0x50 or
4796                ($reg & 0x0F) > 9;
4797
4798        # HR
4799        $reg = i2c_smbus_read_byte_data ($file, 0x85);
4800        return if
4801                ($reg & 0x40) != 0x00 or
4802                ($reg & 0x0F) > 9;
4803
4804        # DATE
4805        $reg = i2c_smbus_read_byte_data ($file, 0x87);
4806        return if
4807                $reg == 0x00 or
4808                ($reg & 0xF0) > 0x30 or
4809                ($reg & 0x0F) > 9;
4810
4811        # MONTH
4812        $reg = i2c_smbus_read_byte_data ($file, 0x89);
4813        return if
4814                $reg == 0x00 or
4815                ($reg & 0xF0) > 0x10 or
4816                ($reg & 0x0F) > 9;
4817
4818        # DAY
4819        $reg = i2c_smbus_read_byte_data ($file, 0x8B);
4820        return if
4821                $reg == 0 or
4822                $reg > 7;
4823
4824        # YEAR
4825        $reg = i2c_smbus_read_byte_data ($file, 0x8D);
4826        return if
4827                ($reg & 0xF0) > 0x90 or
4828                ($reg & 0x0F) > 9;
4829
4830        # CONTROL
4831        $reg = i2c_smbus_read_byte_data ($file, 0x8F);
4832        return if
4833                ($reg & 0x7F) != 0x00;
4834
4835        # CENTURY
4836        $reg = i2c_smbus_read_byte_data ($file, 0x93);
4837        return if
4838                ($reg & 0xF0) > 0x90 or
4839                ($reg & 0x0F) > 9;
4840
4841        return 3;
4842}
4843
4844# $_[0]: A reference to the file descriptor to access this chip.
4845#        We may assume an i2c_set_slave_addr was already done.
4846# $_[1]: Address
4847# Returns: 1
4848# This is a placeholder so we get a report if any device responds
4849# to the SMBus Device Default Address (0x61), which is used for
4850# ARP in SMBus 2.0.
4851sub arp_detect
4852{
4853  return (1);
4854}
4855
4856# This checks for non-FFFF values for SpecInfo and Status.
4857# The address (0x09) is specified by the SMBus standard so it's likely
4858# that this really is a smart battery charger.
4859# $_[0]: A reference to the file descriptor to access this chip.
4860#        We may assume an i2c_set_slave_addr was already done.
4861# $_[1]: Address
4862# Returns: 5
4863sub smartbatt_chgr_detect
4864{
4865  my ($file,$addr) = @_;
4866  # check some registers
4867  if (i2c_smbus_read_word_data($file,0x11) == 0xffff) {
4868        return;
4869  }
4870  if (i2c_smbus_read_word_data($file,0x13) == 0xffff) {
4871        return;
4872  }
4873  return (5);
4874}
4875
4876# This checks for non-FFFF values for State and Info.
4877# The address (0x0a) is specified by the SMBus standard so it's likely
4878# that this really is a smart battery manager/selector.
4879# $_[0]: A reference to the file descriptor to access this chip.
4880#        We may assume an i2c_set_slave_addr was already done.
4881# $_[1]: Address
4882# Returns: 5
4883sub smartbatt_mgr_detect
4884{
4885  my ($file,$addr) = @_;
4886  # check some registers
4887  if (i2c_smbus_read_word_data($file,0x01) == 0xffff) {
4888        return;
4889  }
4890  if (i2c_smbus_read_word_data($file,0x04) == 0xffff) {
4891        return;
4892  }
4893  return (5);
4894}
4895
4896# This checks for non-FFFF values for temperature, voltage, and current.
4897# The address (0x0b) is specified by the SMBus standard so it's likely
4898# that this really is a smart battery.
4899# $_[0]: A reference to the file descriptor to access this chip.
4900#        We may assume an i2c_set_slave_addr was already done.
4901# $_[1]: Address
4902# Returns: 5
4903sub smartbatt_detect
4904{
4905  my ($file,$addr) = @_;
4906  # check some registers
4907  if (i2c_smbus_read_word_data($file,0x08) == 0xffff) {
4908        return;
4909  }
4910  if (i2c_smbus_read_word_data($file,0x09) == 0xffff) {
4911        return;
4912  }
4913  if (i2c_smbus_read_word_data($file,0x0a) == 0xffff) {
4914        return;
4915  }
4916  return (5);
4917}
4918
4919# Returns: 4
4920# These are simple detectors that only look for a register at the
4921# standard location. No writes are performed.
4922# For KCS, use the STATUS register. For SMIC, use the FLAGS register.
4923sub ipmi_kcs_detect
4924{
4925  return if inb (0x0ca3) == 0xff;
4926  return (4);
4927}
4928
4929sub ipmi_smic_detect
4930{
4931  return if inb (0x0cab) == 0xff;
4932  return (4);
4933}
4934
4935# $_[0]: Chip to detect (0 = W83L784R/AR, 1 = W83L785R)
4936# $_[1]: A reference to the file descriptor to access this chip.
4937# $_[2]: Address
4938# Returns: undef if not detected, 6 or 8 if detected
4939# Registers used:
4940#   0x40: Configuration
4941#   0x4a: Full I2C Address (not W83L785R)
4942#   0x4b: I2C addresses of emulated LM75 chips (not W83L785R)
4943#   0x4c: Winbond Vendor ID (Low Byte)
4944#   0x4d: Winbond Vendor ID (High Byte)
4945#   0x4e: Chip ID
4946# Note that this function is always called through a closure, so the
4947# arguments are shifted by one place.
4948sub w83l784r_detect
4949{
4950  my ($reg,@res);
4951  my ($chip,$file,$addr) = @_;
4952
4953  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4954  return if $chip == 0
4955    and i2c_smbus_read_byte_data($file,0x4a) != $addr;
4956  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
4957  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
4958  return if $chip == 0
4959    and i2c_smbus_read_byte_data($file,0x4e) != 0x50;
4960  return if $chip == 1
4961    and i2c_smbus_read_byte_data($file,0x4e) != 0x60;
4962
4963  $reg = i2c_smbus_read_byte_data($file,0x4b);
4964
4965  return 6 if $chip == 1; # W83L785R doesn't have subclients
4966 
4967  @res = (8);
4968  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08 ;
4969  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
4970  return @res;
4971}
4972
4973# $_[0]: Chip to detect (0 = W83L785TS-S)
4974# $_[1]: A reference to the file descriptor to access this chip.
4975#        We may assume an i2c_set_slave_addr was already done.
4976# $_[2]: Address
4977# Returns: undef if not detected, 8 if detected
4978# Registers used:
4979#   0x4C-4E: Mfr and Chip ID
4980# Note that this function is always called through a closure, so the
4981# arguments are shifted by one place.
4982sub w83l785ts_detect
4983{
4984  my ($chip,$file,$addr) = @_;
4985  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
4986  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
4987  return unless i2c_smbus_read_byte_data($file,0x4e) == 0x70;
4988  return (8);
4989}
4990
4991# $_[0]: Chip to detect. Always zero for now, but available for future use
4992#        if somebody finds a way to distinguish MAX6650 and MAX6651.
4993# $_[1]: A reference to the file descriptor to access this chip.
4994#        We may assume an i2c_set_slave_addr was already done.
4995# $_[2]: Address
4996# Returns: undef if not detected, 4 if detected.
4997#
4998# The max6650 has no device ID register. However, a few registers have
4999# spare bits, which are documented as being always zero on read. We read
5000# all of these registers check the spare bits. Any non-zero means this
5001# is not a max6650/1.
5002#
5003# The always zero bits are:
5004#   configuration byte register (0x02) - top 2 bits
5005#   gpio status register (0x14) - top 3 bits
5006#   alarm enable register (0x08) - top 3 bits
5007#   alarm status register (0x0A) - top 3 bits
5008#   tachometer count time register (0x16) - top 6 bits
5009# Additionally, not all values are possible for lower 3 bits of
5010# the configuration register.
5011sub max6650_detect
5012{
5013  my ($chip, $file) = @_;
5014
5015  my $conf = i2c_smbus_read_byte_data($file,0x02);
5016 
5017  return if i2c_smbus_read_byte_data($file,0x16) & 0xFC;
5018  return if i2c_smbus_read_byte_data($file,0x0A) & 0xE0;
5019  return if i2c_smbus_read_byte_data($file,0x08) & 0xE0;
5020  return if i2c_smbus_read_byte_data($file,0x14) & 0xE0;
5021  return if ($conf & 0xC0) or ($conf & 0x07) > 4;
5022
5023  return 4;
5024}
5025
5026# $_[0]: Chip to detect (0 = VT1211)
5027# $_[1]: A reference to the file descriptor to access this chip.
5028#        We may assume an i2c_set_slave_addr was already done.
5029# $_[2]: Address
5030#
5031# This isn't very good detection.
5032# Verify the i2c address, and the stepping ID (which is 0xb0 on
5033# my chip but could be different for others...
5034#
5035sub vt1211_i2c_detect
5036{
5037  my ($chip,$file,$addr) = @_;
5038  return unless (i2c_smbus_read_byte_data($file,0x48) & 0x7f) == $addr;
5039  return unless i2c_smbus_read_byte_data($file,0x3f) == 0xb0;
5040  return 2;
5041}
5042
5043# $_[0]: Chip to detect (0 = VT1211)
5044# $_[1]: ISA address
5045# $_[2]: I2C file handle
5046# $_[3]: I2C address
5047sub vt1211_alias_detect
5048{
5049  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
5050  my $i;
5051  return 0 unless (inb($isa_addr + 0x48) & 0x7f) == $i2c_addr;
5052  return 0 unless (i2c_smbus_read_byte_data($file,0x48) & 0x7f) == $i2c_addr;
5053  for ($i = 0x2b; $i <= 0x3d; $i ++) {
5054    return 0 unless inb($isa_addr + $i) == i2c_smbus_read_byte_data($file,$i);
5055  }
5056  return 1;
5057}
5058
5059
5060######################
5061# PCI CHIP DETECTION #
5062######################
5063
5064# Returns: undef if not detected, (7) or (9) if detected.
5065# The address is encoded in PCI space. We could decode it and print it.
5066# For Linux 2.4 we should probably check for invalid matches (SiS645).
5067sub sis5595_pci_detect
5068{
5069        return unless exists $pci_list{'1039:0008'};
5070        return (kernel_version_at_least(2, 6, 0) ? 9 : 7);
5071}
5072
5073# Returns: undef if not detected, (9) if detected.
5074# The address is encoded in PCI space. We could decode it and print it.
5075sub via686a_pci_detect
5076{
5077        return unless exists $pci_list{'1106:3057'};
5078        return 9;
5079}
5080
5081# Returns: undef if not detected, (9) if detected.
5082# The address is encoded in PCI space. We could decode it and print it.
5083sub via8231_pci_detect
5084{
5085        return unless exists $pci_list{'1106:8235'};
5086        return 9;
5087}
5088
5089# Returns: undef if not detected, (9) if detected.
5090sub k8temp_pci_detect
5091{
5092        return unless exists $pci_list{'1022:1103'};
5093        return 9;
5094}
5095
5096
5097################
5098# MAIN PROGRAM #
5099################
5100
5101# $_[0]: reference to a list of chip hashes
5102sub print_chips_report 
5103{
5104  my ($listref) = @_;
5105  my $data;
5106 
5107  foreach $data (@$listref) {
5108    my $is_i2c = exists $data->{i2c_addr};
5109    my $is_isa = exists $data->{isa_addr};
5110    print "  * ";
5111    if ($is_i2c) {
5112      printf "Bus `%s'\n", $data->{i2c_adap};
5113      printf "    Busdriver `%s', I2C address 0x%02x", 
5114             $data->{i2c_driver}, $data->{i2c_addr};
5115      if (exists $data->{i2c_sub_addrs}) {
5116        print " (and";
5117        my $sub_addr;
5118        foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
5119          printf " 0x%02x",$sub_addr;
5120        }
5121        print ")"
5122      }
5123      print "\n";
5124    }
5125    if ($is_isa) {
5126      print "    " if  $is_i2c;
5127      if ($data->{isa_addr}) {
5128        printf "ISA bus address 0x%04x (Busdriver `i2c-isa')\n", 
5129               $data->{isa_addr};
5130      } else {
5131        print "ISA bus, undetermined address (Busdriver `i2c-isa')\n";
5132      }
5133    }
5134    printf "    Chip `%s' (confidence: %d)\n",
5135           $data->{chipname},  $data->{conf};
5136  }
5137}
5138
5139# $_[0]: 1 if ISA bus is prefered, 0 for SMBus
5140# We build here an array adapters, indexed on the number the adapter has
5141# at this moment (we assume only loaded adapters are interesting at all;
5142# everything that got scanned also got loaded). Each entry is a reference
5143# to a hash containing:
5144#  driver: Name of the adapter driver
5145#  nr_now: Number of the bus now
5146#  nr_later: Number of the bus when the modprobes are done (not included if the
5147#        driver should not be loaded)
5148# A second array, called
5149sub generate_modprobes
5150{
5151  my ($prefer_isa) = @_;
5152
5153  my ($chip,$detection,$nr,$i,@optionlist,@probelist,$driver,$isa,$adap);
5154  my $bmcsensors = 0;
5155  my @adapters;
5156  my $modprobes = "";
5157  my $configfile = "";
5158
5159  # These are always needed
5160  $configfile .= "# I2C module options\n";
5161  $configfile .= "alias char-major-89 i2c-dev\n";
5162
5163  # Collect all loaded adapters
5164  # i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
5165  open(local *INPUTFILE, "i2cdetect -l |") or die "Couldn't find i2cdetect program!!";
5166  local $_;
5167  while (<INPUTFILE>) {
5168    my ($dev_nr, $type, $adap) = /^i2c-(\d+)\s+(\S+)\s+(.*?) *(\t|$)/;
5169    next if ($type eq "dummy" || $type eq "isa");
5170    $adapters[$dev_nr]->{driver} = find_adapter_driver($adap);
5171    $adapters[$dev_nr]->{adapname} = $adap;
5172  }
5173  close INPUTFILE;
5174
5175  # Collect all adapters used
5176  $nr = 0;
5177  $isa = 0;
5178  $modprobes .= "# I2C adapter drivers\n";
5179  foreach $chip (@chips_detected) {
5180    foreach $detection (@{$chip->{detected}}) {
5181      # If there is more than one bus detected by a driver, they are
5182      # still all added. So we number them in the correct order
5183      if (exists $detection->{i2c_driver} and
5184          not exists $adapters[$detection->{i2c_devnr}]->{nr_later} and 
5185          not (exists $detection->{isa_addr} and $prefer_isa)) {
5186         foreach $adap (@adapters) {
5187           next unless exists $adap->{driver};
5188           $adap->{nr_later} = $nr++ if $adap->{driver} eq $detection->{i2c_driver};
5189         }
5190      }
5191      if (exists $detection->{isa_addr} and
5192          not (exists $detection->{i2c_driver} and not $prefer_isa)) {
5193           $isa=1;
5194      }
5195      if ($chip->{driver} eq "bmcsensors") {
5196           $bmcsensors=1;
5197      }
5198    }
5199  }
5200
5201  for ($i = 0; $i < $nr; $i++) {
5202    foreach $adap (@adapters) {
5203      next unless exists $adap->{nr_later} and $adap->{nr_later} == $i;
5204      if ($adap->{driver} eq "UNKNOWN") {
5205        $modprobes .= "# modprobe unknown adapter ".$adap->{adapname}."\n";
5206      } elsif ($adap->{driver} eq "DISABLED") {
5207        $modprobes .= "# modprobe disabled adapter ".$adap->{adapname}."\n";
5208      } elsif ($adap->{driver} eq "to-be-written") {
5209        $modprobes .= "# no driver available for adapter ".$adap->{adapname}."\n";
5210      } else {
5211        $modprobes .= "modprobe $adap->{driver}\n"
5212          unless $modprobes =~ /modprobe $adap->{driver}\n/;
5213      }
5214      last;
5215    }
5216  }
5217  # i2c-isa is loaded automatically (as a dependency) since 2.6.14,
5218  # and will soon be gone.
5219  $modprobes .= "modprobe i2c-isa\n" if ($isa && !kernel_version_at_least(2, 6, 18));
5220  if ($bmcsensors) {
5221    $modprobes .= "# You must also install and load the IPMI modules\n";
5222    $modprobes .= "modprobe i2c-ipmi\n";
5223  }
5224
5225  # Now determine the chip probe lines
5226  $modprobes .= "# Chip drivers\n";
5227  foreach $chip (@chips_detected) {
5228    next if not @{$chip->{detected}};
5229    next if $chip->{driver} eq "not-a-sensor";   
5230    next if $chip->{driver} eq "use-isa-instead";
5231    if ($chip->{driver} eq "to-be-written") {
5232      $modprobes .= "# no driver for $chip->{detected}[0]{chipname} yet\n";
5233    } else {
5234       # need the * for 2.4 kernels, won't necessarily be an exact match
5235       open(local *INPUTFILE, "modprobe -l $chip->{driver}\\* 2>/dev/null |");
5236       local $_;
5237       my $modulefound = 0;
5238       while (<INPUTFILE>) {
5239         if(m@/@) {
5240           $modulefound = 1;
5241           last;
5242         }
5243       }
5244       close INPUTFILE;
5245       #check return value from modprobe in case modprobe -l isn't supported
5246       if((($? >> 8) == 0) && ! $modulefound) {
5247         $modprobes .= "# Warning: the required module $chip->{driver} is not currently installed\n".
5248                       "# on your system. For status of 2.6 kernel ports check\n".
5249                       "# http://www.lm-sensors.org/wiki/Devices. If driver is built\n".
5250                       "# into the kernel, or unavailable, comment out the following line.\n";
5251       }
5252       $modprobes .= "modprobe $chip->{driver}\n";
5253    }
5254
5255    # Handle misdetects
5256    foreach $detection (@{$chip->{misdetected}}) {
5257      push @optionlist, $adapters[$detection->{i2c_devnr}]->{nr_later},
5258                       $detection->{i2c_addr}
5259           if exists $detection->{i2c_addr} and
5260              exists $adapters[$detection->{i2c_devnr}]->{nr_later};
5261      push @optionlist, -1, $detection->{isa_addr}
5262           if exists $detection->{isa_addr} and $isa;
5263    }
5264
5265    # Handle aliases
5266    foreach $detection (@{$chip->{detected}}) {
5267      if (exists $detection->{i2c_driver} and 
5268          exists $detection->{isa_addr} and
5269          exists $adapters[$detection->{i2c_devnr}]->{nr_later} and
5270          $isa) {
5271        if ($prefer_isa) {
5272          push @optionlist,$adapters[$detection->{i2c_devnr}]->{nr_later},
5273                           $detection->{i2c_addr};
5274        } else {
5275          push @optionlist, -1, $detection->{isa_addr}
5276        }
5277      }
5278    }
5279
5280    next if not (@probelist or @optionlist);
5281    $configfile .= "options $chip->{driver}";
5282    $configfile .= sprintf " ignore=%d,0x%02x",shift @optionlist, 
5283                                               shift @optionlist
5284                  if @optionlist;
5285    $configfile .= sprintf ",%d,0x%02x",shift @optionlist, shift @optionlist
5286                  while @optionlist;
5287    $configfile .= sprintf " probe=%d,0x%02x",shift @probelist,
5288                                              shift @probelist
5289                  if @probelist;
5290    $configfile .= sprintf ",%d,0x%02x",shift @probelist, shift @probelist
5291                  while @probelist;
5292    $configfile .= "\n";
5293  }
5294
5295  return ($modprobes,$configfile);
5296 
5297}
5298
5299sub main
5300{
5301  my (@adapters,$res,$did_adapter_detection,$adapter);
5302
5303  # We won't go very far if not root
5304  unless ($> == 0) {
5305    print "You need to be root to run this script.\n";
5306    exit -1;
5307  }
5308
5309  initialize_conf;
5310  initialize_proc_pci;
5311  initialize_modules_list;
5312  initialize_modules_supported;
5313  initialize_kernel_version;
5314  initialize_cpu_list();
5315
5316  print "# sensors-detect revision $revision\n\n";
5317
5318  print "This program will help you determine which kernel modules you need\n",
5319        "to load to use lm_sensors most effectively. It is generally safe\n",
5320        "and recommended to accept the default answers to all questions,\n",
5321        "unless you know what you're doing.\n";
5322  print "You need to have i2c and lm_sensors installed before running this\n",
5323        "program.\n"
5324    unless kernel_version_at_least(2, 6, 0);
5325  print "\n";
5326
5327  print "We can start with probing for (PCI) I2C or SMBus adapters.\n";
5328  print "Do you want to probe now? (YES/no): ";
5329  @adapters = adapter_pci_detection
5330                        if ($did_adapter_detection = not <STDIN> =~ /\s*[Nn]/);
5331  print "\n";
5332
5333  if (not $did_adapter_detection) {
5334    print "As you skipped adapter detection, we will only scan already loaded\n".
5335          "adapter modules.\n";
5336  } else {
5337    print "We will now try to load each adapter module in turn.\n";
5338    foreach $adapter (@adapters) {
5339      next if $adapter eq "DISABLED";
5340      next if $adapter eq "to-be-tested";
5341      if (exists($modules_list{$adapter})) {
5342        print "Module `$adapter' already loaded.\n";
5343      } else {
5344        print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
5345        unless (<STDIN> =~ /^\s*[Nn]/) {
5346          if (system ("modprobe", $adapter)) {
5347            print "Loading failed... skipping.\n";
5348          } else {
5349            print "Module loaded successfully.\n";
5350          }
5351        }
5352      }
5353    }
5354  }
5355
5356  print "If you have undetectable or unsupported adapters, you can have them\n".
5357        "scanned by manually loading the modules before running this script.\n\n";
5358
5359  if (!exists($modules_list{"i2c-dev"})
5360   && !(defined $sysfs_root && -e "$sysfs_root/class/i2c-dev")) {
5361    print "To continue, we need module `i2c-dev' to be loaded.\n";
5362    print "If it is built-in into your kernel, you can safely skip this.\n"
5363      unless kernel_version_at_least(2, 6, 0);
5364    print "Do you want to load `i2c-dev' now? (YES/no): ";
5365    if (<STDIN> =~ /^\s*n/i) {
5366      print "Well, you will know best.\n";
5367    } elsif (system "modprobe", "i2c-dev") {
5368      print "Loading failed, expect problems later on.\n";
5369    } else {
5370      print "Module loaded successfully.\n";
5371    }
5372    print "\n";
5373  }
5374
5375  # Before looking for chips, make sure any special case chips are
5376  # added to the chip_ids list
5377  chip_special_cases();
5378
5379  print "We are now going to do the I2C/SMBus adapter probings. Some chips may\n",
5380        "be double detected; we choose the one with the highest confidence\n",
5381        "value in that case.\n",
5382        "If you found that the adapter hung after probing a certain address,\n",
5383        "you can specify that address to remain unprobed.\n";
5384
5385  my ($inp,@not_to_scan,$inp2);
5386  # i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
5387  open(local *INPUTFILE, "i2cdetect -l |") or die "Couldn't find i2cdetect program!!";
5388  local $_;
5389  while (<INPUTFILE>) {
5390    my ($dev_nr, $type, $adap) = /^i2c-(\d+)\s+(\S+)\s+(.*?) *(\t|$)/;
5391    next if ($type eq "dummy" || $type eq "isa");
5392    print "\n";
5393    print "Next adapter: $adap\n";
5394    print "Do you want to scan it? (YES/no/selectively): ";
5395   
5396    $inp = <STDIN>;
5397    if ($inp =~ /^\s*[Ss]/) {
5398      print "Please enter one or more addresses not to scan. Separate them ",
5399            "with comma's.\n",
5400            "You can specify a range by using dashes. Addresses may be ",
5401            "decimal (like 54)\n",
5402            "or hexadecimal (like 0x33).\n",
5403            "Addresses: ";
5404      $inp2 = <STDIN>;
5405      chop $inp2;
5406      @not_to_scan = parse_not_to_scan 0,0x7f,$inp2;
5407    }
5408    scan_adapter $dev_nr, $adap, find_adapter_driver($adap),
5409                 \@not_to_scan   unless $inp =~ /^\s*[Nn]/;
5410  }
5411  print "\n";
5412
5413  print "Some chips are also accessible through the ISA I/O ports. We have to\n".
5414        "write to arbitrary I/O ports to probe them. This is usually safe though.\n".
5415        "Yes, you do have ISA I/O ports even if you do not have any ISA slots!\n";
5416  print "Do you want to scan the ISA I/O ports? (YES/no): ";
5417  unless (<STDIN> =~ /^\s*n/i) {
5418    initialize_ioports();
5419    scan_isa_bus();
5420    close_ioports();
5421  }
5422  print "\n";
5423
5424  print "Some Super I/O chips may also contain sensors. We have to write to\n".
5425        "standard I/O ports to probe them. This is usually safe.\n";
5426  print "Do you want to scan for Super I/O sensors? (YES/no): ";
5427  unless (<STDIN> =~ /^\s*n/i) {
5428    initialize_ioports();
5429    scan_superio(0x2e, 0x2f);
5430    scan_superio(0x4e, 0x4f);
5431    close_ioports();
5432  }
5433  print "\n";
5434
5435  if(! @chips_detected) {
5436    print "Sorry, no sensors were detected.\n",
5437          "Either your sensors are not supported, or they are connected to an\n",
5438          "I2C or SMBus adapter that is not supported. See doc/FAQ,\n",
5439          "doc/lm_sensors-FAQ.html or http://www.lm-sensors.org/wiki/FAQ\n",
5440          "(FAQ #4.24.3) for further information.\n",
5441          "If you find out what chips are on your board, check\n",
5442          "http://www.lm-sensors.org/wiki/Devices for driver status.\n";
5443    exit;
5444  }
5445
5446  print "Now follows a summary of the probes I have just done.\n".
5447        "Just press ENTER to continue: ";
5448  <STDIN>;
5449
5450  my ($chip,$data);
5451  foreach $chip (@chips_detected) {
5452    next if $chip->{driver} eq "not-a-sensor";
5453    next if $chip->{driver} eq "use-isa-instead";
5454    print "\nDriver `$chip->{driver}' ";
5455    if (@{$chip->{detected}}) {
5456      if (@{$chip->{misdetected}}) {
5457        print "(should be inserted but causes problems):\n";
5458      } else {
5459        print "(should be inserted):\n";
5460      }
5461    } else {
5462      if (@{$chip->{misdetected}}) {
5463        print "(may not be inserted):\n";
5464      } else {
5465        print "(should not be inserted, but is harmless):\n";
5466      }
5467    }
5468    if (@{$chip->{detected}}) {
5469      print "  Detects correctly:\n";
5470      print_chips_report $chip->{detected};
5471    }
5472    if (@{$chip->{misdetected}}) {
5473      print "  Misdetects:\n";
5474      print_chips_report $chip->{misdetected};
5475    }
5476
5477    # People are easily confused
5478    if ($chip->{driver} eq "eeprom") {
5479      print "\n  EEPROMs are *NOT* sensors! They are data storage chips commonly\n",
5480            "  found on memory modules (SPD), in monitors (EDID), or in some\n",
5481            "  laptops, for example.\n";
5482    }
5483  }
5484  print "\n";
5485
5486  print "I will now generate the commands needed to load the required modules.\n".
5487        "Just press ENTER to continue: ";
5488  <STDIN>;
5489     
5490  print "\n";
5491  my ($modprobes, $configfile) = generate_modprobes 1;  # 1 == prefer ISA
5492  print "To make the sensors modules behave correctly, add these lines to\n".
5493        "$modules_conf:\n\n";
5494  print "#----cut here----\n".
5495        $configfile.
5496        "#----cut here----\n\n";
5497
5498  print "To load everything that is needed, add this to some /etc/rc* file:\n\n";
5499  print "#----cut here----\n".
5500        $modprobes.
5501        "# sleep 2 # optional\n".
5502        "/usr/local/bin/sensors -s # recommended\n".
5503        "#----cut here----\n\n";
5504
5505  print "If you have some drivers built into your kernel, the list above will\n".
5506        "contain too many modules. Skip the appropriate ones! You really\n".
5507        "should try these commands right now to make sure everything is\n".
5508        "working properly. Monitoring programs won't work until the needed\n".
5509        "modules are loaded.\n\n";
5510 
5511  my $have_sysconfig = -d '/etc/sysconfig';
5512  printf "Do you want to \%s /etc/sysconfig/lm_sensors? (\%s): ",
5513         (-e '/etc/sysconfig/lm_sensors' ? 'overwrite' : 'generate'),
5514         ($have_sysconfig ? 'YES/no' : 'yes/NO');
5515  $_ = <STDIN>;
5516  if (($have_sysconfig and not m/^\s*n/i) or m/^\s*y/i) {
5517    unless ($have_sysconfig) {
5518      mkdir '/etc/sysconfig', 0777
5519        or die "Sorry, can't create /etc/sysconfig ($!)";
5520    }
5521    open(local *SYSCONFIG, ">/etc/sysconfig/lm_sensors")
5522      or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)";
5523    print SYSCONFIG <<'EOT';
5524#    /etc/sysconfig/lm_sensors - Defines modules loaded by
5525#                                /etc/init.d/lm_sensors
5526#    Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>
5527#
5528#    This program is free software; you can redistribute it and/or modify
5529#    it under the terms of the GNU General Public License as published by
5530#    the Free Software Foundation; either version 2 of the License, or
5531#    (at your option) any later version.
5532#
5533#    This program is distributed in the hope that it will be useful,
5534#    but WITHOUT ANY WARRANTY; without even the implied warranty of
5535#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5536#    GNU General Public License for more details.
5537#
5538#    You should have received a copy of the GNU General Public License
5539#    along with this program; if not, write to the Free Software
5540#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5541#
5542#
5543# See also the lm_sensors homepage at:
5544#     http://www.lm-sensors.org/
5545#
5546# This file is used by /etc/init.d/lm_sensors and defines the modules to
5547# be loaded/unloaded. This file is sourced into /etc/init.d/lm_sensors.
5548#
5549# The format of this file is a shell script that simply defines the modules
5550# in order as normal variables with the special names:
5551#    MODULE_0, MODULE_1, MODULE_2, etc.
5552#
5553# List the modules that are to be loaded for your system
5554#
5555EOT
5556    print SYSCONFIG
5557      "# Generated by sensors-detect on " . scalar localtime() . "\n";
5558    my @modules = grep /^modprobe /, split "\n", $modprobes;
5559    my $i = 0;
5560    my $sysconfig = "";
5561    foreach (@modules) {
5562      s/^modprobe //;
5563      $sysconfig .= "MODULE_$i=$_\n";
5564      $i++;
5565    }
5566    print SYSCONFIG $sysconfig;
5567
5568    print "Copy prog/init/lm_sensors.init to /etc/init.d/lm_sensors\n".
5569          "for initialization at boot time.\n"
5570      unless -f "/etc/init.d/lm_sensors";
5571  }
5572}
5573
5574main;
Note: See TracBrowser for help on using the browser.