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

Revision 3258, 160.7 KB (checked in by khali, 7 years ago)

Add ServerWorks? HT-1000 SMBus detection.

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