root/lm-sensors/branches/lm-sensors-3.0.0/prog/detect/sensors-detect @ 4567

Revision 4567, 168.6 KB (checked in by jwrdegoede, 6 years ago)

also recognise /etc/modprobe.conf (Fedora patch)

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