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

Revision 4572, 168.8 KB (checked in by jwrdegoede, 6 years ago)

try to run MAKEDEV if i2c-dev device files are missing before aborting (adapted 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' && -x '/sbin/MAKEDEV') {
2179      system("/sbin/MAKEDEV i2c");
2180    }
2181    if (-c '/dev/i2c-0') {
2182      $dev_i2c = '/dev/i2c-';
2183    } else { # default
2184      print "No i2c device files found. Use prog/mkdev/mkdev.sh to create them.\n";
2185      exit -1;
2186    }
2187  }
2188}
2189
2190# [0] -> VERSION
2191# [1] -> PATCHLEVEL
2192# [2] -> SUBLEVEL
2193# [3] -> EXTRAVERSION
2194#
2195use vars qw(@kernel_version);
2196
2197sub initialize_kernel_version
2198{
2199  `uname -r` =~ /(\d+)\.(\d+)\.(\d+)(.*)/;
2200  @kernel_version = ($1, $2, $3, $4);
2201}
2202
2203sub kernel_version_at_least
2204{
2205  my ($vers, $plvl, $slvl) = @_;
2206  return 1 if ($kernel_version[0]  > $vers ||
2207                ($kernel_version[0] == $vers && 
2208                  ($kernel_version[1]  > $plvl || 
2209                    ($kernel_version[1] == $plvl && 
2210                      ($kernel_version[2] >= $slvl)))));
2211  return 0;
2212}
2213
2214# @cpu is a list of reference to hashes, one hash per CPU.
2215# Each entry has the following keys: vendor_id, cpu family, model,
2216# model name and stepping, directly taken from /proc/cpuinfo.
2217use vars qw(@cpu);
2218
2219sub initialize_cpu_list
2220{
2221  open(local *INPUTFILE, "/proc/cpuinfo") or die "Can't access /proc/cpuinfo!";
2222  local $_;
2223  my $entry;
2224
2225  while (<INPUTFILE>) {
2226    if (m/^processor\s*:\s*(\d+)/) {
2227      push @cpu, $entry if scalar keys(%{$entry}); # Previous entry
2228      $entry = {}; # New entry
2229      next;
2230    }
2231    if (m/^(vendor_id|cpu family|model|model name|stepping)\s*:\s*(.+)$/) {
2232      my $k = $1;
2233      my $v = $2;
2234      $v =~ s/\s+/ /g;  # Merge multiple spaces
2235      $v =~ s/ $//;     # Trim trailing space
2236      $entry->{$k} = $v;
2237      next;
2238    }
2239  }
2240  push @cpu, $entry if scalar keys(%{$entry}); # Last entry
2241  close INPUTFILE;
2242}
2243
2244# @i2c_adapters is a list of references to hashes, one hash per I2C/SMBus
2245# adapter present on the system. Each entry has the following keys: name
2246# (directly taken from either /proc/bus/i2c or /sys/class/i2c-adapter) and
2247# driver.
2248use vars qw(@i2c_adapters);
2249
2250sub initialize_i2c_adapters_list
2251{
2252  my $entry;
2253  local $_;
2254
2255  if (defined $sysfs_root) {
2256    my $class_dir = "${sysfs_root}/class/i2c-adapter";
2257    opendir(local *ADAPTERS, $class_dir) or return;
2258
2259    while (defined($_ = readdir(ADAPTERS))) {
2260      next unless m/^i2c-(\d+)$/;
2261      $entry = {}; # New entry
2262      $entry->{'name'} = sysfs_device_attribute("${class_dir}/i2c-$1", "name")
2263                      || sysfs_device_attribute("${class_dir}/i2c-$1/device", "name");
2264      $entry->{'driver'} = find_adapter_driver($entry->{'name'});
2265      $i2c_adapters[$1] = $entry;
2266    }
2267    closedir(ADAPTERS);
2268  } else {
2269    open(local *INPUTFILE, "/proc/bus/i2c") or return;
2270
2271    while (<INPUTFILE>) {
2272      my ($nr, $type, $name) = /^i2c-(\d+)\s+(\S+)\s+(.*?) *(\t|$)/;
2273      next if ($type eq "dummy" || $type eq "isa");
2274      $entry = {}; # New entry
2275      $entry->{'name'} = $name;
2276      $entry->{'driver'} = find_adapter_driver($name);
2277      $i2c_adapters[$nr] = $entry;
2278    }
2279    close(INPUTFILE);
2280  }
2281}
2282
2283###########
2284# MODULES #
2285###########
2286
2287use vars qw(%modules_list %modules_supported);
2288
2289sub initialize_modules_list
2290{
2291  open(local *INPUTFILE, "/proc/modules") or return;
2292  local $_;
2293  while (<INPUTFILE>) {
2294    tr/_/-/;
2295    $modules_list{$1} = 1 if m/^(\S*)/;
2296  }
2297}
2298
2299sub initialize_modules_supported
2300{
2301  foreach my $chip (@chip_ids) {
2302    $modules_supported{$chip->{driver}}++;
2303  }
2304}
2305
2306#################
2307# SYSFS HELPERS #
2308#################
2309
2310# From a sysfs device path, return the driver name, or undef
2311sub sysfs_device_driver($)
2312{
2313  my $device = shift;
2314 
2315  my $link = readlink("$device/driver");
2316  return unless defined $link;
2317  return basename($link);
2318}
2319
2320# From a sysfs device path and an attribute name, return the attribute
2321# value, or undef
2322sub sysfs_device_attribute($$)
2323{
2324  my ($device, $attr) = @_;
2325  my $value;
2326
2327  open(local *FILE, "$device/$attr") or return;
2328  return unless defined($value = <FILE>);
2329  close(FILE);
2330
2331  chomp($value);
2332  return $value;
2333}
2334
2335##############
2336# PCI ACCESS #
2337##############
2338
2339use vars qw(%pci_list);
2340
2341# This function returns a list of hashes. Each hash has some PCI information:
2342# 'domain', 'bus', 'slot' and 'func' uniquely identify a PCI device in a
2343# computer; 'vendid' and 'devid' uniquely identify a type of device.
2344# 'class' lets us spot unknown SMBus adapters.
2345# This function is used when sysfs is available (Linux 2.6).
2346sub read_sys_dev_pci($)
2347{
2348  my $devices = shift;
2349  my ($dev, @pci_list);
2350
2351  opendir(local *DEVICES, "$devices")
2352    or die "$devices: $!";
2353
2354  while (defined($dev = readdir(DEVICES))) {
2355    my %record;
2356    next unless $dev =~
2357      m/^(?:([\da-f]+):)?([\da-f]+):([\da-f]+)\.([\da-f]+)$/;
2358
2359    $record{domain} = hex $1;
2360    $record{bus} = hex $2;
2361    $record{slot} = hex $3;
2362    $record{func} = hex $4;
2363
2364    $record{vendid} = oct sysfs_device_attribute("$devices/$dev", "vendor");
2365    $record{devid} = oct sysfs_device_attribute("$devices/$dev", "device");
2366    $record{class} = (oct sysfs_device_attribute("$devices/$dev", "class"))
2367                     >> 8;
2368
2369    push @pci_list, \%record;
2370  }
2371
2372  return \@pci_list;
2373}
2374
2375# This function returns a list of hashes. Each hash has some PCI information:
2376# 'bus', 'slot' and 'func' uniquely identify a PCI device in a computer;
2377# 'vendid' and 'devid' uniquely identify a type of device.
2378# This function is used when sysfs is not available (Linux 2.4).
2379sub read_proc_dev_pci
2380{
2381  my ($dfn, $vend, @pci_list);
2382  open(local *INPUTFILE, "/proc/bus/pci/devices")
2383    or die "/proc/bus/pci/devices: $!";
2384  local $_;
2385  while (<INPUTFILE>) {
2386    my %record;
2387    ($dfn, $vend) = map { hex } (split) [0..1];
2388    $record{bus} = $dfn >> 8;
2389    $record{slot} = ($dfn & 0xf8) >> 3;
2390    $record{func} = $dfn & 0x07;
2391    $record{vendid} = $vend >> 16;
2392    $record{devid} = $vend & 0xffff;
2393   
2394    push @pci_list, \%record;
2395  }
2396  return \@pci_list;
2397}
2398
2399sub initialize_proc_pci
2400{
2401  my $pci_list;
2402
2403  if (defined $sysfs_root) {
2404    $pci_list = read_sys_dev_pci("$sysfs_root/bus/pci/devices");
2405  } else {
2406    $pci_list = read_proc_dev_pci();
2407  }
2408
2409  # Note that we lose duplicate devices at this point, but we don't
2410  # really care. What matters to us is which unique devices are present,
2411  # not how many of each.
2412  %pci_list = map {
2413    sprintf("%04x:%04x", $_->{vendid}, $_->{devid}) => $_
2414  } @{$pci_list};
2415}
2416
2417#####################
2418# ADAPTER DETECTION #
2419#####################
2420
2421sub adapter_pci_detection_sis_96x
2422{
2423  my $driver="";
2424
2425  # first, determine which driver if any...
2426  if (kernel_version_at_least(2,6,0)) {
2427    if (exists $pci_list{"1039:0016"}) {
2428      $driver = "i2c-sis96x";
2429    } elsif (exists $pci_list{"1039:0008"}) {
2430      $driver = "i2c-sis5595";
2431    }
2432  } elsif (kernel_version_at_least(2,4,0)) {
2433    if (exists $pci_list{"1039:0008"}) {
2434      if ((exists $pci_list{"1039:0645"}) ||
2435          (exists $pci_list{"1039:0646"}) ||
2436          (exists $pci_list{"1039:0648"}) ||
2437          (exists $pci_list{"1039:0650"}) ||
2438          (exists $pci_list{"1039:0651"}) ||
2439          (exists $pci_list{"1039:0655"}) ||
2440          (exists $pci_list{"1039:0661"}) ||
2441          (exists $pci_list{"1039:0735"}) ||
2442          (exists $pci_list{"1039:0745"}) ||
2443          (exists $pci_list{"1039:0746"})) {
2444        $driver = "i2c-sis645";
2445      } else {
2446        $driver = "i2c-sis5595";
2447      }
2448    } elsif ((exists $pci_list{"1039:0016"}) ||
2449             (exists $pci_list{"1039:0018"})) {
2450      $driver = "i2c-sis645";
2451    }
2452  }
2453
2454  # then, add the appropriate entries to @pci_adapters
2455  if ($driver eq "i2c-sis5595") {
2456    push @pci_adapters, @pci_adapters_sis5595;
2457  } elsif ($driver eq "i2c-sis645") {
2458    push @pci_adapters, @pci_adapters_sis645;
2459  } elsif ($driver eq "i2c-sis96x") {
2460    push @pci_adapters, @pci_adapters_sis96x;
2461  }
2462}
2463
2464# Build and return a PCI device's bus ID
2465sub pci_busid($)
2466{
2467  my $device = shift;
2468  my $busid;
2469
2470  $busid = sprintf("\%02x:\%02x.\%x",
2471                   $device->{bus}, $device->{slot}, $device->{func});
2472  $busid = sprintf("\%04x:", $device->{domain}) . $busid
2473    if defined $device->{domain};
2474
2475  return $busid;
2476}
2477
2478sub adapter_pci_detection
2479{
2480  my ($key, $device, $try, @res, %smbus);
2481  print "Probing for PCI bus adapters...\n";
2482
2483  # Custom detection routine for some SiS chipsets
2484  adapter_pci_detection_sis_96x();
2485
2486  # Build a list of detected SMBus devices
2487  foreach $key (keys %pci_list) {
2488    $device = $pci_list{$key};
2489    $smbus{$key}++
2490      if exists $device->{class} && $device->{class} == 0x0c05; # SMBus
2491  }
2492
2493  # Loop over the known I2C/SMBus adapters
2494  foreach $try (@pci_adapters) {
2495    $key = sprintf("%04x:%04x", $try->{vendid}, $try->{devid});
2496    if (exists $pci_list{$key}) {
2497        $device = $pci_list{$key};
2498        printf "Use driver `\%s' for device \%s: \%s\n",
2499               $try->{driver}, pci_busid($device), $try->{procid};
2500        if ($try->{driver} eq "to-be-tested") {
2501          print "\nWe are currently looking for testers for this adapter!\n".
2502                "Please check http://www.lm-sensors.org/wiki/Devices\n".
2503                "and/or contact us if you want to help.\n\n";
2504          print "Continue... ";
2505          <STDIN>;
2506          print "\n";
2507        }
2508        push @res,$try->{driver};
2509
2510        # Delete from detected SMBus device list
2511        delete $smbus{$key};
2512    }
2513  }
2514
2515  # Now see if there are unknown SMBus devices left
2516  foreach $key (keys %smbus) {
2517    $device = $pci_list{$key};
2518    printf "Found unknown SMBus adapter \%04x:\%04x at \%s.\n",
2519           $device->{vendid}, $device->{devid}, pci_busid($device);
2520  }
2521 
2522  if (! @res) {
2523    print "Sorry, no known PCI bus adapters found.\n";
2524  }
2525  return @res;
2526}
2527
2528# $_[0]: Adapter description as found in /proc/bus/i2c or sysfs
2529sub find_adapter_driver
2530{
2531  my $adapter;
2532  for $adapter (@pci_adapters) {
2533    return $adapter->{driver}
2534      if (exists $adapter->{match} && $_[0] =~ $adapter->{match});
2535  }
2536  return "UNKNOWN";
2537}
2538
2539#############################
2540# I2C AND SMBUS /DEV ACCESS #
2541#############################
2542
2543# This should really go into a separate module/package.
2544
2545# These are copied from <linux/i2c-dev.h>
2546
2547use constant IOCTL_I2C_SLAVE    => 0x0703;
2548use constant IOCTL_I2C_FUNCS    => 0x0705;
2549use constant IOCTL_I2C_SMBUS    => 0x0720;
2550
2551use constant SMBUS_READ         => 1;
2552use constant SMBUS_WRITE        => 0;
2553
2554use constant SMBUS_QUICK        => 0;
2555use constant SMBUS_BYTE         => 1;
2556use constant SMBUS_BYTE_DATA    => 2;
2557use constant SMBUS_WORD_DATA    => 3;
2558
2559use constant I2C_FUNC_SMBUS_QUICK       => 0x00010000;
2560use constant I2C_FUNC_SMBUS_READ_BYTE   => 0x00020000;
2561
2562# Get the i2c adapter's functionalities
2563# $_[0]: Reference to an opened filehandle
2564# Returns: -1 on failure, functionality bitfield on success.
2565sub i2c_get_funcs($)
2566{
2567  my $file = shift;
2568  my $funcs = pack "L", 0; # Allocate space
2569
2570  ioctl $file, IOCTL_I2C_FUNCS, $funcs or return -1;
2571  $funcs = unpack "L", $funcs;
2572
2573  return $funcs;
2574}
2575
2576# Select the device to communicate with through its address.
2577# $_[0]: Reference to an opened filehandle
2578# $_[1]: Address to select
2579# Returns: 0 on failure, 1 on success.
2580sub i2c_set_slave_addr
2581{
2582  my ($file,$addr) = @_;
2583  $addr += 0; # Make sure it's a number not a string
2584  ioctl $file, IOCTL_I2C_SLAVE, $addr or return 0;
2585  return 1;
2586}
2587
2588# i2c_smbus_access is based upon the corresponding C function (see
2589# <linux/i2c-dev.h>). You should not need to call this directly.
2590# Exact calling conventions are intricate; read i2c-dev.c if you really need
2591# to know.
2592# $_[0]: Reference to an opened filehandle
2593# $_[1]: SMBUS_READ for reading, SMBUS_WRITE for writing
2594# $_[2]: Command (usually register number)
2595# $_[3]: Transaction kind (SMBUS_BYTE, SMBUS_BYTE_DATA, etc.)
2596# $_[4]: Reference to an array used for input/output of data
2597# Returns: 0 on failure, 1 on success.
2598# Note that we need to get back to Integer boundaries through the 'x2'
2599# in the pack. This is very compiler-dependent; I wish there was some other
2600# way to do this.
2601sub i2c_smbus_access
2602{
2603  my ($file,$read_write,$command,$size,$data) = @_;
2604  my $data_array = pack "C32", @$data;
2605  my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
2606  ioctl $file, IOCTL_I2C_SMBUS, $ioctl_data or return 0;
2607  @{$_[4]} = unpack "C32",$data_array;
2608  return 1;
2609}
2610
2611# $_[0]: Reference to an opened filehandle
2612# $_[1]: Either 0 or 1
2613# Returns: -1 on failure, the 0 on success.
2614sub i2c_smbus_write_quick
2615{
2616  my ($file,$value) = @_;
2617  my @data;
2618  i2c_smbus_access $file, $value, 0, SMBUS_QUICK, \@data
2619         or return -1;
2620  return 0;
2621}
2622
2623# $_[0]: Reference to an opened filehandle
2624# Returns: -1 on failure, the read byte on success.
2625sub i2c_smbus_read_byte
2626{
2627  my ($file) = @_;
2628  my @data;
2629  i2c_smbus_access $file, SMBUS_READ, 0, SMBUS_BYTE, \@data
2630         or return -1;
2631  return $data[0];
2632}
2633
2634# $_[0]: Reference to an opened filehandle
2635# $_[1]: Command byte (usually register number)
2636# Returns: -1 on failure, the read byte on success.
2637sub i2c_smbus_read_byte_data
2638{
2639  my ($file,$command) = @_;
2640  my @data;
2641  i2c_smbus_access $file, SMBUS_READ, $command, SMBUS_BYTE_DATA, \@data
2642         or return -1;
2643  return $data[0];
2644}
2645 
2646# $_[0]: Reference to an opened filehandle
2647# $_[1]: Command byte (usually register number)
2648# Returns: -1 on failure, the read word on success.
2649# Note: some devices use the wrong endiannes; use swap_bytes to correct for
2650# this.
2651sub i2c_smbus_read_word_data
2652{
2653  my ($file,$command) = @_;
2654  my @data;
2655  i2c_smbus_access $file, SMBUS_READ, $command, SMBUS_WORD_DATA, \@data
2656         or return -1;
2657  return $data[0] + 256 * $data[1];
2658}
2659
2660# $_[0]: Reference to an opened filehandle
2661# $_[1]: Address
2662# $_[2]: Functionalities of this i2c adapter
2663# Returns: 1 on successful probing, 0 else.
2664# This function is meant to prevent AT24RF08 corruption and write-only
2665# chips locks. This is done by choosing the best probing method depending
2666# on the address range.
2667sub i2c_probe($$$)
2668{
2669  my ($file, $addr, $funcs) = @_;
2670  my $data = [];
2671  if (($addr >= 0x50 && $addr <= 0x5F)
2672   || ($addr >= 0x30 && $addr <= 0x37)) {
2673    # This covers all EEPROMs we know of, including page protection addresses.
2674    # Note that some page protection addresses will not reveal themselves with
2675    # this, because they ack on write only, but this is probably better since
2676    # some EEPROMs write-protect themselves permanently on almost any write to
2677    # their page protection address.
2678    return 0 unless ($funcs & I2C_FUNC_SMBUS_READ_BYTE);
2679    return i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE, $data);
2680  } else {
2681    return 0 unless ($funcs & I2C_FUNC_SMBUS_QUICK);
2682    return i2c_smbus_access($file, SMBUS_WRITE, 0, SMBUS_QUICK, $data);
2683  }
2684}
2685
2686####################
2687# ADAPTER SCANNING #
2688####################
2689
2690use vars qw(@chips_detected);
2691
2692# We will build a complicated structure @chips_detected here, being:
2693# A list of
2694#  references to hashes
2695#    with field 'driver', being a string with the driver name for this chip;
2696#    with field 'detected'
2697#      being a reference to a list of
2698#        references to hashes of type 'detect_data';
2699#    with field 'misdetected'
2700#      being a reference to a list of
2701#        references to hashes of type 'detect_data'
2702
2703# Type detect_data:
2704# A hash
2705#   with field 'i2c_adap' containing an adapter string as appearing
2706#        in /proc/bus/i2c (if this is an I2C detection)
2707#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
2708#       adapter (if this is an I2C detection)
2709#  with field 'i2c_driver', containing the driver name for this adapter
2710#       (if this is an I2C detection)
2711#  with field 'i2c_addr', containing the I2C address of the detection;
2712#       (if this is an I2C detection)
2713#  with field 'i2c_sub_addrs', containing a reference to a list of
2714#       other I2C addresses (if this is an I2C detection)
2715#  with field 'isa_addr' containing the ISA address this chip is on
2716#       (if this is an ISA detection)
2717#  with field 'conf', containing the confidence level of this detection
2718#  with field 'chipname', containing the chip name
2719
2720# This adds a detection to the above structure. We do no alias detection
2721# here; so you should do ISA detections *after* all I2C detections.
2722# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
2723# In all normal cases, it should be all right.
2724# $_[0]: chip driver
2725# $_[1]: reference to data hash
2726# Returns: Nothing
2727sub add_i2c_to_chips_detected
2728{
2729  my ($chipdriver,$datahash) = @_;
2730  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2731      $main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs,
2732      $do_not_add);
2733
2734  # First determine where the hash has to be added.
2735  for ($i = 0; $i < @chips_detected; $i++) {
2736    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2737  }
2738  if ($i == @chips_detected) {
2739    push @chips_detected, { driver => $chipdriver,
2740                            detected => [],
2741                            misdetected => [] };
2742  }
2743  $new_detected_ref = $chips_detected[$i]->{detected};
2744  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2745
2746  # Find out whether our new entry should go into the detected or the
2747  # misdetected list. We compare all i2c addresses; if at least one matches,
2748  # but our conf value is lower, we assume this is a misdetect.
2749  @hash_addrs = ($datahash->{i2c_addr});
2750  push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
2751       if exists $datahash->{i2c_sub_addrs};
2752  $put_in_detected = 1;
2753  $do_not_add = 0;
2754  FIND_LOOP:
2755  foreach $main_entry (@chips_detected) {
2756    foreach $detected_entry (@{$main_entry->{detected}}) {
2757      @entry_addrs = ($detected_entry->{i2c_addr});
2758      push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
2759               if exists $detected_entry->{i2c_sub_addrs};
2760      if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
2761          any_list_match \@entry_addrs, \@hash_addrs) {
2762        if ($detected_entry->{conf} >= $datahash->{conf}) {
2763          $put_in_detected = 0;
2764        }
2765        if ($chipdriver eq $main_entry->{driver}) {
2766          $do_not_add = 1;
2767        }
2768        last FIND_LOOP;
2769      }
2770    }
2771  }
2772
2773  if ($put_in_detected) {
2774    # Here, we move all entries from detected to misdetected which
2775    # match at least in one main or sub address. This may not be the
2776    # best idea to do, as it may remove detections without replacing
2777    # them with second-best ones. Too bad.
2778    # (Khali 2003-09-13) If the driver is the same, the "misdetected"
2779    # entry is simply deleted; failing to do so cause the configuration
2780    # lines generated later to look very confusing (the driver will
2781    # be told to ignore valid addresses).
2782    @hash_addrs = ($datahash->{i2c_addr});
2783    push @hash_addrs, @{$datahash->{i2c_sub_addrs}} 
2784         if exists $datahash->{i2c_sub_addrs};
2785    foreach $main_entry (@chips_detected) {
2786      $detected_ref = $main_entry->{detected};
2787      $misdetected_ref = $main_entry->{misdetected};
2788      for ($i = @$detected_ref-1; $i >=0; $i--) {
2789        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
2790        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
2791             if exists $detected_ref->[$i]->{i2c_sub_addrs};
2792        if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} and
2793            any_list_match \@entry_addrs, \@hash_addrs) {
2794          push @$misdetected_ref,$detected_ref->[$i]
2795            unless $chipdriver eq $main_entry->{driver};
2796          splice @$detected_ref, $i, 1;
2797        }
2798      }
2799    }
2800
2801    # Now add the new entry to detected
2802    push @$new_detected_ref, $datahash;
2803  } else {
2804    # No hard work here
2805    push @$new_misdetected_ref, $datahash
2806      unless $do_not_add;
2807  }
2808}
2809
2810# This adds a detection to the above structure. We also do alias detection
2811# here; so you should do ISA detections *after* all I2C detections.
2812# $_[0]: alias detection function
2813# $_[1]: chip driver
2814# $_[2]: reference to data hash
2815# Returns: 0 if it is not an alias, datahash reference if it is.
2816sub add_isa_to_chips_detected
2817{
2818  my ($alias_detect,$chipdriver,$datahash) = @_;
2819  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
2820      $main_entry,$isalias);
2821
2822  # First determine where the hash has to be added.
2823  $isalias=0;
2824  for ($i = 0; $i < @chips_detected; $i++) {
2825    last if ($chips_detected[$i]->{driver} eq $chipdriver);
2826  }
2827  if ($i == @chips_detected) {
2828    push @chips_detected, { driver => $chipdriver,
2829                            detected => [],
2830                            misdetected => [] };
2831  }
2832  $new_detected_ref = $chips_detected[$i]->{detected};
2833  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
2834
2835  # Now, we are looking for aliases. An alias can only be the same chiptype.
2836  # If an alias is found in the misdetected list, we add the new information
2837  # and terminate this function. If it is found in the detected list, we
2838  # still have to check whether another chip has claimed this ISA address.
2839  # So we remove the old entry from the detected list and put it in datahash.
2840
2841  # Misdetected alias detection:
2842  for ($i = 0; $i < @$new_misdetected_ref; $i++) {
2843    if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
2844        not exists $new_misdetected_ref->[$i]->{isa_addr} and
2845        defined $alias_detect and
2846        $new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2847      open(local *FILE, "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}") or
2848        print("Can't open $dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2849        next;
2850      binmode FILE;
2851      i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{i2c_addr} or
2852           print("Can't set I2C address for ",
2853                 "$dev_i2c$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2854           next;
2855      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2856                          $new_misdetected_ref->[$i]->{i2c_addr})) {
2857        $new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2858        return $new_misdetected_ref->[$i]; 
2859      }
2860    }
2861  }
2862
2863  # Detected alias detection:
2864  for ($i = 0; $i < @$new_detected_ref; $i++) {
2865    if (exists $new_detected_ref->[$i]->{i2c_addr} and
2866        not exists $new_detected_ref->[$i]->{isa_addr} and
2867        defined $alias_detect and
2868        $new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2869      open(local *FILE, "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}") or
2870        print("Can't open $dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2871        next;
2872      binmode FILE;
2873      i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{i2c_addr} or
2874           print("Can't set I2C address for ",
2875                 "$dev_i2c$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2876           next;
2877      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2878                          $new_detected_ref->[$i]->{i2c_addr})) {
2879        $new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2880        ($datahash) = splice (@$new_detected_ref, $i, 1);
2881        $isalias=1;
2882        last;
2883      }
2884    }
2885  }
2886
2887
2888  # Find out whether our new entry should go into the detected or the
2889  # misdetected list. We only compare main isa_addr here, of course.
2890  # (Khali 2004-05-12) If the driver is the same, the "misdetected"
2891  # entry is simply deleted; same we do for I2C chips.
2892  foreach $main_entry (@chips_detected) {
2893    $detected_ref = $main_entry->{detected};
2894    $misdetected_ref = $main_entry->{misdetected};
2895    for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
2896      if (exists $detected_ref->[$i]->{isa_addr} and
2897          exists $datahash->{isa_addr} and
2898          $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
2899        if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
2900          push @$new_misdetected_ref, $datahash
2901            unless $main_entry->{driver} eq $chipdriver;
2902        } else {
2903          push @$misdetected_ref,$detected_ref->[$i]
2904            unless $main_entry->{driver} eq $chipdriver;
2905          splice @$detected_ref, $i,1;
2906          push @$new_detected_ref, $datahash;
2907        }
2908        if ($isalias) {
2909          return $datahash;
2910        } else {
2911          return 0;
2912        }
2913      }
2914    }
2915  }
2916
2917  # Not found? OK, put it in the detected list
2918  push @$new_detected_ref, $datahash;
2919  if ($isalias) {
2920    return $datahash;
2921  } else {
2922    return 0;
2923  }
2924}
2925
2926# From the list of known I2C/SMBus devices, build a list of I2C addresses
2927# which are worth probing. There's no point in probing an address for which
2928# we don't know a single device, and probing some addresses has caused
2929# random trouble in the past.
2930sub i2c_addresses_to_scan()
2931{
2932  my @used;
2933  my @addresses;
2934  my $addr;
2935
2936  foreach my $chip (@chip_ids) {
2937    next unless defined $chip->{'i2c_addrs'};
2938    next if $chip->{'driver'} eq 'not-a-sensor';
2939    foreach $addr (@{$chip->{'i2c_addrs'}}) {
2940      $used[$addr]++;
2941    }
2942  }
2943
2944  for ($addr = 0x03; $addr <= 0x77; $addr++) {
2945    push @addresses, $addr if $used[$addr];
2946  }
2947  return \@addresses;
2948}
2949
2950# $_[0]: The number of the adapter to scan
2951# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
2952# $_[2]: The driver of the adapter
2953# @_[3]: Addresses not to scan (array reference)
2954sub scan_adapter
2955{
2956  my ($adapter_nr, $adapter_name, $adapter_driver, $not_to_scan) = @_;
2957  my ($funcs, $chip, $addr, $conf, @chips, $new_hash, $other_addr);
2958
2959  # As we modify it, we need a copy
2960  my @not_to_scan = @$not_to_scan;
2961
2962  open(local *FILE, "$dev_i2c$adapter_nr") or 
2963    (print "Can't open $dev_i2c$adapter_nr\n"), return;
2964  binmode FILE;
2965
2966  # Can we probe this adapter?
2967  $funcs = i2c_get_funcs(\*FILE);
2968  if ($funcs < 0) {
2969    print "Adapter failed to provide its functionalities, skipping.\n";
2970    return;
2971  }
2972  if (!($funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) {
2973    print "Adapter cannot be probed, skipping.\n";
2974    return;
2975  }
2976  if (~$funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE)) {
2977    print "Adapter doesn't support all probing functions.\n",
2978          "Some addresses won't be probed.\n";
2979  }
2980
2981  # Now scan each address in turn
2982  foreach $addr (@{$i2c_addresses_to_scan}) {
2983    # As the not_to_scan list is sorted, we can check it fast
2984    if (@not_to_scan and $not_to_scan[0] == $addr) {
2985      shift @not_to_scan;
2986      next;
2987    }
2988
2989    if (!i2c_set_slave_addr(\*FILE, $addr)) {
2990      # If the address is busy, in Linux 2.6 we can find out which driver
2991      # is using it, and we assume it is the right one. In Linux 2.4 we
2992      # just give up and warn the user.
2993      my ($device, $driver);
2994      if (defined($sysfs_root)) {
2995        $device = sprintf("$sysfs_root/bus/i2c/devices/\%d-\%04x",
2996                             $adapter_nr, $addr);
2997        $driver = sysfs_device_driver($device);
2998      }
2999      if (defined($driver)) {
3000        $new_hash = {
3001          conf => 6, # Arbitrary confidence
3002          i2c_addr => $addr,
3003          chipname => sysfs_device_attribute($device, "name") || "unknown",
3004          i2c_adap => $adapter_name,
3005          i2c_driver => $adapter_driver,
3006          i2c_devnr => $adapter_nr,
3007        };
3008
3009        printf "Client found at address 0x\%02x\n", $addr;
3010        printf "Handled by driver `\%s' (already loaded), chip type `\%s'\n",
3011               $driver, $new_hash->{chipname};
3012
3013        # Only add it to the list if this is something we would have
3014        # detected, else we end up with random i2c chip drivers listed
3015        # (for example media/video drivers.)
3016        if (exists $modules_supported{$driver}) {
3017          add_i2c_to_chips_detected($driver, $new_hash);
3018        } else {
3019          print "    (note: this is probably NOT a sensor chip!)\n";
3020        }   
3021      } else {
3022        printf("Client at address 0x%02x can not be probed - ".
3023               "unload all client drivers first!\n", $addr);
3024      }
3025      next;
3026    }
3027
3028    next unless i2c_probe(\*FILE, $addr, $funcs);
3029    printf "Client found at address 0x%02x\n",$addr;
3030
3031    $| = 1;
3032    foreach $chip (@chip_ids) {
3033      if (exists $chip->{i2c_addrs} and contains $addr, @{$chip->{i2c_addrs}}) {
3034        printf("\%-60s", sprintf("Probing for `\%s'... ", $chip->{name}));
3035        if (($conf,@chips) = &{$chip->{i2c_detect}} (\*FILE ,$addr)) {
3036          print "Success!\n",
3037                "    (confidence $conf, driver `$chip->{driver}')";
3038          if (@chips) {
3039            print ", other addresses:";
3040            @chips = sort @chips;
3041            foreach $other_addr (sort @chips) {
3042              printf(" 0x%02x",$other_addr);
3043            }
3044          }
3045          printf "\n";
3046          $new_hash = { conf => $conf,
3047                        i2c_addr => $addr,
3048                        chipname => $chip->{name},
3049                        i2c_adap => $adapter_name,
3050                        i2c_driver => $adapter_driver,
3051                        i2c_devnr => $adapter_nr,
3052                      };
3053          if (@chips) {
3054            my @chips_copy = @chips;
3055            $new_hash->{i2c_sub_addrs} = \@chips_copy;
3056          }
3057          add_i2c_to_chips_detected $chip->{driver}, $new_hash;
3058        } else {
3059          print "No\n";
3060        }
3061      }
3062    }
3063    $| = 0;
3064  }
3065}
3066
3067sub scan_isa_bus
3068{
3069  my ($chip,$addr,$conf);
3070  $| = 1;
3071  foreach $chip (@chip_ids) {
3072    next if not exists $chip->{isa_addrs} or not exists $chip->{isa_detect};
3073    foreach $addr (@{$chip->{isa_addrs}}) {
3074      printf("\%-60s", sprintf("Probing for `\%s'\%s... ", $chip->{name},
3075                               $addr ? sprintf(" at 0x\%x", $addr) : ''));
3076      $conf = &{$chip->{isa_detect}} ($addr);
3077      print("No\n"), next if not defined $conf;
3078      print "Success!\n";
3079      printf "    (confidence %d, driver `%s')\n", $conf, $chip->{driver};
3080      my $new_hash = { conf => $conf,
3081                       isa_addr => $addr,
3082                       chipname => $chip->{name}
3083                     };
3084      $new_hash = add_isa_to_chips_detected $chip->{alias_detect},$chip->{driver},
3085                                            $new_hash;
3086      if ($new_hash) {
3087        printf "    Alias of the chip on I2C bus `%s', address 0x%04x\n",
3088                        $new_hash->{i2c_adap},$new_hash->{i2c_addr};
3089      }
3090    }
3091  }
3092  $| = 0;
3093}
3094
3095use vars qw(%superio);
3096
3097# The following are taken from the PNP ISA spec (so it's supposed
3098# to be common to all Super I/O chips):
3099#  devidreg: The device ID register(s)
3100#  logdevreg: The logical device register
3101#  actreg: The activation register within the logical device
3102#  actmask: The activation bit in the activation register
3103#  basereg: The I/O base register within the logical device
3104%superio = (
3105  devidreg => 0x20,
3106  logdevreg => 0x07,
3107  actreg => 0x30,
3108  actmask => 0x01,
3109  basereg => 0x60,
3110);
3111
3112sub exit_superio
3113{
3114  my ($addrreg, $datareg) = @_;
3115
3116  # Some chips (SMSC, Winbond) want this
3117  outb($addrreg, 0xaa);
3118
3119  # Return to "Wait For Key" state (PNP-ISA spec)
3120  outb($addrreg, 0x02);
3121  outb($datareg, 0x02);
3122}
3123
3124# Guess if an unknown Super-I/O chip has sensors
3125sub guess_superio_ld($$$)
3126{
3127  my ($addrreg, $datareg, $typical_addr) = @_;
3128  my ($oldldn, $ldn, $addr);
3129
3130  # Save logical device number
3131  outb($addrreg, $superio{logdevreg});
3132  $oldldn = inb($datareg);
3133
3134  for ($ldn = 0; $ldn < 16; $ldn++) {
3135    # Select logical device
3136    outb($addrreg, $superio{logdevreg});
3137    outb($datareg, $ldn);
3138
3139    # Read base I/O address
3140    outb($addrreg, $superio{basereg});
3141    $addr = inb($datareg) << 8;
3142    outb($addrreg, $superio{basereg} + 1);
3143    $addr |= inb($datareg);
3144    next unless ($addr & 0xfff8) == $typical_addr;
3145
3146    printf "    (logical device \%X has address 0x\%x, could be sensors)\n",
3147           $ldn, $addr;
3148    last;
3149  }
3150
3151  # Be nice, restore original logical device
3152  outb($addrreg, $superio{logdevreg});
3153  outb($datareg, $oldldn);
3154}
3155
3156sub probe_superio($$$)
3157{
3158  my ($addrreg, $datareg, $chip) = @_;
3159  my ($val, $addr);
3160
3161  printf "\%-60s",  "Found `$chip->{name}'";
3162
3163  # Does it have hardware monitoring capabilities?
3164  if (!exists $chip->{driver}) {
3165    print "\n    (no information available)\n";
3166    return;
3167  }
3168  if ($chip->{driver} eq "not-a-sensor") {
3169    print "\n    (no hardware monitoring capabilities)\n";
3170    return;
3171  }
3172  if ($chip->{driver} eq "via-smbus-only") {
3173    print "\n    (hardware monitoring capabilities accessible via SMBus only)\n";
3174    return;
3175  }
3176
3177  # Switch to the sensor logical device
3178  outb($addrreg, $superio{logdevreg});
3179  outb($datareg, $chip->{logdev});
3180
3181  # Check the activation register
3182  outb($addrreg, $superio{actreg});
3183  $val = inb($datareg);
3184  if (!($val & $superio{actmask})) {
3185    print "\n    (but not activated)\n";
3186    return;
3187  }
3188
3189  # Get the IO base register
3190  outb($addrreg, $superio{basereg});
3191  $addr = inb($datareg);
3192  outb($addrreg, $superio{basereg} + 1);
3193  $addr = ($addr << 8) | inb($datareg);
3194  if ($addr == 0) {
3195    print "\n    (but no address specified)\n";
3196    return;
3197  }
3198  print "Success!\n";
3199  printf "    (address 0x\%x, driver `%s')\n", $addr, $chip->{driver};
3200  my $new_hash = { conf => 9,
3201                   isa_addr => $addr,
3202                   chipname => $chip->{name}
3203                 };
3204  add_isa_to_chips_detected $chip->{alias_detect},$chip->{driver},
3205                                        $new_hash;
3206}
3207
3208# Detection routine for non-standard SMSC Super I/O chips
3209# $_[0]: Super I/O LPC config/index port
3210# $_[1]: Super I/O LPC data port
3211# $_[2]: Reference to array of non-standard chips
3212# Return values: 1 if non-standard chip found, 0 otherwise
3213sub smsc_ns_detect_superio
3214{
3215    my ($addrreg, $datareg, $ns_chips) = @_;
3216    my ($val, $chip);
3217
3218    # read alternate device ID register
3219    outb($addrreg, 0x0d);
3220    $val = inb($datareg);
3221    if ($val == 0x00 || $val == 0xff) {
3222        return 0;
3223    }
3224
3225    print "Yes\n";
3226
3227    foreach $chip (@{$ns_chips}) {
3228        if ($chip->{devid} == $val) {
3229            probe_superio($addrreg, $datareg, $chip);
3230            return 1;
3231        }
3232    }
3233
3234    printf("Found unknown non-standard chip with ID 0x%02x\n", $val);
3235    return 1;
3236}
3237
3238sub scan_superio
3239{
3240  my ($addrreg, $datareg) = @_;
3241  my ($val, $found);
3242
3243  printf("Probing for Super-I/O at 0x\%x/0x\%x\n", $addrreg, $datareg);
3244
3245  $| = 1;
3246# reset state to avoid false positives
3247  exit_superio($addrreg, $datareg);
3248  FAMILY:
3249  foreach my $family (@superio_ids) {
3250    printf("\%-60s", "Trying family `$family->{family}'... ");
3251# write the password
3252    foreach $val (@{$family->{enter}->{$addrreg}}) {
3253      outb($addrreg, $val);
3254    }
3255# call the non-standard detection routine first if it exists
3256    if (defined($family->{ns_detect}) && 
3257        &{$family->{ns_detect}}($addrreg, $datareg, $family->{ns_chips})) {
3258      exit_superio($addrreg, $datareg);
3259      last FAMILY;
3260    }
3261# did it work?
3262    outb($addrreg, $superio{devidreg});
3263    $val = inb($datareg);
3264    outb($addrreg, $superio{devidreg} + 1);
3265    $val = ($val << 8) | inb($datareg);
3266    if ($val == 0x0000 || $val == 0xffff) {
3267      print "No\n";
3268      next FAMILY;
3269    }
3270    print "Yes\n";
3271
3272    $found = 0;
3273    foreach my $chip (@{$family->{chips}}) {
3274      if (($chip->{devid} > 0xff && ($val & ($chip->{devid_mask} || 0xffff)) == $chip->{devid})
3275       || ($chip->{devid} <= 0xff && ($val >> 8) == $chip->{devid})) {
3276        probe_superio($addrreg, $datareg, $chip);
3277        $found++;
3278      }
3279    }
3280
3281    if (!$found) {
3282      printf("Found unknown chip with ID 0x%04x\n", $val);
3283      # Guess if a logical device could correspond to sensors
3284      guess_superio_ld($addrreg, $datareg, $family->{guess})
3285        if defined $family->{guess};
3286    }
3287
3288    exit_superio($addrreg, $datareg);
3289    last FAMILY;
3290  }
3291  $| = 0;
3292}
3293
3294
3295sub scan_cpu($)
3296{
3297  my $entry = shift;
3298  my $confidence;
3299
3300  printf("\%-60s", "$entry->{name}... ");
3301  if (defined ($confidence = $entry->{detect}())) {
3302    print "Success!\n";
3303    printf "    (driver `%s')\n", $entry->{driver};
3304    my $new_hash = {
3305      conf => $confidence,
3306      chipname => $entry->{name},
3307    };
3308    add_isa_to_chips_detected(undef, $entry->{driver}, $new_hash);
3309  } else {
3310    print "No\n";
3311  }
3312}
3313
3314
3315##################
3316# CHIP DETECTION #
3317##################
3318
3319# This routine allows you to select which chips are optionally added to the
3320# chip detection list. The most common use is to allow for different chip
3321# detection/drivers based on different linux kernels
3322# This routine follows the pattern of the SiS adapter special cases
3323sub chip_special_cases
3324{
3325        # Based on the kernel, add the appropriate chip structure to the
3326        # chip_ids detection list
3327        if (kernel_version_at_least(2, 6, 0)) {
3328                push @chip_ids, @chip_kern26_ids;
3329        } else {
3330                push @chip_ids, @chip_kern24_ids;
3331        }
3332}
3333
3334# Each function returns a confidence value. The higher this value, the more
3335# sure we are about this chip. A Winbond W83781D, for example, will be
3336# detected as a LM78 too; but as the Winbond detection has a higher confidence
3337# factor, you should identify it as a Winbond.
3338
3339# Each function returns a list. The first element is the confidence value;
3340# Each element after it is an SMBus address. In this way, we can detect
3341# chips with several SMBus addresses. The SMBus address for which the
3342# function was called is never returned.
3343
3344# If there are devices which get confused if they are only read from, then
3345# this program will surely confuse them. But we guarantee never to write to
3346# any of these devices.
3347
3348
3349# $_[0]: A reference to the file descriptor to access this chip.
3350# $_[1]: Address
3351# Returns: undef if not detected, (7) if detected.
3352# Registers used: 0x58
3353sub mtp008_detect
3354{
3355  my ($file,$addr) = @_;
3356  return if (i2c_smbus_read_byte_data($file,0x58)) != 0xac;
3357  return (8);
3358}
3359 
3360# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3361# $_[1]: A reference to the file descriptor to access this chip.
3362# $_[2]: Address
3363# Returns: undef if not detected, (6) if detected.
3364# Registers used:
3365#   0x40: Configuration
3366#   0x48: Full I2C Address
3367#   0x49: Device ID
3368# Note that this function is always called through a closure, so the
3369# arguments are shifted by one place.
3370sub lm78_detect
3371{
3372  my $reg;
3373  my ($chip,$file,$addr) = @_;
3374  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
3375  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
3376  $reg = i2c_smbus_read_byte_data($file,0x49);
3377  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
3378                    ($chip == 1 and $reg == 0x40) or
3379                    ($chip == 2 and ($reg & 0xfe) == 0xc0);
3380  return (6);
3381}
3382
3383# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3384# $_[1]: Address
3385# Returns: undef if not detected, 6 if detected.
3386# Note: Only address 0x290 is scanned at this moment.
3387sub lm78_isa_detect
3388{
3389  my ($chip,$addr) = @_ ;
3390  my $val = inb ($addr + 1);
3391  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
3392            inb ($addr + 7) != $val;
3393
3394  $val = inb($addr + 5);
3395  outb($addr + 5, ~$val & 0x7f);
3396  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
3397    outb($addr+5,$val);
3398    return;
3399  }
3400  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
3401  return unless (&$readproc(0x40) & 0x80) == 0x00;
3402  my $reg = &$readproc(0x49);
3403  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
3404                ($chip == 1 and $reg == 0x40) or
3405                ($chip == 2 and ($reg & 0xfe) == 0xc0);
3406
3407  # Explicitly prevent misdetection of Winbond chips
3408  $reg = &$readproc(0x4f);
3409  return if $reg == 0xa3 || $reg == 0x5c;
3410
3411  # Explicitly prevent misdetection of ITE chips
3412  $reg = &$readproc(0x58);
3413  return if $reg == 0x90;
3414
3415  return 6;
3416}
3417
3418
3419# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
3420# $_[1]: ISA address
3421# $_[2]: I2C file handle
3422# $_[3]: I2C address
3423sub lm78_alias_detect
3424{
3425  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
3426  my $i;
3427  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
3428  return 0 unless &$readproc(0x48) == $i2c_addr;
3429  for ($i = 0x2b; $i <= 0x3d; $i ++) {
3430    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
3431  }
3432  return 1;
3433}
3434
3435# $_[0]: Chip to detect (0 = LM75, 1 = DS75)
3436# $_[1]: A reference to the file descriptor to access this chip.
3437# $_[2]: Address (unused)
3438# Returns: undef if not detected, 3 or 6 if detected;
3439#   6 means that the temperatures make sense;
3440#   3 means that the temperatures look strange;
3441# Registers used:
3442#   0x00: Temperature
3443#   0x01: Configuration
3444#   0x02: Hysteresis
3445#   0x03: Overtemperature Shutdown
3446#   0x04-0x07: No registers
3447# The first detection step is based on the fact that the LM75 has only
3448# four registers, and cycles addresses over 8-byte boundaries. We use the
3449# 0x04-0x07 addresses (unused) to improve the reliability. These are not
3450# real registers and will always return the last returned value. This isn't
3451# documented.
3452# Note that register 0x00 may change, so we can't use the modulo trick on it.
3453# The DS75 is a bit different, it doesn't cycle over 8-byte boundaries, and
3454# all register addresses from 0x04 to 0x0f behave like 0x04-0x07 do for
3455# the LM75.
3456sub lm75_detect
3457{
3458  my $i;
3459  my ($chip, $file, $addr) = @_;
3460  my $cur = i2c_smbus_read_word_data($file,0x00);
3461  my $conf = i2c_smbus_read_byte_data($file,0x01);
3462
3463  my $hyst = i2c_smbus_read_word_data($file,0x02);
3464  my $maxreg = $chip == 1 ? 0x0f : 0x07;
3465  for $i (0x04 .. $maxreg) {
3466    return if i2c_smbus_read_word_data($file, $i) != $hyst;
3467  }
3468
3469  my $os = i2c_smbus_read_word_data($file,0x03);
3470  for $i (0x04 .. $maxreg) {
3471    return if i2c_smbus_read_word_data($file, $i) != $os;
3472  }
3473
3474  if ($chip == 0) {
3475    for ($i = 8; $i <= 248; $i += 40) {
3476      return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf
3477             or i2c_smbus_read_word_data($file, $i + 0x02) != $hyst
3478             or i2c_smbus_read_word_data($file, $i + 0x03) != $os;
3479    }
3480  }
3481
3482  # All registers hold the same value, obviously a misdetection
3483  return if $conf == ($cur & 0xff) and $cur == $hyst
3484    and $cur == $os;
3485
3486  $cur = swap_bytes($cur);
3487  $hyst = swap_bytes($hyst);
3488  $os = swap_bytes($os);
3489  # Unused bits
3490  return if $chip == 0 and ($conf & 0xe0);
3491  return if $chip == 1 and ($conf & 0x80);
3492
3493  $cur = $cur >> 8;
3494  $hyst = $hyst >> 8;
3495  $os = $os >> 8;
3496  # Most probable value ranges
3497  return 6 if $cur <= 100 and ($hyst >= 10 && $hyst <= 125)
3498    and ($os >= 20 && $os <= 127) and $hyst < $os;
3499  return 3;
3500}
3501
3502# $_[0]: A reference to the file descriptor to access this chip.
3503# $_[1]: Address
3504# Returns: undef if not detected, 3 or 6 if detected;
3505#   6 means that the temperatures make sense;
3506#   3 means that the temperatures look strange;
3507# Registers used:
3508#   0x00: Temperature
3509#   0x01: Configuration
3510#   0x02: Hysteresis
3511#   0x03: Overtemperature Shutdown
3512#   0x04: Low limit
3513#   0x05: High limit
3514#   0x04-0x07: No registers
3515# The first detection step is based on the fact that the LM77 has only
3516# six registers, and cycles addresses over 8-byte boundaries. We use the
3517# 0x06-0x07 addresses (unused) to improve the reliability. These are not
3518# real registers and will always return the last returned value. This isn't
3519# documented.
3520# Note that register 0x00 may change, so we can't use the modulo trick on it.
3521sub lm77_detect
3522{
3523  my $i;
3524  my ($file,$addr) = @_;
3525  my $cur = i2c_smbus_read_word_data($file,0x00);
3526  my $conf = i2c_smbus_read_byte_data($file,0x01);
3527  my $hyst = i2c_smbus_read_word_data($file,0x02);
3528  my $os = i2c_smbus_read_word_data($file,0x03);
3529
3530  my $low = i2c_smbus_read_word_data($file,0x04);
3531  return if i2c_smbus_read_word_data($file,0x06) != $low;
3532  return if i2c_smbus_read_word_data($file,0x07) != $low;
3533
3534  my $high = i2c_smbus_read_word_data($file,0x05);
3535  return if i2c_smbus_read_word_data($file,0x06) != $high;
3536  return if i2c_smbus_read_word_data($file,0x07) != $high;
3537
3538  for ($i = 8; $i <= 248; $i += 40) {
3539    return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf;
3540    return if i2c_smbus_read_word_data($file, $i + 0x02) != $hyst;
3541    return if i2c_smbus_read_word_data($file, $i + 0x03) != $os;
3542    return if i2c_smbus_read_word_data($file, $i + 0x04) != $low;
3543    return if i2c_smbus_read_word_data($file, $i + 0x05) != $high;
3544  }
3545
3546  # All registers hold the same value, obviously a misdetection
3547  return if $conf == ($cur & 0xff) and $cur == $hyst
3548    and $cur == $os and $cur == $low and $cur == $high;
3549
3550  $cur = swap_bytes($cur);
3551  $os = swap_bytes($os);
3552  $hyst = swap_bytes($hyst);
3553  $low = swap_bytes($low);
3554  $high = swap_bytes($high);
3555  # Unused bits
3556  return if ($conf & 0xe0)
3557    or (($cur >> 12) != 0 && ($cur >> 12) != 0xf)
3558    or (($hyst >> 12) != 0 && ($hyst >> 12) != 0xf)
3559    or (($os >> 12) != 0 && ($os >> 12) != 0xf)
3560    or (($low >> 12) != 0 && ($low >> 12) != 0xf)
3561    or (($high >> 12) != 0 && ($high >> 12) != 0xf);
3562
3563  $cur /= 16;
3564  $hyst /= 16;
3565  $os /= 16;
3566  $high /= 16;
3567  $low /= 16;
3568
3569  # Most probable value ranges
3570  return 6 if $cur <= 100 and $hyst <= 40
3571    and ($os >= 20 && $os <= 127) and ($high >= 20 && $high <= 127);
3572  return 3;
3573}
3574
3575# $_[0]: Chip to detect (0 = LM92, 1 = LM76, 2 = MAX6633/MAX6634/MAX6635)
3576# $_[1]: A reference to the file descriptor to access this chip.
3577# $_[2]: Address
3578# Returns: undef if not detected, 2 or 4 if detected;
3579# Registers used:
3580#   0x01: Configuration (National Semiconductor only)
3581#   0x02: Hysteresis
3582#   0x03: Critical Temp
3583#   0x04: Low Limit
3584#   0x05: High Limit
3585#   0x07: Manufacturer ID (LM92 only)
3586# One detection step is based on the fact that the LM92 and clones have a
3587# limited number of registers, which cycle modulo 16 address values.
3588# Note that register 0x00 may change, so we can't use the modulo trick on it.
3589sub lm92_detect
3590{
3591  my ($chip, $file, $addr) = @_;
3592
3593  my $conf = i2c_smbus_read_byte_data($file, 0x01);
3594  my $hyst = i2c_smbus_read_word_data($file, 0x02);
3595  my $crit = i2c_smbus_read_word_data($file, 0x03);
3596  my $low = i2c_smbus_read_word_data($file, 0x04);
3597  my $high = i2c_smbus_read_word_data($file, 0x05);
3598
3599  return if $conf == 0 and $hyst == 0 and $crit == 0
3600        and $low == 0 and $high == 0;
3601
3602  return if $chip == 0
3603        and i2c_smbus_read_word_data($file, 0x07) != 0x0180;
3604 
3605  return if ($chip == 0 || $chip == 1)
3606        and ($conf & 0xE0);
3607
3608  for (my $i = 0; $i < 8; $i++) {
3609    return if i2c_smbus_read_byte_data($file, $i*16+0x01) != $conf;
3610    return if i2c_smbus_read_word_data($file, $i*16+0x02) != $hyst;
3611    return if i2c_smbus_read_word_data($file, $i*16+0x03) != $crit;
3612    return if i2c_smbus_read_word_data($file, $i*16+0x04) != $low;
3613    return if i2c_smbus_read_word_data($file, $i*16+0x05) != $high;
3614  }
3615 
3616  foreach my $temp ($hyst, $crit, $low, $high) {
3617    return if $chip == 2 and ($temp & 0x7F00);
3618    return if $chip != 2 and ($temp & 0x0700);
3619  }
3620
3621  return 4 if $chip == 0;
3622  return 2;
3623}
3624 
3625# $_[0]: A reference to the file descriptor to access this chip.
3626# $_[1]: Address
3627# Returns: undef if not detected, 3 if detected
3628# Registers used:
3629#   0xAA: Temperature
3630#   0xA1: High limit
3631#   0xA2: Low limit
3632#   0xAC: Configuration
3633# Detection is weak. We check if bit 4 (NVB) is clear, because it is
3634# unlikely to be set (would mean that EEPROM is currently being accessed).
3635# Temperature checkings will hopefully prevent LM75 or other chips from
3636# being detected as a DS1621.
3637sub ds1621_detect
3638{
3639  my $i;
3640  my ($file,$addr) = @_;
3641  my $temp = i2c_smbus_read_word_data($file,0xAA);
3642  my $high = i2c_smbus_read_word_data($file,0xA1);
3643  my $low = i2c_smbus_read_word_data($file,0xA2);
3644  return if ($temp | $high | $low) & 0x7F00;
3645  my $conf = i2c_smbus_read_byte_data($file,0xAC);
3646  return if ($temp == 0 && $high == 0 && $low == 0 && $conf == 0);
3647  return 3 if ($conf & 0x10) == 0x00;
3648  return;
3649}
3650
3651# $_[0]: A reference to the file descriptor to access this chip.
3652# $_[1]: Address
3653# Returns: undef if not detected, 1 to 3 if detected.
3654# Registers used:
3655#   0x00: Configuration register
3656#   0x02: Interrupt state register
3657#   0x2a-0x3d: Limits registers
3658# This one is easily misdetected since it doesn't provide identification
3659# registers. So we have to use some tricks:
3660#   - 6-bit addressing, so limits readings modulo 0x40 should be unchanged
3661#   - positive temperature limits
3662#   - limits order correctness
3663# Hopefully this should limit the rate of false positives, without increasing
3664# the rate of false negatives.
3665# Thanks to Lennard Klein for testing on a non-LM80 chip, which was
3666# previously misdetected, and isn't anymore. For reference, it scored
3667# a final confidence of 0, and changing from strict limit comparisons
3668# to loose comparisons did not change the score.
3669sub lm80_detect
3670{
3671  my ($i,$reg);
3672  my ($file,$addr) = @_;
3673
3674  return if (i2c_smbus_read_byte_data($file,0x00) & 0x80) != 0;
3675  return if (i2c_smbus_read_byte_data($file,0x02) & 0xc0) != 0;
3676
3677  for ($i = 0x2a; $i <= 0x3d; $i++) {
3678    $reg = i2c_smbus_read_byte_data($file,$i);
3679    return if i2c_smbus_read_byte_data($file,$i+0x40) != $reg;
3680    return if i2c_smbus_read_byte_data($file,$i+0x80) != $reg;
3681    return if i2c_smbus_read_byte_data($file,$i+0xc0) != $reg;
3682  }
3683 
3684  # Refine a bit by checking wether limits are in the correct order
3685  # (min<max for voltages, hyst<max for temperature). Since it is still
3686  # possible that the chip is an LM80 with limits not properly set,
3687  # a few "errors" are tolerated.
3688  my $confidence = 0;
3689  for ($i = 0x2a; $i <= 0x3a; $i++) {
3690    $confidence++
3691      if i2c_smbus_read_byte_data($file,$i) < i2c_smbus_read_byte_data($file,$i+1);
3692  }
3693  # hot temp<OS temp
3694  $confidence++
3695    if i2c_smbus_read_byte_data($file,0x38) < i2c_smbus_read_byte_data($file,0x3a);
3696
3697  # Negative temperature limits are unlikely.
3698  for ($i = 0x3a; $i <= 0x3d; $i++) {
3699    $confidence++ if (i2c_smbus_read_byte_data($file,$i) & 0x80) == 0;
3700  }
3701
3702  # $confidence is between 0 and 14
3703  $confidence = ($confidence >> 1) - 4;
3704  # $confidence is now between -4 and 3
3705
3706  return unless $confidence > 0;
3707
3708  return $confidence;
3709}
3710
3711# $_[0]: Chip to detect
3712#   (0 = LM82/LM83)
3713# $_[1]: A reference to the file descriptor to access this chip.
3714# $_[2]: Address
3715# Returns: undef if not detected, 4 to 8 if detected.
3716# Registers used:
3717#   0x02: Status 1
3718#   0x03: Configuration
3719#   0x04: Company ID of LM84
3720#   0x35: Status 2
3721#   0xfe: Manufacturer ID
3722#   0xff: Chip ID / die revision
3723# We can use the LM84 Company ID register because the LM83 and the LM82 are
3724# compatible with the LM84.
3725# The LM83 chip ID is missing from the datasheet and was contributed by
3726# Magnus Forsstrom: 0x03.
3727# At least some revisions of the LM82 seem to be repackaged LM83, so they
3728# have the same chip ID, and temp2/temp4 will be stuck in "OPEN" state.
3729# For this reason, we don't even try to distinguish between both chips.
3730# Thanks to Ben Gardner for reporting.
3731sub lm83_detect
3732{
3733  my ($chip, $file) = @_;
3734  return if i2c_smbus_read_byte_data($file,0xfe) != 0x01;
3735  my $chipid = i2c_smbus_read_byte_data($file,0xff);
3736  return if $chipid != 0x01 && $chipid != 0x03;
3737
3738  my $confidence = 4;
3739  $confidence++
3740    if (i2c_smbus_read_byte_data($file,0x02) & 0xa8) == 0x00;
3741  $confidence++
3742    if (i2c_smbus_read_byte_data($file,0x03) & 0x41) == 0x00;
3743  $confidence++
3744    if i2c_smbus_read_byte_data($file,0x04) == 0x00;
3745  $confidence++
3746    if (i2c_smbus_read_byte_data($file,0x35) & 0x48) == 0x00;
3747
3748  return $confidence;
3749}
3750
3751# $_[0]: Chip to detect
3752#   (0 = LM90, 1=LM89/LM99, 2=LM86, 3=ADM1032, 4=MAX6657/MAX6658/MAX6659,
3753#    5 = ADT7461, 6 = MAX6648/MAX6692, 7 = MAX6680/MAX6681)
3754# $_[1]: A reference to the file descriptor to access this chip.
3755# $_[2]: Address
3756# Returns: undef if not detected, 4, 6 or 8 if detected.
3757#   The Maxim chips MAX6657, MAX6658 and MAX6659 have a low confidence
3758#   value (4) because they don't have a die revision register.
3759# Registers used:
3760#   0x03: Configuration
3761#   0x04: Conversion rate
3762#   0xfe: Manufacturer ID
3763#   0xff: Chip ID / die revision
3764sub lm90_detect
3765{
3766  my ($chip, $file, $addr) = @_;
3767  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
3768  my $cid = i2c_smbus_read_byte_data($file, 0xff);
3769  my $conf = i2c_smbus_read_byte_data($file, 0x03);
3770  my $rate = i2c_smbus_read_byte_data($file, 0x04);
3771
3772  if ($chip == 0) {
3773    return if ($conf & 0x2a) != 0;
3774    return if $rate > 0x09;
3775    return if $mid != 0x01;     # National Semiconductor
3776    return 8 if $cid == 0x21;   # LM90
3777    return 6 if ($cid & 0x0f) == 0x20;
3778  }
3779  if ($chip == 1) {
3780    return if ($conf & 0x2a) != 0;
3781    return if $rate > 0x09;
3782    return if $mid != 0x01;     # National Semiconductor
3783    return 8 if $addr == 0x4c and $cid == 0x31; # LM89/LM99
3784    return 8 if $addr == 0x4d and $cid == 0x34; # LM89-1/LM99-1
3785    return 6 if ($cid & 0x0f) == 0x30;
3786  }
3787  if ($chip == 2) {
3788    return if ($conf & 0x2a) != 0;
3789    return if $rate > 0x09;
3790    return if $mid != 0x01;     # National Semiconductor
3791    return 8 if $cid == 0x11;   # LM86
3792    return 6 if ($cid & 0xf0) == 0x10;
3793  }
3794  if ($chip == 3) {
3795    return if ($conf & 0x3f) != 0;
3796    return if $rate > 0x0a;
3797    return if $mid != 0x41;     # Analog Devices
3798    return 8 if ($cid & 0xf0) == 0x40; # ADM1032
3799  }
3800  if ($chip == 4) {
3801    return if ($conf & 0x1f) != ($mid & 0x0f); # No low nibble,
3802                                               # returns previous low nibble
3803    return if $rate > 0x09;
3804    return if $mid != 0x4d;     # Maxim
3805    return if $cid != 0x4d;     # No register, returns previous value
3806    return 4;
3807  }
3808  if ($chip == 5) {
3809    return if ($conf & 0x1b) != 0;
3810    return if $rate > 0x0a;
3811    return if $mid != 0x41;     # Analog Devices
3812    return 8 if $cid == 0x61;   # ADT7461
3813  }
3814  if ($chip == 6) {
3815    return if ($conf & 0x3f) != 0;
3816    return if $rate > 0x07;
3817    return if $mid != 0x4d;     # Maxim
3818    return if $cid != 0x59;     # MAX6648/MAX6692
3819    return 8;
3820  }   
3821  if ($chip == 7) {
3822    return if ($conf & 0x03) != 0;
3823    return if $rate > 0x07;
3824    return if $mid != 0x4d;     # Maxim
3825    return if $cid != 0x01;     # MAX6680/MAX6681
3826    return 6;
3827  }
3828  return;
3829}
3830
3831# $_[0]: Chip to detect
3832#   (1 = LM63, 2 = F75363SG)
3833# $_[1]: A reference to the file descriptor to access this chip.
3834# $_[2]: Address (unused)
3835# Returns: undef if not detected, 8 if detected.
3836# Registers used:
3837#   0xfe: Manufacturer ID
3838#   0xff: Chip ID / die revision
3839#   0x03: Configuration (two or three unused bits)
3840#   0x16: Alert mask (two or three unused bits)
3841#   0x03-0x0e: Mirrored registers (five pairs)
3842sub lm63_detect
3843{
3844  my ($chip, $file, $addr) = @_;
3845
3846  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
3847  my $cid = i2c_smbus_read_byte_data($file, 0xff);
3848  my $conf = i2c_smbus_read_byte_data($file, 0x03);
3849  my $mask = i2c_smbus_read_byte_data($file, 0x16);
3850
3851  if ($chip == 1) {
3852    return if $mid != 0x01    # National Semiconductor
3853           || $cid != 0x41;   # LM63
3854    return if ($conf & 0x18) != 0x00
3855           || ($mask & 0xa4) != 0xa4;
3856  } elsif ($chip == 2) {
3857    return if $mid != 0x23    # Fintek
3858           || $cid != 0x20;   # F75363SG
3859    return if ($conf & 0x1a) != 0x00
3860           || ($mask & 0x84) != 0x00; 
3861  }
3862
3863  # For compatibility with the LM86, some registers are mirrored
3864  # to alternative locations
3865  return if $conf != i2c_smbus_read_byte_data($file, 0x09);
3866  foreach my $i (0x04, 0x05, 0x07, 0x08) {
3867    return if i2c_smbus_read_byte_data($file, $i)
3868           != i2c_smbus_read_byte_data($file, $i+6);
3869  }
3870
3871  return 8;
3872}
3873
3874# $_[0]: Chip to detect
3875#   (0 = ADM1029)
3876# $_[1]: A reference to the file descriptor to access this chip.
3877# $_[2]: Address (unused)
3878# Returns: undef if not detected, 6 if detected.
3879# Registers used:
3880#   0x02, 0x03: Fan support
3881#   0x06: Temperature support
3882#   0x07, 0x08, 0x09: Fan config
3883#   0x0d: Manufacturer ID
3884#   0x0e: Chip ID / die revision
3885sub adm1029_detect
3886{
3887  my ($chip, $file, $addr) = @_;
3888  my $mid = i2c_smbus_read_byte_data($file, 0x0d);
3889  my $cid = i2c_smbus_read_byte_data($file, 0x0e);
3890  my $cfg;
3891
3892  if ($chip == 0) {
3893    return unless $mid == 0x41;             # Analog Devices
3894    return unless ($cid & 0xF0) == 0x00;    # ADM1029
3895
3896    # Extra check on unused bits
3897    $cfg = i2c_smbus_read_byte_data($file, 0x02);
3898    return unless $cfg == 0x03;
3899    $cfg = i2c_smbus_read_byte_data($file, 0x06);
3900    return unless ($cfg & 0xF9) == 0x01;
3901    foreach my $reg (0x03, 0x07, 0x08, 0x09) {
3902      $cfg = i2c_smbus_read_byte_data($file, $reg);
3903      return unless ($cfg & 0xFC) == 0x00;
3904    }
3905
3906    return 7;
3907  }
3908  return;
3909}
3910
3911# $_[0]: Chip to detect
3912#   (0 = ADM1030, 1=ADM1031)
3913# $_[1]: A reference to the file descriptor to access this chip.
3914# $_[2]: Address
3915# Returns: undef if not detected, 3 to 7 (ADM1031) or 9 (ADM1030)
3916#          if detected.
3917# Registers used:
3918#   0x01: Config 2
3919#   0x03: Status 2
3920#   0x0d, 0x0e, 0x0f: Temperature offsets
3921#   0x22: Fan speed config
3922#   0x3d: Chip ID
3923#   0x3e: Manufacturer ID
3924#   0x3f: Die revision
3925sub adm1031_detect
3926{
3927  my ($chip, $file, $addr) = @_;
3928  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3929  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3930  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3931  my $conf2 = i2c_smbus_read_byte_data($file, 0x01);
3932  my $stat2 = i2c_smbus_read_byte_data($file, 0x03);
3933  my $fsc = i2c_smbus_read_byte_data($file, 0x22);
3934  my $lto = i2c_smbus_read_byte_data($file, 0x0d);
3935  my $r1to = i2c_smbus_read_byte_data($file, 0x0e);
3936  my $r2to = i2c_smbus_read_byte_data($file, 0x0f);
3937  my $confidence = 3;
3938
3939  if ($chip == 0) {
3940    return if $mid != 0x41;     # Analog Devices
3941    return if $cid != 0x30;     # ADM1030
3942    $confidence++ if ($drev & 0x70) == 0x00;
3943    $confidence++ if ($conf2 & 0x4A) == 0x00;
3944    $confidence++ if ($stat2 & 0x3F) == 0x00;
3945    $confidence++ if ($fsc & 0xF0) == 0x00;
3946    $confidence++ if ($lto & 0x70) == 0x00;
3947    $confidence++ if ($r1to & 0x70) == 0x00;
3948    return $confidence;
3949  }
3950  if ($chip == 1) {
3951    return if $mid != 0x41;     # Analog Devices
3952    return if $cid != 0x31;     # ADM1031
3953    $confidence++ if ($drev & 0x70) == 0x00;
3954    $confidence++ if ($lto & 0x70) == 0x00;
3955    $confidence++ if ($r1to & 0x70) == 0x00;
3956    $confidence++ if ($r2to & 0x70) == 0x00;
3957    return $confidence;
3958  }
3959  return;
3960}
3961
3962# $_[0]: Chip to detect
3963#   (0 = ADM1033, 1 = ADM1034)
3964# $_[1]: A reference to the file descriptor to access this chip.
3965# $_[2]: Address (unused)
3966# Returns: undef if not detected, 4 or 6 if detected.
3967# Registers used:
3968#   0x3d: Chip ID
3969#   0x3e: Manufacturer ID
3970#   0x3f: Die revision
3971sub adm1034_detect
3972{
3973  my ($chip, $file, $addr) = @_;
3974  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
3975  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
3976  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
3977
3978  if ($chip == 0) {
3979    return if $mid != 0x41;     # Analog Devices
3980    return if $cid != 0x33;     # ADM1033
3981    return if ($drev & 0xf8) != 0x00;
3982    return 6 if $drev == 0x02;
3983    return 4;
3984  }
3985  if ($chip == 1) {
3986    return if $mid != 0x41;     # Analog Devices
3987    return if $cid != 0x34;     # ADM1034
3988    return if ($drev & 0xf8) != 0x00;
3989    return 6 if $drev == 0x02;
3990    return 4;
3991  }
3992  return
3993}
3994
3995# $_[0]: Chip to detect
3996#   (0 = ADT7467/ADT7468, 1 = ADT7476, 2 = ADT7462, 3 = ADT7466,
3997#    4 = ADT7470)
3998# $_[1]: A reference to the file descriptor to access this chip.
3999# $_[2]: Address
4000# Returns: undef if not detected, 5 or 7 if detected.
4001# Registers used:
4002#   0x3d: Chip ID
4003#   0x3e: Manufacturer ID
4004#   0x3f: Die revision
4005sub adt7467_detect
4006{
4007  my ($chip, $file, $addr) = @_;
4008  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
4009  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
4010  my $drev = i2c_smbus_read_byte_data($file, 0x3f);
4011
4012  if ($chip == 0) {
4013    return if $mid != 0x41;     # Analog Devices
4014    return if $cid != 0x68;     # ADT7467
4015    return if ($drev & 0xf0) != 0x70;
4016    return 7 if ($drev == 0x71 || $drev == 0x72);
4017    return 5;
4018  }
4019  if ($chip == 1) {
4020    return if $mid != 0x41;     # Analog Devices
4021    return if $cid != 0x76;     # ADT7476
4022    return if ($drev & 0xf0) != 0x60;
4023    return 7 if ($drev == 0x69);
4024    return 5;
4025  }
4026  if ($chip == 2) {
4027    return if $mid != 0x41;     # Analog Devices
4028    return if $cid != 0x62;     # ADT7462
4029    return if ($drev & 0xf0) != 0x00;
4030    return 7 if ($drev == 0x04);
4031    return 5;
4032  }
4033  if ($chip == 3) {
4034    return if $mid != 0x41;     # Analog Devices
4035    return if $cid != 0x66;     # ADT7466
4036    return if ($drev & 0xf0) != 0x00;
4037    return 7 if ($drev == 0x02);
4038    return 5;
4039  }
4040  if ($chip == 4) {
4041    return if $mid != 0x41;     # Analog Devices
4042    return if $cid != 0x70;     # ADT7470
4043    return if ($drev & 0xf0) != 0x00;
4044    return 7 if ($drev == 0x00);
4045    return 5;
4046  }
4047  return
4048}
4049
4050# $_[0]: Chip to detect
4051#   (0 = ADT7473, 1 = ADT7475)
4052# $_[1]: A reference to the file descriptor to access this chip.
4053# $_[2]: Address (unused)
4054# Returns: undef if not detected, 5 if detected.
4055# Registers used:
4056#   0x3d: Chip ID
4057#   0x3e: Manufacturer ID
4058sub adt7473_detect
4059{
4060  my ($chip, $file, $addr) = @_;
4061  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
4062  my $cid = i2c_smbus_read_byte_data($file, 0x3d);
4063
4064  if ($chip == 0) {
4065    return if $mid != 0x41;     # Analog Devices
4066    return if $cid != 0x73;     # ADT7473
4067    return 5;
4068  }
4069  if ($chip == 1) {
4070    return if $mid != 0x41;     # Analog Devices
4071    return if $cid != 0x75;     # ADT7475
4072    return 5;
4073  }
4074  return
4075}
4076
4077# $_[0]: Chip to detect
4078#   (0 = aSC7512, 1 = aSC7611, 2 = aSC7621)
4079# $_[1]: A reference to the file descriptor to access this chip.
4080# $_[2]: Address (unused)
4081# Returns: undef if not detected, 1 if detected.
4082# Registers used:
4083#   0x3e: Manufacturer ID (0x61)
4084#   0x3f: Version
4085
4086sub andigilog_detect
4087{
4088  my ($chip, $file, $addr) = @_;
4089  my $mid = i2c_smbus_read_byte_data($file, 0x3e);
4090  my $cid = i2c_smbus_read_byte_data($file, 0x3f);
4091
4092  return if ($mid != 0x61);
4093
4094  if ($chip == 0) {
4095    return if $cid != 0x62;
4096    return 5;
4097  }
4098
4099  if ($chip == 1) {
4100    return if $cid != 0x69;
4101    return 5;
4102  }
4103
4104  if ($chip == 2) {
4105    return if $cid != 0x6C;
4106    return 5;
4107  }
4108
4109  return;
4110}
4111
4112# $_[0]: Chip to detect
4113#   (0 = aSC7511)
4114# $_[1]: A reference to the file descriptor to access this chip.
4115# $_[2]: Address (unused)
4116# Returns: undef if not detected, 1 if detected.
4117# Registers used:
4118#   0xfe: Manufacturer ID
4119#   0xff: Die Code
4120sub andigilog_aSC7511_detect
4121{
4122  my ($chip, $file, $addr) = @_;
4123  my $mid = i2c_smbus_read_byte_data($file, 0xfe);
4124  my $die = i2c_smbus_read_byte_data($file, 0xff);
4125
4126  if ($chip == 0) {
4127    return if $mid != 0x61;     # Andigilog
4128    if ($die == 0x0) {
4129        return 3;
4130    } else {
4131        return 1;
4132    }
4133  }
4134  return;
4135}
4136
4137# $_[0]: Vendor to check for
4138#   (0x01 = National Semi, 0x41 = Analog Dev, 0x5c = SMSC)
4139# $_[1]: A reference to the file descriptor to access this chip.
4140# #_[2]: Base address.
4141# Returns: undef if not detected, (7) or (8) if detected.
4142# Registers used: 0x3e == Vendor register.
4143#                 0x3d == Device ID register (Analog Devices only).
4144#                 0x3f == Version/Stepping register.
4145# Constants used: 0x01 == National Semiconductor Vendor Id.
4146#                 0x41 == Analog Devices Vendor Id.
4147#                 0x5c == SMSC Vendor Id.
4148#                 0x60 == Version number. The lower 4 stepping
4149#                         bits are masked and ignored.
4150sub lm85_detect
4151{
4152  my ($vendor,$file,$addr) = @_;
4153  return if (i2c_smbus_read_byte_data($file,0x3e)) != $vendor ;
4154  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) != 0x60;
4155
4156  if ($vendor == 0x41) # Analog Devices
4157  {
4158    return if i2c_smbus_read_byte_data($file, 0x3d) != 0x27;
4159    return (8);
4160  }
4161
4162  return (7);
4163}
4164
4165# $_[0]: A reference to the file descriptor to access this chip.
4166# $_[1]: Address
4167# Returns: undef if not detected, (7) if detected.
4168# Registers used: 0x3E, 0x3F
4169#        Assume lower 2 bits of reg 0x3F are for revisions.
4170sub lm87_detect
4171{
4172  my ($file,$addr) = @_;
4173  return if (i2c_smbus_read_byte_data($file,0x3e)) != 0x02;
4174  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xfc) != 0x04;
4175  return (7);
4176}
4177 
4178# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S,
4179#                        3 = W83627HF, 4 = AS99127F (rev.1),
4180#                        5 = AS99127F (rev.2), 6 = ASB100, 7 = W83791D,
4181#                        8 = W83792D, 9 = W83627EHF 10 = W83627DHG)
4182# $_[1]: A reference to the file descriptor to access this chip.
4183# $_[2]: Address
4184# Returns: undef if not detected, (8,addr1,addr2) if detected, but only
4185#          if the LM75 chip emulation is enabled.
4186# Registers used:
4187#   0x48: Full I2C Address
4188#   0x4a: I2C addresses of emulated LM75 chips
4189#   0x4e: Vendor ID byte selection, and bank selection
4190#   0x4f: Vendor ID
4191#   0x58: Device ID (only when in bank 0)
4192# Note: Fails if the W8378xD is not in bank 0!
4193# Note: Detection overrules a previous LM78 detection
4194# Note: Asus chips do not have their I2C address at register 0x48?
4195#       AS99127F rev.1 and ASB100 have 0x00, confirmation wanted for
4196#       AS99127F rev.2.
4197sub w83781d_detect
4198{
4199  my ($reg1,$reg2,@res);
4200  my ($chip,$file,$addr) = @_;
4201
4202  return unless (i2c_smbus_read_byte_data($file,0x48) == $addr)
4203    or ($chip >= 4 && $chip <= 6);
4204
4205  $reg1 = i2c_smbus_read_byte_data($file,0x4e);
4206  $reg2 = i2c_smbus_read_byte_data($file,0x4f);
4207  if ($chip == 4) { # Asus AS99127F (rev.1)
4208    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or 
4209                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x12);
4210  } elsif ($chip == 6) { # Asus ASB100
4211    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0x94) or 
4212                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x06);
4213  } else { # Winbond and Asus AS99127F (rev.2)
4214    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
4215                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
4216  }
4217
4218  return unless ($reg1 & 0x07) == 0x00;
4219
4220  $reg1 = i2c_smbus_read_byte_data($file,0x58);
4221  return if $chip == 0 and ($reg1 != 0x10 && $reg1 != 0x11);
4222  return if $chip == 1 and  $reg1 != 0x30;
4223  return if $chip == 2 and  $reg1 != 0x40;
4224  return if $chip == 3 and  $reg1 != 0x21;
4225  return if $chip == 4 and  $reg1 != 0x31;
4226  return if $chip == 5 and  $reg1 != 0x31;
4227  return if $chip == 6 and  $reg1 != 0x31;
4228  return if $chip == 7 and  $reg1 != 0x71;
4229  return if $chip == 8 and  $reg1 != 0x7a;
4230  return if $chip == 9 and  $reg1 != 0xa1;
4231  return if $chip == 10 and  $reg1 != 0xa2;
4232  $reg1 = i2c_smbus_read_byte_data($file,0x4a);
4233  # Default address is 0x2d
4234  @res = ($addr != 0x2d) ? (7) : (8);
4235  return @res if $chip == 9; # No subclients
4236  push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08;
4237  push @res, (($reg1 & 0x70) >> 4) + 0x48 unless ($reg1 & 0x80 or $chip == 2);
4238  return @res;
4239}
4240 
4241# $_[0]: Chip to detect (0 = W83793)
4242# $_[1]: A reference to the file descriptor to access this chip.
4243# $_[2]: Address
4244# Returns: undef if not detected
4245#          6 if detected and bank different from 0
4246#          (8,addr1,addr2) if detected, band is 0 and LM75 chip emulation
4247#          is enabled
4248# Registers used:
4249#   0x0b: Full I2C Address
4250#   0x0c: I2C addresses of emulated LM75 chips
4251#   0x00: Vendor ID byte selection, and bank selection(Bank 0,1,2)
4252#   0x0d: Vendor ID(Bank 0,1,2)
4253#   0x0e: Device ID(Bank 0,1,2)
4254sub w83793_detect
4255{
4256  my ($bank, $reg, @res);
4257  my ($chip, $file, $addr) = @_;
4258
4259  $bank = i2c_smbus_read_byte_data($file, 0x00);
4260  $reg = i2c_smbus_read_byte_data($file, 0x0d);
4261
4262  return unless (($bank & 0x80) == 0x00 and $reg == 0xa3) or 
4263                (($bank & 0x80) == 0x80 and $reg == 0x5c);
4264
4265  $reg = i2c_smbus_read_byte_data($file, 0x0e);
4266  return if $chip == 0 and $reg != 0x7b;
4267
4268# If bank 0 is selected, we can do more checks
4269  return 6 unless ($bank & 0x07) == 0;
4270  $reg = i2c_smbus_read_byte_data($file, 0x0b);
4271  return unless ($reg == ($addr << 1));
4272
4273  $reg = i2c_smbus_read_byte_data($file, 0x0c);
4274  @res = (8);
4275  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08;
4276  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
4277  return @res;
4278}
4279
4280# $_[0]: A reference to the file descriptor to access this chip.
4281# $_[1]: Address
4282# Returns: undef if not detected, 3 if detected
4283# Registers used:
4284#   0x48: Full I2C Address
4285#   0x4e: Vendor ID byte selection
4286#   0x4f: Vendor ID
4287#   0x58: Device ID
4288# Note that the datasheet was useless and this detection routine
4289# is based on dumps we received from users. Also, the W83781SD is *NOT*
4290# a hardware monitoring chip as far as we know, but we still want to
4291# detect it so that people won't keep reporting it as an unknown chip
4292# we should investigate about.
4293sub w83791sd_detect
4294{
4295  my ($file, $addr) = @_;
4296  my ($reg1, $reg2);
4297
4298  return unless (i2c_smbus_read_byte_data($file, 0x48) == $addr);
4299
4300  $reg1 = i2c_smbus_read_byte_data($file, 0x4e);
4301  $reg2 = i2c_smbus_read_byte_data($file, 0x4f);
4302  return unless (!($reg1 & 0x80) && $reg2 == 0xa3)
4303             || (($reg1 & 0x80) && $reg2 == 0x5c);
4304
4305  $reg1 = i2c_smbus_read_byte_data($file, 0x58);
4306  return unless $reg1 == 0x72;
4307
4308  return 3;
4309}
4310
4311# $_[0]: Chip to detect (0 = ASM58, 1 = AS2K129R, 2 = ???)
4312# $_[1]: A reference to the file descriptor to access this chip
4313# $_[2]: Address (unused)
4314# Returns: undef if not detected, 5 if detected
4315# Registers used:
4316#   0x4e: Vendor ID high byte
4317#   0x4f: Vendor ID low byte
4318#   0x58: Device ID
4319# Note: The values were given by Alex van Kaam, we don't have datasheets
4320#       to confirm.
4321sub mozart_detect
4322{
4323  my ($vid,$dev);
4324  my ($chip,$file,$addr) = @_;
4325
4326  $vid = (i2c_smbus_read_byte_data($file,0x4e) << 8)
4327       +  i2c_smbus_read_byte_data($file,0x4f);
4328  $dev = i2c_smbus_read_byte_data($file,0x58);
4329
4330  return if ($chip == 0) and ($dev != 0x56 || $vid != 0x9436);
4331  return if ($chip == 1) and ($dev != 0x56 || $vid != 0x9406);
4332  return if ($chip == 2) and ($dev != 0x10 || $vid != 0x5ca3);
4333
4334  return 5;
4335}
4336
4337# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF,
4338#                        9 = W83627EHF 10 = W83627DHG)
4339# $_[1]: ISA address
4340# $_[2]: I2C file handle
4341# $_[3]: I2C address
4342sub w83781d_alias_detect
4343{
4344  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
4345  my $i;
4346  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
4347  return 0 unless &$readproc(0x48) == $i2c_addr;
4348  for ($i = 0x2b; $i <= 0x3d; $i ++) {
4349    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
4350  }
4351  return 1;
4352}
4353
4354# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D)
4355# $_[1]: Address
4356# Returns: undef if not detected, (8) if detected.
4357sub w83781d_isa_detect
4358{
4359  my ($chip,$addr) = @_ ;
4360  my ($reg1,$reg2);
4361  my $val = inb ($addr + 1);
4362  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
4363            inb ($addr + 7) != $val;
4364
4365  $val = inb($addr + 5);
4366  outb($addr+5, ~$val & 0x7f);
4367  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
4368    outb($addr+5,$val);
4369    return;
4370  }
4371
4372  my $read_proc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
4373  $reg1 = &$read_proc(0x4e);
4374  $reg2 = &$read_proc(0x4f);
4375  return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
4376                (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
4377  return unless ($reg1 & 0x07) == 0x00;
4378  $reg1 = &$read_proc(0x58);
4379  return if $chip == 0 and  ($reg1 & 0xfe) != 0x10;
4380  return if $chip == 1 and  ($reg1 & 0xfe) != 0x30;
4381
4382  return 8;
4383}
4384
4385# $_[0]: Chip to detect (0 = Revision 0x00, 1 = Revision 0x80)
4386# $_[1]: A reference to the file descriptor to access this chip.
4387# $_[2]: Address
4388# Returns: undef if not detected, (6) if detected.
4389# Registers used:
4390#   0x00: Device ID
4391#   0x01: Revision ID
4392#   0x03: Configuration
4393# Mediocre detection
4394sub gl518sm_detect
4395{
4396  my $reg;
4397  my ($chip,$file,$addr) = @_;
4398  return unless i2c_smbus_read_byte_data($file,0x00) == 0x80;
4399  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
4400  $reg = i2c_smbus_read_byte_data($file,0x01);
4401  return unless ($chip == 0 and $reg == 0x00) or
4402                ($chip == 1 and $reg == 0x80);
4403  return (6);
4404}
4405
4406# $_[0]: A reference to the file descriptor to access this chip.
4407# $_[1]: Address
4408# Returns: undef if not detected, (5) if detected.
4409# Registers used:
4410#   0x00: Device ID
4411#   0x01: Revision ID
4412#   0x03: Configuration
4413# Mediocre detection
4414sub gl520sm_detect
4415{
4416  my ($file,$addr) = @_;
4417  return unless i2c_smbus_read_byte_data($file,0x00) == 0x20;
4418  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
4419  # The line below must be better checked before I dare to use it.
4420  # return unless i2c_smbus_read_byte_data($file,0x01) == 0x00;
4421  return (5);
4422}
4423
4424# $_[0]: A reference to the file descriptor to access this chip.
4425# $_[1]: Address
4426# Returns: undef if not detected, (5) if detected.
4427# Registers used:
4428#   0x00: Device ID
4429# Mediocre detection
4430sub gl525sm_detect
4431{
4432  my ($file,$addr) = @_;
4433  return unless i2c_smbus_read_byte_data($file,0x00) == 0x25;
4434  return (5);
4435}
4436
4437# $_[0]: Chip to detect (0 = ADM9240, 1 = DS1780, 2 = LM81)
4438# $_[1]: A reference to the file descriptor to access this chip.
4439# $_[2]: Address
4440# Returns: undef if not detected, (7) if detected.
4441# Registers used:
4442#   0x3e: Company ID
4443#   0x40: Configuration
4444#   0x48: Full I2C Address
4445# Note: Detection overrules a previous LM78 detection
4446sub adm9240_detect
4447{
4448  my $reg;
4449  my ($chip, $file,$addr) = @_;
4450  $reg = i2c_smbus_read_byte_data($file,0x3e);
4451  return unless ($chip == 0 and $reg == 0x23) or
4452                ($chip == 1 and $reg == 0xda) or
4453                ($chip == 2 and $reg == 0x01);
4454  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4455  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
4456 
4457  return (7);
4458}
4459
4460# $_[0]: Chip to detect (0 = ADM1022, 1 = THMC50, 2 = ADM1028)
4461# $_[1]: A reference to the file descriptor to access this chip.
4462# $_[2]: Address
4463# Returns: undef if not detected, (8) if detected.
4464# Registers used:
4465#   0x3e: Company ID
4466#   0x3f: Revision
4467#   0x40: Configuration
4468# Note: Detection overrules a previous LM78 or ADM9240 detection
4469sub adm1022_detect
4470{
4471  my $reg;
4472  my ($chip, $file,$addr) = @_;
4473  $reg = i2c_smbus_read_byte_data($file,0x3e);
4474  return unless ($chip == 0 and $reg == 0x41) or
4475                ($chip == 1 and $reg == 0x49) or
4476                ($chip == 2 and $reg == 0x41);
4477  $reg = i2c_smbus_read_byte_data($file,0x40);
4478  return if ($reg & 0x10);                      # Soft Reset always reads 0
4479  return if ($chip != 0 and ($reg & 0x80));     # Reserved on THMC50 and ADM1028
4480  $reg = i2c_smbus_read_byte_data($file, 0x3f) & 0xf0;
4481  return unless ($chip == 0 and $reg == 0xc0) or
4482                ($chip == 1 and $reg == 0xc0) or
4483                ($chip == 2 and $reg == 0xd0);
4484  return (8);
4485}
4486
4487# $_[0]: Chip to detect (0 = ADM1025, 1 = NE1619)
4488# $_[1]: A reference to the file descriptor to access this chip.
4489# $_[2]: Address
4490# Returns: undef if not detected, (8) if detected.
4491# Registers used:
4492#   0x3e: Company ID
4493#   0x3f: Revision
4494#   0x40: Configuration
4495#   0x41: Status 1
4496#   0x42: Status 2
4497# Note: Detection overrules a previous LM78 or ADM9240 detection
4498sub adm1025_detect
4499{
4500  my $reg;
4501  my ($chip, $file,$addr) = @_;
4502
4503  $reg = i2c_smbus_read_byte_data($file,0x3e);
4504  return if ($chip == 0) and ($reg != 0x41);
4505  return if ($chip == 1) and ($reg != 0xA1);
4506
4507  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4508  return unless (i2c_smbus_read_byte_data($file,0x41) & 0xC0) == 0x00;
4509  return unless (i2c_smbus_read_byte_data($file,0x42) & 0xBC) == 0x00;
4510  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x20;
4511
4512  return (8);
4513}
4514
4515# $_[0]: Chip to detect (0 = ADM1026)
4516# $_[1]: A reference to the file descriptor to access this chip.
4517# $_[2]: Address
4518# Returns: undef if not detected, (8) if detected.
4519# Registers used:
4520#   0x16: Company ID
4521#   0x17: Revision
4522sub adm1026_detect
4523{
4524  my $reg;
4525  my ($chip, $file,$addr) = @_;
4526  $reg = i2c_smbus_read_byte_data($file,0x16);
4527  return unless ($reg == 0x41);
4528  return unless (i2c_smbus_read_byte_data($file,0x17) & 0xf0) == 0x40;
4529  return (8);
4530}
4531
4532# $_[0]: Chip to detect (0 = ADM1024)
4533# $_[1]: A reference to the file descriptor to access this chip.
4534# $_[2]: Address
4535# Returns: undef if not detected, (8) if detected.
4536# Registers used:
4537#   0x3e: Company ID
4538#   0x3f: Revision
4539#   0x40: Configuration
4540sub adm1024_detect
4541{
4542  my $reg;
4543  my ($chip, $file,$addr) = @_;
4544  $reg = i2c_smbus_read_byte_data($file,0x3e);
4545  return unless ($reg == 0x41);
4546  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
4547  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x10;
4548  return (8);
4549}
4550
4551# $_[0]: Chip to detect
4552#   (0 = ADM1021, 1 = ADM1021A/ADM1023, 2 = MAX1617, 3 = MAX1617A, 4 = THMC10,
4553#    5 = LM84, 6 = GL523, 7 = MC1066)
4554# $_[1]: A reference to the file descriptor to access this chip.
4555# $_[2]: Address
4556# Returns: undef if not detected, 3 if simply detected, 5 if detected and
4557#          manufacturer ID matches, 7 if detected and manufacturer ID and
4558#          revision match
4559# Registers used:
4560#   0x04: Company ID (LM84 only)
4561#   0xfe: Company ID (all but LM84 and MAX1617)
4562#   0xff: Revision (ADM1021, ADM1021A/ADM1023 and MAX1617A)
4563#   0x02: Status
4564#   0x03: Configuration
4565#   0x04: Conversion rate
4566#   0x00-0x01, 0x05-0x08: Temperatures (MAX1617 and LM84)
4567# Note: Especially the MAX1617 has very bad detection; we give it a low
4568# confidence value.
4569sub adm1021_detect
4570{
4571  my ($chip, $file, $addr) = @_;
4572  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
4573  my $rev = i2c_smbus_read_byte_data($file, 0xff);
4574  my $conf = i2c_smbus_read_byte_data($file, 0x03);
4575  my $status = i2c_smbus_read_byte_data($file, 0x02);
4576  my $convrate = i2c_smbus_read_byte_data($file, 0x04);
4577
4578  # Check manufacturer IDs and product revisions when available
4579  return if $chip == 0 and $man_id != 0x41 ||
4580                          ($rev & 0xf0) != 0x00;
4581  return if $chip == 1 and $man_id != 0x41 ||
4582                          ($rev & 0xf0) != 0x30;
4583  return if $chip == 3 and $man_id != 0x4d ||
4584                           $rev != 0x01;
4585  return if $chip == 4 and $man_id != 0x49;
4586  return if $chip == 5 and $convrate != 0x00;
4587  return if $chip == 6 and $man_id != 0x23;
4588  return if $chip == 7 and $man_id != 0x54;
4589
4590  # Check unused bits
4591  if ($chip == 5) # LM84
4592  {
4593    return if ($status & 0xab) != 0;
4594    return if ($conf & 0x7f) != 0;
4595  }
4596  else
4597  {
4598    return if ($status & 0x03) != 0;
4599    return if ($conf & 0x3f) != 0;
4600    return if ($convrate & 0xf8) != 0;
4601  }
4602
4603  # Extra checks for MAX1617 and LM84, since those are often misdetected
4604  # We verify several assertions (6 for the MAX1617, 4 for the LM84) and
4605  # discard the chip if any fail. Note that these checks are not done
4606  # by the adm1021 driver.
4607  if ($chip == 2 || $chip == 5)
4608  {
4609    my $lte = i2c_smbus_read_byte_data($file, 0x00);
4610    my $rte = i2c_smbus_read_byte_data($file, 0x01);
4611    my $lhi = i2c_smbus_read_byte_data($file, 0x05);
4612    my $rhi = i2c_smbus_read_byte_data($file, 0x07);
4613    my $llo = i2c_smbus_read_byte_data($file, 0x06);
4614    my $rlo = i2c_smbus_read_byte_data($file, 0x08);
4615
4616    # If all registers hold the same value, it has to be a misdetection
4617    return if $lte == $rte and $lte == $lhi and $lte == $rhi
4618           and $lte == $llo and $lte == $rlo;
4619
4620    # Negative temperatures
4621    return if ($lte & 0x80) or ($rte & 0x80);
4622    # Negative high limits
4623    return if ($lhi & 0x80) or ($rhi & 0x80);
4624    # Low limits over high limits
4625    if ($chip != 5) # LM84 doesn't have low limits
4626    {
4627      $llo-=256 if ($llo & 0x80);
4628      $rlo-=256 if ($rlo & 0x80);
4629      return if ($llo > $lhi) or ($rlo > $rhi);
4630    }
4631  }
4632
4633  return 3 if ($chip == 2) or ($chip == 5);
4634  return 7 if $chip <= 3;
4635  return 5;
4636}
4637
4638# $_[0]: Chip to detect
4639#   (0 = MAX1668, 1 = MAX1805, 2 = MAX1989)
4640# $_[1]: A reference to the file descriptor to access this chip.
4641#        We may assume an i2c_set_slave_addr was already done.
4642# $_[2]: Address
4643# Returns: undef if not detected, 7 if detected
4644# Registers used:
4645#   0xfe: Company ID
4646#   0xff: Device ID
4647sub max1668_detect
4648{
4649  my ($chip, $file, $addr) = @_;
4650  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
4651  my $dev_id = i2c_smbus_read_byte_data($file, 0xff);
4652
4653  return if $man_id != 0x4d;
4654  return if $chip == 0 and $dev_id != 0x03;
4655  return if $chip == 1 and $dev_id != 0x05;
4656  return if $chip == 2 and $dev_id != 0x0b;
4657
4658  return 7;
4659}
4660
4661# $_[0]: Chip to detect
4662#   (0 = MAX1619)
4663# $_[1]: A reference to the file descriptor to access this chip.
4664# $_[2]: Address
4665# Returns: undef if not detected, 7 if detected
4666# Registers used:
4667#   0xfe: Company ID
4668#   0xff: Device ID
4669#   0x02: Status
4670#   0x03: Configuration
4671#   0x04: Conversion rate
4672sub max1619_detect
4673{
4674  my ($chip, $file, $addr) = @_;
4675  my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
4676  my $dev_id = i2c_smbus_read_byte_data($file, 0xff);
4677  my $conf = i2c_smbus_read_byte_data($file, 0x03);
4678  my $status = i2c_smbus_read_byte_data($file, 0x02);
4679  my $convrate = i2c_smbus_read_byte_data($file, 0x04);
4680
4681  return if $man_id != 0x4D
4682    or $dev_id != 0x04
4683    or ($conf & 0x03)
4684    or ($status & 0x61)
4685    or $convrate >= 8;
4686
4687  return 7;
4688}
4689
4690# $_[0]: A reference to the file descriptor to access this chip.
4691# $_[1]: Address (unused)
4692# Returns: undef if not detected, 6 if detected.
4693# Registers used:
4694#   0x28: User ID
4695#   0x29: User ID2
4696#   0x2A: Version ID
4697
4698sub ite_overclock_detect
4699{
4700  my ($file, $addr) = @_;
4701
4702  my $uid1 = i2c_smbus_read_byte_data($file, 0x28);
4703  my $uid2 = i2c_smbus_read_byte_data($file, 0x29);
4704  return if $uid1 != 0x83
4705         || $uid2 != 0x12;
4706
4707  return 6;
4708}
4709
4710# $_[0]: Chip to detect (0 = IT8712F)
4711# $_[1]: A reference to the file descriptor to access this chip.
4712# $_[2]: Address
4713# Returns: undef if not detected, 7 or 8 if detected (tops LM78).
4714# Registers used:
4715#   0x00: Configuration
4716#   0x48: Full I2C Address
4717#   0x58: Mfr ID
4718#   0x5b: Device ID (not on IT8705)
4719# Note that this function is always called through a closure, so the
4720# arguments are shifted by one place.
4721sub ite_detect
4722{
4723  my $reg;
4724  my ($chip,$file,$addr) = @_;
4725  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
4726  return unless (i2c_smbus_read_byte_data($file, 0x00) & 0x90) == 0x10;
4727  return unless i2c_smbus_read_byte_data($file,0x58) == 0x90;
4728  return if $chip == 0 and i2c_smbus_read_byte_data($file,0x5b) != 0x12;
4729  return (7 + ($addr == 0x2d));
4730}
4731
4732
4733# $_[0]: Chip to detect (0 = IT8712F)
4734# $_[1]: ISA address
4735# $_[2]: I2C file handle
4736# $_[3]: I2C address
4737sub ite_alias_detect
4738{
4739  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
4740  my $i;
4741  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
4742  return 0 unless &$readproc(0x48) == $i2c_addr;
4743  for ($i = 0x30; $i <= 0x45; $i++) {
4744    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
4745  }
4746  return 1;
4747}
4748
4749# $_[0]: A reference to the file descriptor to access this chip
4750# $_[1]: Address
4751# Returns: 8 for a memory eeprom
4752# Registers used:
4753#   0-63: SPD Data and Checksum
4754sub eeprom_detect
4755{
4756  my ($file, $addr) = @_;
4757  my $checksum = 0;
4758
4759  # Check the checksum for validity (works for most DIMMs and RIMMs)
4760  for (my $i = 0; $i <= 62; $i++) {
4761    $checksum += i2c_smbus_read_byte_data($file, $i);
4762  }
4763  $checksum &= 255;
4764
4765  return 8
4766    if $checksum == i2c_smbus_read_byte_data($file, 63);
4767
4768  return;
4769}
4770
4771# $_[0]: A reference to the file descriptor to access this chip.
4772# $_[1]: Address
4773# Returns: undef if not detected, 8 if detected.
4774# Registers used:
4775#   0x00..0x07: DDC signature
4776sub ddcmonitor_detect
4777{
4778  my ($file,$addr) = @_;
4779
4780  return unless
4781    i2c_smbus_read_byte_data($file,0x00) == 0x00 and
4782    i2c_smbus_read_byte_data($file,0x01) == 0xFF and
4783    i2c_smbus_read_byte_data($file,0x02) == 0xFF and
4784    i2c_smbus_read_byte_data($file,0x03) == 0xFF and
4785    i2c_smbus_read_byte_data($file,0x04) == 0xFF and
4786    i2c_smbus_read_byte_data($file,0x05) == 0xFF and
4787    i2c_smbus_read_byte_data($file,0x06) == 0xFF and
4788    i2c_smbus_read_byte_data($file,0x07) == 0x00;
4789
4790  return 8;
4791}
4792
4793# $_[0]: A reference to the file descriptor to access this chip.
4794# $_[1]: Address
4795# Returns: undef if not detected, (8) if detected.
4796# Registers used:
4797#   0x00-0x02: Identification ('P','E','G' -> Pegasus ? :-)
4798sub fscpos_detect
4799{
4800  my ($file,$addr) = @_;
4801  # check the first 3 registers
4802  if (i2c_smbus_read_byte_data($file,0x00) != 0x50) {
4803        return;
4804  }
4805  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
4806        return;
4807  }
4808  if (i2c_smbus_read_byte_data($file,0x02) != 0x47) {
4809        return;
4810  }
4811  return (8);
4812}
4813
4814# $_[0]: A reference to the file descriptor to access this chip.
4815# $_[1]: Address
4816# Returns: undef if not detected, (8) if detected.
4817# Registers used:
4818#   0x00-0x02: Identification ('S','C','Y')
4819sub fscscy_detect
4820{
4821  my ($file,$addr) = @_;
4822  # check the first 3 registers
4823  if (i2c_smbus_read_byte_data($file,0x00) != 0x53) {
4824        return;
4825  }
4826  if (i2c_smbus_read_byte_data($file,0x01) != 0x43) {
4827        return;
4828  }
4829  if (i2c_smbus_read_byte_data($file,0x02) != 0x59) {
4830        return;
4831  }
4832  return (8);
4833}
4834
4835# $_[0]: A reference to the file descriptor to access this chip.
4836# $_[1]: Address
4837# Returns: undef if not detected, (8) if detected.
4838# Registers used:
4839#   0x00-0x02: Identification ('H','E','R')
4840sub fscher_detect
4841{
4842  my ($file,$addr) = @_;
4843  # check the first 3 registers
4844  if (i2c_smbus_read_byte_data($file,0x00) != 0x48) {
4845        return;
4846  }
4847  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
4848        return;
4849  }
4850  if (i2c_smbus_read_byte_data($file,0x02) != 0x52) {
4851        return;
4852  }
4853  return (8);
4854}
4855
4856# $_[0]: A reference to the file descriptor to access this chip.
4857# $_[1]: Address (unused)
4858# Returns: undef if not detected, 5 if detected.
4859# Registers used:
4860#   0x3E: Manufacturer ID
4861#   0x3F: Version/Stepping
4862sub lm93_detect
4863{
4864  my $file = shift;
4865  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x01
4866            and i2c_smbus_read_byte_data($file, 0x3F) == 0x73;
4867  return 5;
4868}
4869
4870# $_[0]: A reference to the file descriptor to access this chip.
4871# $_[1]: Address
4872# Returns: undef if not detected, (7) if detected.
4873# Registers used:
4874#   0x3F: Revision ID
4875#   0x48: Address
4876#   0x4A, 0x4B, 0x4F, 0x57, 0x58: Reserved bits.
4877# We do not use 0x49's reserved bits on purpose. The register is named
4878# "VID4/Device ID" so it is doubtful bits 7-1 are really unused.
4879sub m5879_detect
4880{
4881  my ($file, $addr) = @_;
4882
4883  return
4884    unless i2c_smbus_read_byte_data($file, 0x3F) == 0x01;
4885 
4886  return
4887    unless i2c_smbus_read_byte_data($file, 0x48) == $addr;
4888 
4889  return
4890    unless (i2c_smbus_read_byte_data($file, 0x4A) & 0x06) == 0
4891       and (i2c_smbus_read_byte_data($file, 0x4B) & 0xFC) == 0
4892       and (i2c_smbus_read_byte_data($file, 0x4F) & 0xFC) == 0
4893       and (i2c_smbus_read_byte_data($file, 0x57) & 0xFE) == 0
4894       and (i2c_smbus_read_byte_data($file, 0x58) & 0xEF) == 0;
4895
4896  return (7);
4897}
4898
4899# $_[0]: A reference to the file descriptor to access this chip.
4900# $_[1]: Address
4901# Returns: undef if not detected, 5 or 6 if detected.
4902# Registers used:
4903#   0x3E: Manufacturer ID
4904#   0x3F: Version/Stepping
4905#   0x47: VID (3 reserved bits)
4906#   0x49: VID4 (7 reserved bits)
4907sub smsc47m192_detect
4908{
4909  my ($file, $addr) = @_;
4910  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x55
4911           and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF0) == 0x20
4912           and (i2c_smbus_read_byte_data($file, 0x47) & 0x70) == 0x00
4913           and (i2c_smbus_read_byte_data($file, 0x49) & 0xFE) == 0x80;
4914  return ($addr == 0x2d ? 6 : 5);
4915}
4916
4917# $_[0]: A reference to the file descriptor to access this chip.
4918# $_[1]: Address
4919# Returns: undef if not detected, 5 or 6 if detected.
4920# Registers used:
4921#   0x3E: Manufacturer ID
4922#   0x3F: Version/Stepping
4923#   0x73: Read-only test register (4 test bits)
4924#   0x8A: Read-only test register (7 test bits)
4925sub dme1737_detect
4926{
4927  my ($file, $addr) = @_;
4928  return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x5c
4929           and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF8) == 0x88
4930           and (i2c_smbus_read_byte_data($file, 0x73) & 0x0F) == 0x09
4931           and (i2c_smbus_read_byte_data($file, 0x8A) & 0x7F) == 0x4D;
4932  return ($addr == 0x2e ? 6 : 5);
4933}
4934
4935# $_[0]: Chip to detect
4936#   (1 = F75111R/RG/N, 2 = F75121R/F75122R/RG, 3 = F75373S/SG,
4937#    4 = F75375S/SP, 5 = F75387SG/RG, 6 = F75383M/S/F75384M/S,
4938#    7 = custom power control IC)
4939# $_[1]: A reference to the file descriptor to access this chip.
4940# $_[2]: Address (unused)
4941# Returns: undef if not detected, 7 if detected.
4942# Registers used:
4943#   0x5A-0x5B: Chip ID
4944#   0x5D-0x5E: Vendor ID
4945sub fintek_detect
4946{
4947  my ($chip, $file, $addr) = @_;
4948  my $chipid = (i2c_smbus_read_byte_data($file, 0x5A) << 8)
4949             | i2c_smbus_read_byte_data($file, 0x5B);
4950  my $vendid = (i2c_smbus_read_byte_data($file, 0x5D) << 8)
4951             | i2c_smbus_read_byte_data($file, 0x5E);
4952
4953  return unless $vendid == 0x1934; # Fintek ID
4954
4955  if ($chip == 1) { # F75111R/RG/N
4956    return unless $chipid == 0x0300;
4957  } elsif ($chip == 2) { # F75121R/F75122R/RG
4958    return unless $chipid == 0x0301;
4959  } elsif ($chip == 3) { # F75373S/SG
4960    return unless $chipid == 0x0204;
4961  } elsif ($chip == 4) { # F75375S/SP
4962    return unless $chipid == 0x0306;
4963  } elsif ($chip == 5) { # F75387SG/RG
4964    return unless $chipid == 0x0410;
4965  } elsif ($chip == 6) { # F75383M/S/F75384M/S
4966    # The datasheet has 0x0303, but Fintek say 0x0413 is also possible
4967    return unless $chipid == 0x0303 || $chipid == 0x0413;
4968  } elsif ($chip == 7) { # custom power control IC
4969    return unless $chipid == 0x0302;
4970  }
4971
4972  return 7;
4973}
4974
4975# $_[0]: A reference to the file descriptor to access this chip.
4976# $_[1]: Address
4977# Returns: undef if not detected, 1 if detected
4978# Detection is rather difficult, since the PCA9540 has a single register.
4979# Fortunately, no other device is known to live at this address.
4980sub pca9540_detect
4981{
4982        my ($file, $addr) = @_;
4983        my $reg = i2c_smbus_read_byte($file);
4984
4985        return if ($reg & 0xfa);
4986        return if $reg != i2c_smbus_read_byte($file);
4987        return if $reg != i2c_smbus_read_byte($file);
4988        return if $reg != i2c_smbus_read_byte($file);
4989
4990        return 1;
4991}
4992
4993# This checks for non-FFFF values for temperature, voltage, and current.
4994# The address (0x0b) is specified by the SMBus standard so it's likely
4995# that this really is a smart battery.
4996# $_[0]: A reference to the file descriptor to access this chip.
4997# $_[1]: Address
4998# Returns: 5
4999sub smartbatt_detect
5000{
5001  my ($file,$addr) = @_;
5002  # check some registers
5003  if (i2c_smbus_read_word_data($file,0x08) == 0xffff) {
5004        return;
5005  }
5006  if (i2c_smbus_read_word_data($file,0x09) == 0xffff) {
5007        return;
5008  }
5009  if (i2c_smbus_read_word_data($file,0x0a) == 0xffff) {
5010        return;
5011  }
5012  return (5);
5013}
5014
5015# Returns: 4
5016# These are simple detectors that only look for a register at the
5017# standard location. No writes are performed.
5018# For KCS, use the STATUS register. For SMIC, use the FLAGS register.
5019sub ipmi_kcs_detect
5020{
5021  return if inb (0x0ca3) == 0xff;
5022  return (4);
5023}
5024
5025sub ipmi_smic_detect
5026{
5027  return if inb (0x0cab) == 0xff;
5028  return (4);
5029}
5030
5031# $_[0]: Chip to detect (0 = W83L784R/AR, 1 = W83L785R)
5032# $_[1]: A reference to the file descriptor to access this chip.
5033# $_[2]: Address
5034# Returns: undef if not detected, 6 or 8 if detected
5035# Registers used:
5036#   0x40: Configuration
5037#   0x4a: Full I2C Address (not W83L785R)
5038#   0x4b: I2C addresses of emulated LM75 chips (not W83L785R)
5039#   0x4c: Winbond Vendor ID (Low Byte)
5040#   0x4d: Winbond Vendor ID (High Byte)
5041#   0x4e: Chip ID
5042# Note that this function is always called through a closure, so the
5043# arguments are shifted by one place.
5044sub w83l784r_detect
5045{
5046  my ($reg,@res);
5047  my ($chip,$file,$addr) = @_;
5048
5049  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
5050  return if $chip == 0
5051    and i2c_smbus_read_byte_data($file,0x4a) != $addr;
5052  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
5053  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
5054  return if $chip == 0
5055    and i2c_smbus_read_byte_data($file,0x4e) != 0x50;
5056  return if $chip == 1
5057    and i2c_smbus_read_byte_data($file,0x4e) != 0x60;
5058
5059  $reg = i2c_smbus_read_byte_data($file,0x4b);
5060
5061  return 6 if $chip == 1; # W83L785R doesn't have subclients
5062 
5063  @res = (8);
5064  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08 ;
5065  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
5066  return @res;
5067}
5068
5069# $_[0]: Chip to detect (0 = W83L785TS-S)
5070# $_[1]: A reference to the file descriptor to access this chip.
5071# $_[2]: Address
5072# Returns: undef if not detected, 8 if detected
5073# Registers used:
5074#   0x4C-4E: Mfr and Chip ID
5075# Note that this function is always called through a closure, so the
5076# arguments are shifted by one place.
5077sub w83l785ts_detect
5078{
5079  my ($chip,$file,$addr) = @_;
5080  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
5081  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
5082  return unless i2c_smbus_read_byte_data($file,0x4e) == 0x70;
5083  return (8);
5084}
5085
5086# $_[0]: Chip to detect. Always zero for now, but available for future use
5087#        if somebody finds a way to distinguish MAX6650 and MAX6651.
5088# $_[1]: A reference to the file descriptor to access this chip.
5089# $_[2]: Address
5090# Returns: undef if not detected, 4 if detected.
5091#
5092# The max6650 has no device ID register. However, a few registers have
5093# spare bits, which are documented as being always zero on read. We read
5094# all of these registers check the spare bits. Any non-zero means this
5095# is not a max6650/1.
5096#
5097# The always zero bits are:
5098#   configuration byte register (0x02) - top 2 bits
5099#   gpio status register (0x14) - top 3 bits
5100#   alarm enable register (0x08) - top 3 bits
5101#   alarm status register (0x0A) - top 3 bits
5102#   tachometer count time register (0x16) - top 6 bits
5103# Additionally, not all values are possible for lower 3 bits of
5104# the configuration register.
5105sub max6650_detect
5106{
5107  my ($chip, $file) = @_;
5108
5109  my $conf = i2c_smbus_read_byte_data($file,0x02);
5110 
5111  return if i2c_smbus_read_byte_data($file,0x16) & 0xFC;
5112  return if i2c_smbus_read_byte_data($file,0x0A) & 0xE0;
5113  return if i2c_smbus_read_byte_data($file,0x08) & 0xE0;
5114  return if i2c_smbus_read_byte_data($file,0x14) & 0xE0;
5115  return if ($conf & 0xC0) or ($conf & 0x07) > 4;
5116
5117  return 4;
5118}
5119
5120# $_[0]: Chip to detect. Always zero.
5121# $_[1]: A reference to the file descriptor to access this chip.
5122# $_[2]: Address.
5123#
5124# Returns: undef if not detected, 6 if detected.
5125sub max6655_detect
5126{
5127  my ($chip, $file, $addr) = @_;
5128
5129  # checking RDID (Device ID)
5130  return unless i2c_smbus_read_byte_data($file, 0xfe) == 0x0a;
5131  # checking RDRV (Manufacturer ID)
5132  return unless i2c_smbus_read_byte_data($file, 0xff) == 0x4d;
5133  # checking unused bits (conversion rate, extended temperature)
5134  return unless i2c_smbus_read_byte_data($file, 0x04) & 0xf8;
5135  return unless i2c_smbus_read_byte_data($file, 0x10) & 0x1f;
5136  return unless i2c_smbus_read_byte_data($file, 0x11) & 0x1f;
5137  return unless i2c_smbus_read_byte_data($file, 0x12) & 0x1f;
5138
5139  return 6;
5140}
5141
5142# $_[0]: Chip to detect (0 = VT1211)
5143# $_[1]: A reference to the file descriptor to access this chip.
5144# $_[2]: Address
5145#
5146# This isn't very good detection.
5147# Verify the i2c address, and the stepping ID (which is 0xb0 on
5148# my chip but could be different for others...
5149#
5150sub vt1211_i2c_detect
5151{
5152  my ($chip,$file,$addr) = @_;
5153  return unless (i2c_smbus_read_byte_data($file,0x48) & 0x7f) == $addr;
5154  return unless i2c_smbus_read_byte_data($file,0x3f) == 0xb0;
5155  return 2;
5156}
5157
5158# $_[0]: Chip to detect (0 = VT1211)
5159# $_[1]: ISA address
5160# $_[2]: I2C file handle
5161# $_[3]: I2C address
5162sub vt1211_alias_detect
5163{
5164  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
5165  my $i;
5166  return 0 unless (inb($isa_addr + 0x48) & 0x7f) == $i2c_addr;
5167  return 0 unless (i2c_smbus_read_byte_data($file,0x48) & 0x7f) == $i2c_addr;
5168  for ($i = 0x2b; $i <= 0x3d; $i ++) {
5169    return 0 unless inb($isa_addr + $i) == i2c_smbus_read_byte_data($file,$i);
5170  }
5171  return 1;
5172}
5173
5174
5175######################
5176# PCI CHIP DETECTION #
5177######################
5178
5179# Returns: undef if not detected, (7) or (9) if detected.
5180# The address is encoded in PCI space. We could decode it and print it.
5181# For Linux 2.4 we should probably check for invalid matches (SiS645).
5182sub sis5595_pci_detect
5183{
5184        return unless exists $pci_list{'1039:0008'};
5185        return (kernel_version_at_least(2, 6, 0) ? 9 : 7);
5186}
5187
5188# Returns: undef if not detected, (9) if detected.
5189# The address is encoded in PCI space. We could decode it and print it.
5190sub via686a_pci_detect
5191{
5192        return unless exists $pci_list{'1106:3057'};
5193        return 9;
5194}
5195
5196# Returns: undef if not detected, (9) if detected.
5197# The address is encoded in PCI space. We could decode it and print it.
5198sub via8231_pci_detect
5199{
5200        return unless exists $pci_list{'1106:8235'};
5201        return 9;
5202}
5203
5204# Returns: undef if not detected, (9) if detected.
5205sub k8temp_pci_detect
5206{
5207        return unless exists $pci_list{'1022:1103'};
5208        return 9;
5209}
5210
5211# Returns: undef if not detected, (9) if detected.
5212# the device 0xa620 should not be visible on host PCI bus, gateway
5213# must be used
5214sub intel_amb_detect
5215{
5216        if ((exists $pci_list{'8086:a620'}) ||
5217           (exists $pci_list{'8086:25f0'})) {
5218                return 9;
5219        }
5220        return;
5221}
5222
5223# Returns: undef if not detected, (9) if detected.
5224sub coretemp_detect
5225{
5226        my $probecpu;
5227        foreach $probecpu (@cpu) {
5228                if ($probecpu->{'vendor_id'} eq 'GenuineIntel' && 
5229                                $probecpu->{'cpu family'} == 6 &&
5230                                ($probecpu->{'model'} == 14 ||
5231                                 $probecpu->{'model'} == 15)) {
5232                        return 9;
5233                }
5234        }
5235        return;
5236}
5237
5238################
5239# MAIN PROGRAM #
5240################
5241
5242# $_[0]: reference to a list of chip hashes
5243sub print_chips_report 
5244{
5245  my ($listref) = @_;
5246  my $data;
5247 
5248  foreach $data (@$listref) {
5249    my $is_i2c = exists $data->{i2c_addr};
5250    my $is_isa = exists $data->{isa_addr};
5251    print "  * ";
5252    if ($is_i2c) {
5253      printf "Bus `%s'\n", $data->{i2c_adap};
5254      printf "    Busdriver `%s', I2C address 0x%02x", 
5255             $data->{i2c_driver}, $data->{i2c_addr};
5256      if (exists $data->{i2c_sub_addrs}) {
5257        print " (and";
5258        my $sub_addr;
5259        foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
5260          printf " 0x%02x",$sub_addr;
5261        }
5262        print ")"
5263      }
5264      print "\n    ";
5265    }
5266    if ($is_isa) {
5267      print "ISA bus";
5268      if ($data->{isa_addr}) {
5269        printf ", address 0x%x", $data->{isa_addr};
5270      }
5271      print " (Busdriver `i2c-isa')"
5272        unless kernel_version_at_least(2, 6, 18);
5273      print "\n    ";
5274    }
5275    printf "Chip `%s' (confidence: %d)\n",
5276           $data->{chipname},  $data->{conf};
5277  }
5278}
5279
5280# $_[0]: 1 if ISA bus is prefered, 0 for SMBus
5281# We build here an array adapters, indexed on the number the adapter has
5282# at this moment (we assume only loaded adapters are interesting at all;
5283# everything that got scanned also got loaded). Each entry is a reference
5284# to a hash containing:
5285#  driver: Name of the adapter driver
5286#  nr_now: Number of the bus now
5287#  nr_later: Number of the bus when the modprobes are done (not included if the
5288#        driver should not be loaded)
5289# A second array, called
5290sub generate_modprobes
5291{
5292  my ($prefer_isa) = @_;
5293
5294  my ($chip,$detection,$nr,$i,@optionlist,@probelist,$driver,$isa,$adap);
5295  my $ipmi = 0;
5296  my $modprobes = "";
5297  my $configfile = "";
5298
5299  # These are always needed
5300  $configfile .= "# I2C module options\n";
5301  $configfile .= "alias char-major-89 i2c-dev\n";
5302
5303  # Collect all adapters used
5304  $nr = 0;
5305  $isa = 0;
5306  foreach $chip (@chips_detected) {
5307    foreach $detection (@{$chip->{detected}}) {
5308      # If there is more than one bus detected by a driver, they are
5309      # still all added. So we number them in the correct order
5310      if (exists $detection->{i2c_driver} and
5311          not exists $i2c_adapters[$detection->{i2c_devnr}]->{nr_later} and 
5312          not (exists $detection->{isa_addr} and $prefer_isa)) {
5313         foreach $adap (@i2c_adapters) {
5314           next unless exists $adap->{driver};
5315           $adap->{nr_later} = $nr++ if $adap->{driver} eq $detection->{i2c_driver};
5316         }
5317      }
5318      if (exists $detection->{isa_addr} and
5319          not (exists $detection->{i2c_driver} and not $prefer_isa)) {
5320           $isa=1;
5321      }
5322      if ($chip->{driver} eq "bmcsensors" || 
5323          $chip->{driver} eq "ipmisensors") {
5324           $ipmi = 1;
5325      }
5326    }
5327  }
5328
5329  $modprobes .= "# I2C adapter drivers\n" if $nr;
5330  for ($i = 0; $i < $nr; $i++) {
5331    foreach $adap (@i2c_adapters) {
5332      next unless exists $adap->{nr_later} and $adap->{nr_later} == $i;
5333      if ($adap->{driver} eq "UNKNOWN") {
5334        $modprobes .= "# modprobe unknown adapter ".$adap->{name}."\n";
5335      } elsif ($adap->{driver} eq "DISABLED") {
5336        $modprobes .= "# modprobe disabled adapter ".$adap->{name}."\n";
5337      } elsif ($adap->{driver} eq "to-be-written") {
5338        $modprobes .= "# no driver available for adapter ".$adap->{name}."\n";
5339      } else {
5340        $modprobes .= "modprobe $adap->{driver}\n"
5341          unless $modprobes =~ /modprobe $adap->{driver}\n/;
5342      }
5343      last;
5344    }
5345  }
5346  # i2c-isa is loaded automatically (as a dependency) since 2.6.14,
5347  # and will soon be gone.
5348  $modprobes .= "modprobe i2c-isa\n" if ($isa && !kernel_version_at_least(2, 6, 18));
5349  if ($ipmi) {
5350    $modprobes .= "# You must also install and load the IPMI modules\n";
5351    if (kernel_version_at_least(2, 6, 0)) {
5352      $modprobes .= "modprobe ipmi-si\n";
5353    } else {
5354      $modprobes .= "modprobe i2c-ipmi\n";
5355    }
5356  }
5357
5358  # Now determine the chip probe lines
5359  $modprobes .= "# Chip drivers\n";
5360  foreach $chip (@chips_detected) {
5361    next if not @{$chip->{detected}};
5362    next if $chip->{driver} eq "not-a-sensor";   
5363    next if $chip->{driver} eq "use-isa-instead";
5364    if ($chip->{driver} eq "to-be-written") {
5365      $modprobes .= "# no driver for $chip->{detected}[0]{chipname} yet\n";
5366    } else {
5367       # need the * for 2.4 kernels, won't necessarily be an exact match
5368       open(local *INPUTFILE, "modprobe -l $chip->{driver}\\* 2>/dev/null |");
5369       local $_;
5370       my $modulefound = 0;
5371       while (<INPUTFILE>) {
5372         if(m@/@) {
5373           $modulefound = 1;
5374           last;
5375         }
5376       }
5377       close INPUTFILE;
5378       #check return value from modprobe in case modprobe -l isn't supported
5379       if((($? >> 8) == 0) && ! $modulefound) {
5380         $modprobes .= "# Warning: the required module $chip->{driver} is not currently installed\n".
5381                       "# on your system. For status of 2.6 kernel ports check\n".
5382                       "# http://www.lm-sensors.org/wiki/Devices. If driver is built\n".
5383                       "# into the kernel, or unavailable, comment out the following line.\n";
5384       }
5385       $modprobes .= "modprobe $chip->{driver}\n";
5386    }
5387
5388    # Handle misdetects
5389    foreach $detection (@{$chip->{misdetected}}) {
5390      push @optionlist, $i2c_adapters[$detection->{i2c_devnr}]->{nr_later},
5391                       $detection->{i2c_addr}
5392           if exists $detection->{i2c_addr} and
5393              exists $i2c_adapters[$detection->{i2c_devnr}]->{nr_later};
5394      push @optionlist, -1, $detection->{isa_addr}
5395           if exists $detection->{isa_addr} and $isa;
5396    }
5397
5398    # Handle aliases
5399    foreach $detection (@{$chip->{detected}}) {
5400      if (exists $detection->{i2c_driver} and 
5401          exists $detection->{isa_addr} and
5402          exists $i2c_adapters[$detection->{i2c_devnr}]->{nr_later} and
5403          $isa) {
5404        if ($prefer_isa) {
5405          push @optionlist, $i2c_adapters[$detection->{i2c_devnr}]->{nr_later},
5406                           $detection->{i2c_addr};
5407        } else {
5408          push @optionlist, -1, $detection->{isa_addr}
5409        }
5410      }
5411    }
5412
5413    next if not (@probelist or @optionlist);
5414    $configfile .= "options $chip->{driver}";
5415    $configfile .= sprintf " ignore=%d,0x%02x",shift @optionlist, 
5416                                               shift @optionlist
5417                  if @optionlist;
5418    $configfile .= sprintf ",%d,0x%02x",shift @optionlist, shift @optionlist
5419                  while @optionlist;
5420    $configfile .= sprintf " probe=%d,0x%02x",shift @probelist,
5421                                              shift @probelist
5422                  if @probelist;
5423    $configfile .= sprintf ",%d,0x%02x",shift @probelist, shift @probelist
5424                  while @probelist;
5425    $configfile .= "\n";
5426  }
5427
5428  return ($modprobes,$configfile);
5429 
5430}
5431
5432sub main
5433{
5434  my (@adapters,$res,$did_adapter_detection,$adapter);
5435
5436  # We won't go very far if not root
5437  unless ($> == 0) {
5438    print "You need to be root to run this script.\n";
5439    exit -1;
5440  }
5441
5442  initialize_conf;
5443  initialize_proc_pci;
5444  initialize_modules_list;
5445  initialize_modules_supported;
5446  initialize_kernel_version;
5447  initialize_cpu_list();
5448
5449  print "# sensors-detect revision $revision\n\n";
5450
5451  print "This program will help you determine which kernel modules you need\n",
5452        "to load to use lm_sensors most effectively. It is generally safe\n",
5453        "and recommended to accept the default answers to all questions,\n",
5454        "unless you know what you're doing.\n";
5455  print "You need to have i2c and lm_sensors installed before running this\n",
5456        "program.\n"
5457    unless kernel_version_at_least(2, 6, 0);
5458  print "\n";
5459
5460  print "We can start with probing for (PCI) I2C or SMBus adapters.\n";
5461  print "Do you want to probe now? (YES/no): ";
5462  @adapters = adapter_pci_detection
5463                        if ($did_adapter_detection = not <STDIN> =~ /\s*[Nn]/);
5464  print "\n";
5465
5466  if (not $did_adapter_detection) {
5467    print "As you skipped adapter detection, we will only scan already loaded\n".
5468          "adapter modules.\n";
5469  } else {
5470    print "We will now try to load each adapter module in turn.\n";
5471    foreach $adapter (@adapters) {
5472      next if $adapter eq "DISABLED";
5473      next if $adapter eq "to-be-tested";
5474      if (exists($modules_list{$adapter})) {
5475        print "Module `$adapter' already loaded.\n";
5476      } else {
5477        print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
5478        unless (<STDIN> =~ /^\s*[Nn]/) {
5479          if (system ("modprobe", $adapter)) {
5480            print "Loading failed... skipping.\n";
5481          } else {
5482            print "Module loaded successfully.\n";
5483          }
5484        }
5485      }
5486    }
5487  }
5488
5489  print "If you have undetectable or unsupported adapters, you can have them\n".
5490        "scanned by manually loading the modules before running this script.\n\n";
5491  initialize_i2c_adapters_list();
5492
5493  if (!exists($modules_list{"i2c-dev"})
5494   && !(defined $sysfs_root && -e "$sysfs_root/class/i2c-dev")) {
5495    print "To continue, we need module `i2c-dev' to be loaded.\n";
5496    print "If it is built-in into your kernel, you can safely skip this.\n"
5497      unless kernel_version_at_least(2, 6, 0);
5498    print "Do you want to load `i2c-dev' now? (YES/no): ";
5499    if (<STDIN> =~ /^\s*n/i) {
5500      print "Well, you will know best.\n";
5501    } elsif (system "modprobe", "i2c-dev") {
5502      print "Loading failed, expect problems later on.\n";
5503    } else {
5504      print "Module loaded successfully.\n";
5505    }
5506    print "\n";
5507  }
5508
5509  # Before looking for chips, make sure any special case chips are
5510  # added to the chip_ids list
5511  chip_special_cases();
5512  $i2c_addresses_to_scan = i2c_addresses_to_scan();
5513
5514  print "We are now going to do the I2C/SMBus adapter probings. Some chips may\n",
5515        "be double detected; we choose the one with the highest confidence\n",
5516        "value in that case.\n",
5517        "If you found that the adapter hung after probing a certain address,\n",
5518        "you can specify that address to remain unprobed.\n";
5519
5520  my ($inp,@not_to_scan,$inp2);
5521  for (my $dev_nr = 0; $dev_nr < @i2c_adapters; $dev_nr++) {
5522    next unless exists $i2c_adapters[$dev_nr];
5523    my $adap = $i2c_adapters[$dev_nr]->{'name'};
5524    print "\n";
5525    print "Next adapter: $adap (i2c-$dev_nr)\n";
5526    print "Do you want to scan it? (YES/no/selectively): ";
5527   
5528    $inp = <STDIN>;
5529    if ($inp =~ /^\s*[Ss]/) {
5530      print "Please enter one or more addresses not to scan. Separate them ",
5531            "with comma's.\n",
5532            "You can specify a range by using dashes. Addresses may be ",
5533            "decimal (like 54)\n",
5534            "or hexadecimal (like 0x33).\n",
5535            "Addresses: ";
5536      $inp2 = <STDIN>;
5537      chop $inp2;
5538      @not_to_scan = parse_not_to_scan 0,0x7f,$inp2;
5539    }
5540    scan_adapter $dev_nr, $adap, $i2c_adapters[$dev_nr]->{'driver'},
5541                 \@not_to_scan   unless $inp =~ /^\s*[Nn]/;
5542  }
5543  print "\n";
5544
5545  print "Some chips are also accessible through the ISA I/O ports. We have to\n".
5546        "write to arbitrary I/O ports to probe them. This is usually safe though.\n".
5547        "Yes, you do have ISA I/O ports even if you do not have any ISA slots!\n";
5548  print "Do you want to scan the ISA I/O ports? (YES/no): ";
5549  unless (<STDIN> =~ /^\s*n/i) {
5550    initialize_ioports();
5551    scan_isa_bus();
5552    close_ioports();
5553  }
5554  print "\n";
5555
5556  print "Some Super I/O chips may also contain sensors. We have to write to\n".
5557        "standard I/O ports to probe them. This is usually safe.\n";
5558  print "Do you want to scan for Super I/O sensors? (YES/no): ";
5559  unless (<STDIN> =~ /^\s*n/i) {
5560    initialize_ioports();
5561    scan_superio(0x2e, 0x2f);
5562    scan_superio(0x4e, 0x4f);
5563    close_ioports();
5564  }
5565  print "\n";
5566
5567  print "Some CPUs or memory controllers may also contain embedded sensors.\n";
5568  print "Do you want to scan for them? (YES/no): ";
5569  unless (<STDIN> =~ /^\s*n/i) {
5570    $| = 1;
5571    foreach my $entry (@cpu_ids) {
5572      scan_cpu($entry);
5573    }
5574    $| = 0;
5575  }
5576  print "\n";
5577
5578  if(! @chips_detected) {
5579    print "Sorry, no sensors were detected.\n",
5580          "Either your sensors are not supported, or they are connected to an\n",
5581          "I2C or SMBus adapter that is not supported. See doc/FAQ,\n",
5582          "doc/lm_sensors-FAQ.html or http://www.lm-sensors.org/wiki/FAQ\n",
5583          "(FAQ #4.24.3) for further information.\n",
5584          "If you find out what chips are on your board, check\n",
5585          "http://www.lm-sensors.org/wiki/Devices for driver status.\n";
5586    exit;
5587  }
5588
5589  print "Now follows a summary of the probes I have just done.\n".
5590        "Just press ENTER to continue: ";
5591  <STDIN>;
5592
5593  my ($chip,$data);
5594  foreach $chip (@chips_detected) {
5595    next if $chip->{driver} eq "not-a-sensor";
5596    next if $chip->{driver} eq "use-isa-instead";
5597    print "\nDriver `$chip->{driver}' ";
5598    if (@{$chip->{detected}}) {
5599      if (@{$chip->{misdetected}}) {
5600        print "(should be inserted but causes problems):\n";
5601      } else {
5602        print "(should be inserted):\n";
5603      }
5604    } else {
5605      if (@{$chip->{misdetected}}) {
5606        print "(may not be inserted):\n";
5607      } else {
5608        print "(should not be inserted, but is harmless):\n";
5609      }
5610    }
5611    if (@{$chip->{detected}}) {
5612      print "  Detects correctly:\n";
5613      print_chips_report $chip->{detected};
5614    }
5615    if (@{$chip->{misdetected}}) {
5616      print "  Misdetects:\n";
5617      print_chips_report $chip->{misdetected};
5618    }
5619  }
5620  print "\n";
5621
5622  print "I will now generate the commands needed to load the required modules.\n".
5623        "Just press ENTER to continue: ";
5624  <STDIN>;
5625     
5626  print "\n";
5627  my ($modprobes, $configfile) = generate_modprobes 1;  # 1 == prefer ISA
5628  print "To make the sensors modules behave correctly, add these lines to\n".
5629        "$modules_conf:\n\n";
5630  print "#----cut here----\n".
5631        $configfile.
5632        "#----cut here----\n\n";
5633
5634  print "To load everything that is needed, add this to some /etc/rc* file:\n\n";
5635  print "#----cut here----\n".
5636        $modprobes.
5637        "# sleep 2 # optional\n".
5638        (-e '/usr/bin/sensors' ?
5639          "/usr/bin/sensors -s # recommended\n" :
5640          "/usr/local/bin/sensors -s # recommended\n") .
5641        "#----cut here----\n\n";
5642
5643  print "If you have some drivers built into your kernel, the list above will\n".
5644        "contain too many modules. Skip the appropriate ones! You really\n".
5645        "should try these commands right now to make sure everything is\n".
5646        "working properly. Monitoring programs won't work until the needed\n".
5647        "modules are loaded.\n\n";
5648 
5649  my $have_sysconfig = -d '/etc/sysconfig';
5650  printf "Do you want to \%s /etc/sysconfig/lm_sensors? (\%s): ",
5651         (-e '/etc/sysconfig/lm_sensors' ? 'overwrite' : 'generate'),
5652         ($have_sysconfig ? 'YES/no' : 'yes/NO');
5653  $_ = <STDIN>;
5654  if (($have_sysconfig and not m/^\s*n/i) or m/^\s*y/i) {
5655    unless ($have_sysconfig) {
5656      mkdir '/etc/sysconfig', 0777
5657        or die "Sorry, can't create /etc/sysconfig ($!)";
5658    }
5659    open(local *SYSCONFIG, ">/etc/sysconfig/lm_sensors")
5660      or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)";
5661    print SYSCONFIG <<'EOT';
5662#    /etc/sysconfig/lm_sensors - Defines modules loaded by
5663#                                /etc/init.d/lm_sensors
5664#    Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>
5665#
5666#    This program is free software; you can redistribute it and/or modify
5667#    it under the terms of the GNU General Public License as published by
5668#    the Free Software Foundation; either version 2 of the License, or
5669#    (at your option) any later version.
5670#
5671#    This program is distributed in the hope that it will be useful,
5672#    but WITHOUT ANY WARRANTY; without even the implied warranty of
5673#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5674#    GNU General Public License for more details.
5675#
5676#    You should have received a copy of the GNU General Public License
5677#    along with this program; if not, write to the Free Software
5678#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5679#
5680#
5681# See also the lm_sensors homepage at:
5682#     http://www.lm-sensors.org/
5683#
5684# This file is used by /etc/init.d/lm_sensors and defines the modules to
5685# be loaded/unloaded. This file is sourced into /etc/init.d/lm_sensors.
5686#
5687# The format of this file is a shell script that simply defines the modules
5688# in order as normal variables with the special names:
5689#    MODULE_0, MODULE_1, MODULE_2, etc.
5690#
5691# List the modules that are to be loaded for your system
5692#
5693EOT
5694    print SYSCONFIG
5695      "# Generated by sensors-detect on " . scalar localtime() . "\n";
5696    my @modules = grep /^modprobe /, split "\n", $modprobes;
5697    my $i = 0;
5698    my $sysconfig = "";
5699    foreach (@modules) {
5700      s/^modprobe //;
5701      $sysconfig .= "MODULE_$i=$_\n";
5702      $i++;
5703    }
5704    print SYSCONFIG $sysconfig;
5705
5706    print "Copy prog/init/lm_sensors.init to /etc/init.d/lm_sensors\n".
5707          "for initialization at boot time.\n"
5708      unless -f "/etc/init.d/lm_sensors";
5709  }
5710}
5711
5712main;
Note: See TracBrowser for help on using the browser.