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

Revision 4585, 168.7 KB (checked in by khali, 6 years ago)

Cleanup the module.conf / modprobe.conf selection code.

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