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

Revision 1905, 121.7 KB (checked in by khali, 10 years ago)

Add detection of Philips NE1619 (ADM1025 clone).

  • 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#
7#    This program is free software; you can redistribute it and/or modify
8#    it under the terms of the GNU General Public License as published by
9#    the Free Software Foundation; either version 2 of the License, or
10#    (at your option) any later version.
11#
12#    This program is distributed in the hope that it will be useful,
13#    but WITHOUT ANY WARRANTY; without even the implied warranty of
14#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15#    GNU General Public License for more details.
16#
17#    You should have received a copy of the GNU General Public License
18#    along with this program; if not, write to the Free Software
19#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20#
21
22# TODO: Better handling of chips with several addresses
23
24# A Perl wizard really ought to look upon this; the PCI and I2C stuff should
25# each be put in a separate file, using modules and packages. That is beyond
26# me.
27
28require 5.004;
29
30use strict;
31use Fcntl;
32use POSIX;
33
34#########################
35# CONSTANT DECLARATIONS #
36#########################
37
38use vars qw(@pci_adapters @chip_ids @superio_ids @undetectable_adapters @dmidecode);
39
40@dmidecode = ( '/usr/local/sbin/dmidecode', '/usr/sbin/dmidecode' );
41
42@undetectable_adapters = ( 'i2c-elektor', 'i2c-elv', 'i2c-philips-par',
43                           'i2c-velleman' );
44
45# This is the list of SMBus or I2C adapters we recognize by their PCI
46# signature. This is an easy and fast way to determine which SMBus or I2C
47# adapters should be present.
48# Each entry must have a vendid (Vendor ID), devid (Device ID), func (PCI
49# Function) and procid (string as appears in /proc/pci; see linux/driver/pci,
50# either pci.c or oldproc.c). If no driver is written yet, omit the
51# driver (Driver Name) field. The match (Match Description) field should
52# contain a function which returns zero if its two parameter matches
53# the text as it would appear in /proc/bus/i2c.
54@pci_adapters = ( 
55     { 
56       vendid => 0x8086,
57       devid  => 0x7113,
58       func => 3,
59       procid => "Intel 82371AB PIIX4 ACPI",
60       driver => "i2c-piix4",
61       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
62     } , 
63     { 
64       vendid => 0x8086,
65       devid  => 0x719b,
66       func => 3,
67       procid => "Intel 82443MX Mobile",
68       driver => "i2c-piix4",
69       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
70     } , 
71     { 
72       vendid => 0x8086,
73       devid  => 0x2413,
74       func => 3,
75       procid => "Intel 82801AA ICH",
76       driver => "i2c-i801",
77       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
78     } , 
79     { 
80       vendid => 0x8086,
81       devid  => 0x2423,
82       func => 3,
83       procid => "Intel 82801AB ICH0",
84       driver => "i2c-i801",
85       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
86     } , 
87     { 
88       vendid => 0x8086,
89       devid  => 0x2443,
90       func => 3,
91       procid => "Intel 82801BA ICH2",
92       driver => "i2c-i801",
93       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
94     } , 
95     { 
96       vendid => 0x8086,
97       devid  => 0x2483,
98       func => 3,
99       procid => "Intel 82801CA/CAM ICH3",
100       driver => "i2c-i801",
101       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
102     } , 
103     { 
104       vendid => 0x8086,
105       devid  => 0x24C3,
106       func => 3,
107       procid => "Intel 82801DB ICH4",
108       driver => "i2c-i801",
109       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
110     } , 
111     { 
112       vendid => 0x8086,
113       devid  => 0x24D3,
114       func => 3,
115       procid => "Intel 82801EB ICH5",
116       driver => "i2c-i801",
117       match => sub { $_[0] =~ /^SMBus I801 adapter at [0-9,a-f]{4}/ },
118     } , 
119     { 
120       vendid => 0x1106,
121       devid  => 0x3040,
122       func => 3,
123       procid => "VIA Technologies VT82C586B Apollo ACPI",
124       driver => "i2c-via",
125       match => sub { $_[0] =~ /^VIA i2c/ },
126     } ,
127     { 
128       vendid => 0x1106,
129       devid  => 0x3050,
130       func => 3,
131       procid => "VIA Technologies VT82C596 Apollo ACPI",
132       driver => "i2c-viapro",
133       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
134     } ,
135     { 
136       vendid => 0x1106,
137       devid  => 0x3051,
138       func => 3,
139       procid => "VIA Technologies VT82C596B ACPI",
140       driver => "i2c-viapro",
141       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
142     } ,
143     { 
144       vendid => 0x1106,
145       devid  => 0x3057,
146       func => 4,
147       procid => "VIA Technologies VT82C686 Apollo ACPI",
148       driver => "i2c-viapro",
149       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
150     } ,
151     { 
152       vendid => 0x1106,
153       devid  => 0x3074,
154       func => 0,
155       procid => "VIA Technologies VT8233 VLink South Bridge",
156       driver => "i2c-viapro",
157       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
158     } ,
159     { 
160       vendid => 0x1106,
161       devid  => 0x3147,
162       func => 0,
163       procid => "VIA Technologies VT8233A South Bridge",
164       driver => "i2c-viapro",
165       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
166     } ,
167     { 
168       vendid => 0x1106,
169       devid  => 0x3177,
170       func => 0,
171       procid => "VIA Technologies VT8233A/8235 South Bridge",
172       driver => "i2c-viapro",
173       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
174     } ,
175     { 
176       vendid => 0x1106,
177       devid  => 0x8235,
178       func => 4,
179       procid => "VIA Technologies VT8231 South Bridge",
180       driver => "i2c-viapro",
181       match => sub { $_[0] =~ /^SMBus Via Pro adapter at/ },
182     } ,
183     {
184       vendid => 0x1039,
185       devid  => 0x0008,
186       func => 0,
187       procid => "Silicon Integrated Systems SIS5595",
188       driver => "i2c-sis5595",
189       match => sub {  $_[0] =~ /^SMBus SIS5595 adapter at [0-9,a-f]{4}/ },
190     } ,
191     {
192       vendid => 0x1039,
193       devid  => 0x0018,
194       func => 0,
195       procid => "Silicon Integrated Systems 85C503/5513 (LPC Bridge)",
196       driver => "i2c-sis645",
197       match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
198     } ,
199     {
200       vendid => 0x1039,
201       devid  => 0x5597,
202       func => 0,
203       procid => "Silicon Integrated Systems SIS5581/5582/5597/5598 (To be written - Do not use 5595 drivers)",
204       driver => "to-be-written",
205       match => sub { 0 },
206     } ,
207     {
208       vendid => 0x1039,
209       devid  => 0x5598,
210       func => 0,
211       procid => "Silicon Integrated Systems SIS5598 (To be written - Do not use 5595 drivers)",
212       driver => "to-be-written",
213       match => sub { 0 },
214     } ,
215     {
216       vendid => 0x1039,
217       devid  => 0x0540,
218       func => 0,
219       procid => "Silicon Integrated Systems SIS540 (To be written - Do not use 5595 drivers)",
220       driver => "to-be-written",
221       match => sub { 0 },
222     } ,
223     {
224       vendid => 0x1039,
225       devid  => 0x0630,
226       func => 0,
227       procid => "Silicon Integrated Systems SIS630",
228       driver => "i2c-sis630",
229       match => sub { $_[0] =~ /^SMBus SIS630 adapter at [0-9,a-f]{4}/ },
230     } ,
231     {
232       vendid => 0x1039,
233       devid  => 0x0645,
234       func => 0,
235       procid => "Silicon Integrated Systems SIS645",
236       driver => "i2c-sis645",
237       match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
238     } ,
239     {
240       vendid => 0x1039,
241       devid  => 0x0646,
242       func => 0,
243       procid => "Silicon Integrated Systems SIS645DX",
244       driver => "i2c-sis645",
245       match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
246     } ,
247     {
248       vendid => 0x1039,
249       devid  => 0x0648,
250       func => 0,
251       procid => "Silicon Integrated Systems SIS648",
252       driver => "i2c-sis645",
253       match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
254     } ,
255     {
256       vendid => 0x1039,
257       devid  => 0x0650,
258       func => 0,
259       procid => "Silicon Integrated Systems SIS650",
260       driver => "i2c-sis645",
261       match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
262     } ,
263     {
264       vendid => 0x1039,
265       devid  => 0x0651,
266       func => 0,
267       procid => "Silicon Integrated Systems SIS651",
268       driver => "i2c-sis645",
269       match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
270     } ,
271     {
272       vendid => 0x1039,
273       devid  => 0x0735,
274       func => 0,
275       procid => "Silicon Integrated Systems SIS735",
276       driver => "i2c-sis645",
277       match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
278     } ,
279     {
280       vendid => 0x1039,
281       devid  => 0x0745,
282       func => 0,
283       procid => "Silicon Integrated Systems SIS745",
284       driver => "i2c-sis645",
285       match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
286     } ,
287     {
288       vendid => 0x1039,
289       devid  => 0x0746,
290       func => 0,
291       procid => "Silicon Integrated Systems SIS746",
292       driver => "i2c-sis645",
293       match => sub { $_[0] =~ /^SMBus SiS645 adapter at 0x[0-9,a-f]{4}/ },
294     } ,
295     {
296       vendid => 0x1039,
297       devid  => 0x0730,
298       func => 0,
299       procid => "Silicon Integrated Systems SIS730",
300       driver => "i2c-sis630",
301       match => sub { $_[0] =~ /^SMBus SIS630 adapter at [0-9,a-f]{4}/ },
302     } ,
303#
304# Both Ali chips below have same PCI ID. Can't be helped. Only one should load.
305#
306     {
307       vendid => 0x10b9,
308       devid => 0x7101,
309       func => 0,
310       procid => "Acer Labs 1533/1543",
311       driver => "i2c-ali15x3",
312       match => sub { $_[0] =~ /^SMBus ALI15X3 adapter at/ },
313     },
314     {
315       vendid => 0x10b9,
316       devid => 0x7101,
317       func => 0,
318       procid => "Acer Labs 1535",
319       driver => "i2c-ali1535",
320       match => sub { $_[0] =~ /^SMBus ALI1535 adapter at/ },
321     },
322     { 
323       vendid => 0x106b,
324       devid  => 0x000e,
325       func => 0,
326       procid => "Apple Computer Inc. Hydra Mac I/O",
327       driver => "i2c-hydra",
328       match => sub { $_[0] =~ /^Hydra i2c/ },
329     },
330     { 
331       vendid => 0x1022,
332       devid  => 0x740b,
333       func => 3,
334       procid => "AMD-756 Athlon ACPI",
335       driver => "i2c-amd756",
336       match => sub { $_[0] =~ /^SMBus AMD756 adapter at [0-9,a-f]{4}/ },
337     },
338     { 
339       vendid => 0x1022,
340       devid  => 0x7413,
341       func => 3,
342       procid => "AMD-766 Athlon ACPI",
343       driver => "i2c-amd756",
344       match => sub { $_[0] =~ /^SMBus AMD766 adapter at [0-9,a-f]{4}/ },
345     },
346     { 
347       vendid => 0x1022,
348       devid  => 0x7443,
349       func => 3,
350       procid => "AMD-768 System Management",
351       driver => "i2c-amd756",
352       match => sub { $_[0] =~ /^SMBus AMD768 adapter at [0-9,a-f]{4}/ },
353     },
354     { 
355       vendid => 0x1022,
356       devid  => 0x746b,
357       func => 3,
358       procid => "AMD-8111 ACPI",
359       driver => "i2c-amd756",
360       match => sub { $_[0] =~ /^SMBus AMD8111 adapter at [0-9,a-f]{4}/ },
361     },
362     { 
363       vendid => 0x1022,
364       devid  => 0x746a,
365       func => 2,
366       procid => "AMD-8111 SMBus 2.0",
367       driver => "i2c-amd8111",
368       match => sub { $_[0] =~ /^SMBus2 AMD8111 adapter at [0-9,a-f]{4}/ },
369     },
370     {
371       vendid => 0x102b,
372       devid  => 0x0519,
373       func   => 0,
374       procid => "MGA 2064W [Millennium]",
375       driver => "i2c-matroxfb",
376       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
377     },
378     {
379       vendid => 0x102b,
380       devid  => 0x051a,
381       func   => 0,
382       procid => "MGA 1064SG [Mystique]",
383       driver => "i2c-matroxfb",
384       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
385     },
386     {
387       vendid => 0x102b,
388       devid  => 0x051b,
389       func   => 0,
390       procid => "MGA 2164W [Millennium II]",
391       driver => "i2c-matroxfb",
392       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
393     },
394     {
395       vendid => 0x102b,
396       devid  => 0x051e,
397       func   => 0,
398       procid => "MGA 1064SG [Mystique] AGP",
399       driver => "i2c-matroxfb",
400       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
401     },
402     {
403       vendid => 0x102b,
404       devid  => 0x051f,
405       func   => 0,
406       procid => "MGA 2164W [Millennium II] AGP",
407       driver => "i2c-matroxfb",
408       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
409     },
410     {
411       vendid => 0x102b,
412       devid  => 0x1000,
413       func   => 0,
414       procid => "MGA G100 [Productiva]",
415       driver => "i2c-matroxfb",
416       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
417     },
418     {
419       vendid => 0x102b,
420       devid  => 0x1001,
421       func   => 0,
422       procid => "MGA G100 [Productiva] AGP",
423       driver => "i2c-matroxfb",
424       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
425     },
426     {
427       vendid => 0x102b,
428       devid  => 0x0520,
429       func   => 0,
430       procid => "MGA G200",
431       driver => "i2c-matroxfb",
432       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
433     },
434     {
435       vendid => 0x102b,
436       devid  => 0x0521,
437       func   => 0,
438       procid => "MGA G200 AGP",
439       driver => "i2c-matroxfb",
440       match  => sub { $_[0] =~ /^DDC:fb[0-9]{1,2}/ },
441     },
442     {
443       vendid => 0x102b,
444       devid  => 0x0525,
445       func   => 0,
446       procid => "MGA G400 AGP",
447       driver => "i2c-matroxfb",
448       match  => sub { $_[0] =~ /^(DDC,MAVEN):fb[0-9]{1,2}/ },
449     },
450     {
451       vendid => 0x121a,
452       devid  => 0x0005,
453       func   => 0,
454       procid => "3Dfx Voodoo3",
455       driver => "i2c-voodoo3",
456       match  => sub { $_[0] =~ /Banshee adapter/ },
457     },
458     {
459       vendid => 0x121a,
460       devid  => 0x0003,
461       func   => 0,
462       procid => "3Dfx Voodoo Banshee",
463       driver => "i2c-voodoo3",
464       match  => sub { $_[0] =~ /Banshee adapter/ },
465     },
466     { 
467       vendid => 0x8086,
468       devid  => 0x7121,
469       func => 0,
470       procid => "Intel 82810 GMCH",
471       driver => "i2c-i810",
472       match => sub { $_[0] =~ /^I810/ },
473     } , 
474     { 
475       vendid => 0x8086,
476       devid  => 0x7123,
477       func => 0,
478       procid => "Intel 82810-DC100 GMCH",
479       driver => "i2c-i810",
480       match => sub { $_[0] =~ /^I810/ },
481     } , 
482     { 
483       vendid => 0x8086,
484       devid  => 0x7125,
485       func => 0,
486       procid => "Intel 82810E GMCH",
487       driver => "i2c-i810",
488       match => sub { $_[0] =~ /^I810/ },
489     } , 
490     { 
491       vendid => 0x8086,
492       devid  => 0x1132,
493       func => 0,
494       procid => "Intel 82815 GMCH",
495       driver => "i2c-i810",
496       match => sub { $_[0] =~ /^I810/ },
497     } , 
498     { 
499       vendid => 0x12d2,
500       devid  => 0x0018,
501       func => 0,
502       procid => "RIVA 128",
503       driver => "rivatv",
504       match => sub { $_[0] =~ /^NVIDIA display/ },
505     } , 
506     { 
507       vendid => 0x10de,
508       devid  => 0x0020,
509       func => 0,
510       procid => "RIVA TNT",
511       driver => "rivatv",
512       match => sub { $_[0] =~ /^NVIDIA display/ },
513     } , 
514     { 
515       vendid => 0x10de,
516       devid  => 0x0028,
517       func => 0,
518       procid => "RIVA TNT2",
519       driver => "rivatv",
520       match => sub { $_[0] =~ /^NVIDIA display/ },
521     } , 
522     { 
523       vendid => 0x10de,
524       devid  => 0x0029,
525       func => 0,
526       procid => "RIVA UTNT2",
527       driver => "rivatv",
528       match => sub { $_[0] =~ /^NVIDIA display/ },
529     } , 
530     { 
531       vendid => 0x10de,
532       devid  => 0x002c,
533       func => 0,
534       procid => "RIVA VTNT2",
535       driver => "rivatv",
536       match => sub { $_[0] =~ /^NVIDIA display/ },
537     } , 
538     { 
539       vendid => 0x10de,
540       devid  => 0x002d,
541       func => 0,
542       procid => "RIVA UVTNT2",
543       driver => "rivatv",
544       match => sub { $_[0] =~ /^NVIDIA display/ },
545     } , 
546     { 
547       vendid => 0x10de,
548       devid  => 0x00a0,
549       func => 0,
550       procid => "RIVA ITNT2",
551       driver => "rivatv",
552       match => sub { $_[0] =~ /^NVIDIA display/ },
553     } , 
554     { 
555       vendid => 0x10de,
556       devid  => 0x0100,
557       func => 0,
558       procid => "GeForce SDR",
559       driver => "rivatv",
560       match => sub { $_[0] =~ /^NVIDIA display/ },
561     } , 
562     { 
563       vendid => 0x10de,
564       devid  => 0x0101,
565       func => 0,
566       procid => "GeForce DDR",
567       driver => "rivatv",
568       match => sub { $_[0] =~ /^NVIDIA display/ },
569     } , 
570     { 
571       vendid => 0x10de,
572       devid  => 0x0102,
573       func => 0,
574       procid => "Quadro",
575       driver => "rivatv",
576       match => sub { $_[0] =~ /^NVIDIA display/ },
577     } , 
578     { 
579       vendid => 0x10de,
580       devid  => 0x0150,
581       func => 0,
582       procid => "GeForce2 GTS",
583       driver => "rivatv",
584       match => sub { $_[0] =~ /^NVIDIA display/ },
585     } , 
586     { 
587       vendid => 0x10de,
588       devid  => 0x0110,
589       func => 0,
590       procid => "GeForce2 MX",
591       driver => "rivatv",
592       match => sub { $_[0] =~ /^NVIDIA display/ },
593     } , 
594     { 
595       vendid => 0x10de,
596       devid  => 0x0111,
597       func => 0,
598       procid => "GeForce2 MX2",
599       driver => "rivatv",
600       match => sub { $_[0] =~ /^NVIDIA display/ },
601     } , 
602     { 
603       vendid => 0x10de,
604       devid  => 0x0113,
605       func => 0,
606       procid => "Quadro2 MXR",
607       driver => "rivatv",
608       match => sub { $_[0] =~ /^NVIDIA display/ },
609     } , 
610     { 
611       vendid => 0x10de,
612       devid  => 0x0151,
613       func => 0,
614       procid => "GeForce2 GTS2",
615       driver => "rivatv",
616       match => sub { $_[0] =~ /^NVIDIA display/ },
617     } , 
618     { 
619       vendid => 0x10de,
620       devid  => 0x0152,
621       func => 0,
622       procid => "GeForce2 Ultra",
623       driver => "rivatv",
624       match => sub { $_[0] =~ /^NVIDIA display/ },
625     } , 
626     { 
627       vendid => 0x10de,
628       devid  => 0x0153,
629       func => 0,
630       procid => "Quadro2 Pro",
631       driver => "rivatv",
632       match => sub { $_[0] =~ /^NVIDIA display/ },
633     } , 
634     { 
635       vendid => 0x10de,
636       devid  => 0x01b4,
637       func => 1,
638       procid => "nVidia nForce SMBus",
639       driver => "i2c-amd756",
640       match => sub { $_[0] =~ /^SMBus nVidia nForce adapter at [0-9,a-f]{4}/ },
641     } , 
642     { 
643       vendid => 0x10de,
644       devid  => 0x0064,
645       func => 1,
646       procid => "nVidia Corporation nForce2 SMBus (MCP)",
647       driver => "i2c-nforce2",
648       match => sub { $_[0] =~ /^SMBus nForce2 adapter at / },
649     } , 
650     { 
651       vendid => 0x1166,
652       devid  => 0x0200,
653       func => 0,
654       procid => "ServerWorks OSB4 South Bridge",
655       driver => "i2c-piix4",
656       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
657     } , 
658     { 
659       vendid => 0x1055,
660       devid  => 0x9463,
661       func => 0,
662       procid => "SMSC Victory66 South Bridge",
663       driver => "i2c-piix4",
664       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
665     } , 
666     { 
667       vendid => 0x1166,
668       devid  => 0x0201,
669       func => 0,
670       procid => "ServerWorks CSB5 South Bridge",
671       driver => "i2c-piix4",
672       match => sub { $_[0] =~ /^SMBus PIIX4 adapter at / },
673     } , 
674     { 
675       vendid => 0x1283,
676       devid  => 0x8172,
677       func => 0,
678       procid => "ITE 8172G MIPS/SH4 Support Chip",
679       driver => "i2c-adap-ite",
680       match => sub { $_[0] =~ /^ITE IIC adapter/ },
681     } , 
682     { 
683       vendid => 0x5333,
684       devid  => 0x8A20,
685       func => 0,
686       procid => "S3 Savage 3D",
687       driver => "to-be-written",
688       match => sub { 0 },
689     } , 
690     { 
691       vendid => 0x5333,
692       devid  => 0x8A21,
693       func => 0,
694       procid => "S3 Savage 3D MV",
695       driver => "to-be-written",
696       match => sub { 0 },
697     } , 
698     { 
699       vendid => 0x5333,
700       devid  => 0x8A22,
701       func => 0,
702       procid => "S3 Savage 4",
703       driver => "i2c-savage4",
704       match => sub { $_[0] =~ /Savage4 adapter/ },
705     } , 
706     { 
707       vendid => 0x5333,
708       devid  => 0x9102,
709       func => 0,
710       procid => "S3 Savage 2000",
711       driver => "i2c-savage4",
712       match => sub { $_[0] =~ /Savage4 adapter/ },
713     } , 
714     { 
715       vendid => 0x5333,
716       devid  => 0x8A25,
717       func => 0,
718       procid => "S3 ProSavage PM",
719       driver => "to-be-written",
720       match => sub { $_[0] =~ /^dontmatchthis/ },
721     } , 
722     { 
723       vendid => 0x5333,
724       devid  => 0x8A26,
725       func => 0,
726       procid => "S3 ProSavage KM",
727       driver => "to-be-written",
728       match => sub { 0 },
729     } , 
730     { 
731       vendid => 0x5333,
732       devid  => 0x8C10,
733       func => 0,
734       procid => "S3 Savage MX MV",
735       driver => "to-be-written",
736       match => sub { 0 },
737     } , 
738     { 
739       vendid => 0x5333,
740       devid  => 0x8C11,
741       func => 0,
742       procid => "S3 Savage MX",
743       driver => "to-be-written",
744       match => sub { 0 },
745     } , 
746     { 
747       vendid => 0x5333,
748       devid  => 0x8C12,
749       func => 0,
750       procid => "S3 Savage IX MV",
751       driver => "to-be-written",
752       match => sub { 0 },
753     } , 
754     { 
755       vendid => 0x5333,
756       devid  => 0x8C13,
757       func => 0,
758       procid => "S3 Savage IX",
759       driver => "to-be-written",
760       match => sub { 0 },
761     } , 
762);
763
764use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect
765            lm75_detect lm80_detect w83781d_detect w83781d_alias_detect
766            adm1025_detect w83781d_isa_detect gl518sm_detect gl520sm_detect
767            adm9240_detect adm1021_detect sis5595_isa_detect eeprom_detect
768            via686a_isa_detect adm1022_detect ltc1710_detect gl525sm_detect
769            lm87_detect ite_detect ite_isa_detect ite_alias_detect
770            ddcmonitor_detect ds1621_detect adm1024_detect fscpos_detect
771            fscscy_detect pcf8591_detect arp_detect ipmi_kcs_detect
772            ipmi_smic_detect via8231_isa_detect lm85_detect smartbatt_detect
773            adm1026_detect w83l785ts_detect lm83_detect lm90_detect
774            saa1064_detect w83l784r_detect);
775
776# This is a list of all recognized chips.
777# Each entry must have the following fields:
778#  name: The full chip name
779#  driver: The driver name (without .o extension). Put in something like
780#      "Unwritten: <drivername>" if it is not yet available.
781#  i2c_addrs (optional): For I2C chips, the range of valid I2C addresses to
782#      probe. Recommend avoiding 0x69 because of clock chips.
783#  i2c_driver_addrs (optional): For I2C chips, the range of valid I2C
784#      addresses probed by the kernel driver. Strictly optional.
785#  i2c_detect (optional): For I2C chips, the function to call to detect
786#      this chip. The function should take two parameters: an open file
787#      descriptor to access the bus, and the I2C address to probe.
788#  isa_addrs (optional): For ISA chips, the range of valid port addresses to
789#      probe.
790#  isa_driver_addrs (optional): For ISA chips, the range of valid ISA
791#      addresses probed by the kernel driver. Strictly optional.
792#  isa_detect (optional): For ISA chips, the function to call to detect
793#      this chip. The function should take one parameter: the ISA address
794#      to probe.
795#  alias_detect (optional): For chips which can be both on the ISA and the
796#      I2C bus, a function which detectes whether two entries are the same.
797#      The function should take three parameters: The ISA address, the
798#      I2C bus number, and the I2C address.
799@chip_ids = (
800     {
801       name => "Myson MTP008",
802       driver => "mtp008",
803       i2c_addrs => [0x2c..0x2e], 
804       i2c_detect => sub { mtp008_detect @_},
805     } ,
806     {
807       name => "National Semiconductor LM78",
808       driver => "lm78",
809       i2c_addrs => [0x20..0x2f], 
810       i2c_detect => sub { lm78_detect 0, @_},
811       isa_addrs => [0x290],
812       isa_detect => sub { lm78_isa_detect 0, @_ },
813       alias_detect => sub { lm78_alias_detect 0, @_ },
814     } ,
815     {
816       name => "National Semiconductor LM78-J",
817       driver => "lm78",
818       i2c_addrs => [0x20..0x2f], 
819       i2c_detect => sub { lm78_detect 1, @_ },
820       isa_addrs => [0x290],
821       isa_detect => sub { lm78_isa_detect 1, @_ },
822       alias_detect => sub { lm78_alias_detect 1, @_ },
823     } ,
824     {
825       name => "National Semiconductor LM79",
826       driver => "lm78",
827       i2c_addrs => [0x20..0x2f], 
828       i2c_detect => sub { lm78_detect 2, @_ },
829       isa_addrs => [0x290],
830       isa_detect => sub { lm78_isa_detect 2, @_ },
831       alias_detect => sub { lm78_alias_detect 2, @_ },
832     } ,
833     {
834       name => "National Semiconductor LM75",
835       driver => "lm75",
836       i2c_addrs => [0x48..0x4f],
837       i2c_detect => sub { lm75_detect @_},
838     } ,
839     {
840       name => "National Semiconductor LM80",
841       driver => "lm80",
842       i2c_addrs => [0x28..0x2f],
843       i2c_detect => sub { lm80_detect @_} ,
844     },
845     {
846       name => "National Semiconductor LM85",
847       driver => "lm85",
848       i2c_addrs => [0x2c..0x2e],
849       i2c_detect => sub { lm85_detect 0x01, @_},
850     },
851     {
852       name => "Analog Devices ADM1027 or ADT7463",
853       driver => "lm85",
854       i2c_addrs => [0x2c..0x2e],
855       i2c_detect => sub { lm85_detect 0x41, @_},
856     },
857     {
858       name => "SMSC EMC6D100 and EMC6D101",
859       driver => "lm85",
860       i2c_addrs => [0x2c..0x2e],
861       i2c_detect => sub { lm85_detect 0x5c, @_},
862     },
863     {
864       name => "National Semiconductor LM87",
865       driver => "lm87",
866       i2c_addrs => [0x2c..0x2e],
867       i2c_detect => sub { lm87_detect @_} ,
868     },
869     {
870       name => "Winbond W83781D",
871       driver => "w83781d",
872       i2c_detect => sub { w83781d_detect 0, @_},
873       i2c_addrs => [0x20..0x2f], 
874       isa_addrs => [0x290],
875       isa_detect => sub { w83781d_isa_detect 0, @_ },
876       alias_detect => sub { w83781d_alias_detect 0, @_ },
877     } ,
878     {
879       name => "Winbond W83782D",
880       driver => "w83781d",
881       i2c_addrs => [0x20..0x2f], 
882       i2c_detect => sub { w83781d_detect 1, @_},
883       isa_addrs => [0x290],
884       isa_detect => sub { w83781d_isa_detect 1, @_ },
885       alias_detect => sub { w83781d_alias_detect 1, @_ },
886     } ,
887     {
888       name => "Winbond W83783S",
889       driver => "w83781d",
890       i2c_addrs => [0x2d],
891       i2c_detect => sub { w83781d_detect 2, @_},
892     } ,
893     {
894       name => "Winbond W83791D",
895       driver => "w83781d",
896       i2c_addrs => [0x2c..0x2f],
897       i2c_detect => sub { w83781d_detect 7, @_},
898     } ,
899     {
900       name => "Winbond W83627HF",
901       driver => "w83781d",
902       i2c_addrs => [0x20..0x2f], 
903       i2c_detect => sub { w83781d_detect 3, @_},
904       isa_addrs => [0x290],
905       isa_detect => sub { w83781d_isa_detect 3, @_ },
906       alias_detect => sub { w83781d_alias_detect 3, @_ },
907     } ,
908     {
909       name => "Asus AS99127F (rev.1)",
910       driver => "w83781d",
911       i2c_addrs => [0x28..0x2f],
912       i2c_detect => sub { w83781d_detect 4, @_},
913     } ,
914     {
915       name => "Asus AS99127F (rev.2)",
916       driver => "w83781d",
917       i2c_addrs => [0x28..0x2f],
918       i2c_detect => sub { w83781d_detect 5, @_},
919     } ,
920     {
921       name => "Asus ASB100 Bach",
922       driver => "w83781d",
923       i2c_addrs => [0x28..0x2f],
924       i2c_detect => sub { w83781d_detect 6, @_},
925     } ,
926     {
927       name => "Winbond W83L784R/AR",
928       driver => "to-be-written",
929       i2c_addrs => [0x2d],
930       i2c_detect => sub { w83l784r_detect 0, @_},
931     } ,
932     {
933       name => "Winbond W83L785TS",
934       driver => "to-be-written",
935       i2c_addrs => [0x2e], 
936       i2c_detect => sub { w83l785ts_detect 0, @_},
937     } ,
938     {
939       name => "Winbond W83697HF",
940       driver => "w83781d",
941       isa_addrs => [0x290],
942       isa_detect => sub { w83781d_isa_detect 5, @_ },
943     } ,
944     {
945       name => "Genesys Logic GL518SM Revision 0x00",
946       driver => "gl518sm",
947       i2c_addrs => [0x2c, 0x2d],
948       i2c_detect => sub { gl518sm_detect 0, @_} ,
949     },
950     {
951       name => "Genesys Logic GL518SM Revision 0x80",
952       driver => "gl518sm",
953       i2c_addrs => [0x2c, 0x2d],
954       i2c_detect => sub { gl518sm_detect 1, @_} ,
955     },
956     {
957       name => "Genesys Logic GL520SM",
958       driver => "gl520sm",
959       i2c_addrs => [0x2c, 0x2d],
960       i2c_detect => sub { gl520sm_detect @_} ,
961     },
962     {
963       name => "Genesys Logic GL525SM",
964       driver => "Unwritten (GL525SM)",
965       i2c_addrs => [0x2d],
966       i2c_detect => sub { gl525sm_detect @_} ,
967     },
968     {
969       name => "Analog Devices ADM9240",
970       driver => "adm9240",
971       i2c_addrs => [0x2c..0x2f],
972       i2c_detect => sub { adm9240_detect 0, @_ }
973     },
974     {
975       name => "Dallas Semiconductor DS1621",
976       driver => "ds1621",
977       i2c_addrs => [0x48..0x4f],
978       i2c_detect => sub { ds1621_detect @_},
979     } ,
980     {
981       name => "Dallas Semiconductor DS1780",
982       driver => "adm9240",
983       i2c_addrs => [0x2c..0x2f],
984       i2c_detect => sub { adm9240_detect 1, @_ }
985     },
986     {
987       name => "National Semiconductor LM81",
988       driver => "adm9240",
989       i2c_addrs => [0x2c..0x2f],
990       i2c_detect => sub { adm9240_detect 2, @_ }
991     },
992     {
993       name => "Analog Devices ADM1026",
994       driver => "adm1026",
995       i2c_addrs => [0x2c,0x2d,0x2e],
996       i2c_detect => sub { adm1026_detect 0, @_ }
997     },
998     {
999       name => "Analog Devices ADM1025",
1000       driver => "adm1025",
1001       i2c_addrs => [0x2c..0x2e],
1002       i2c_detect => sub { adm1025_detect 0, @_ }
1003     },
1004     {
1005       name => "Philips NE1619",
1006       driver => "adm1025",
1007       i2c_addrs => [0x2c..0x2d],
1008       i2c_detect => sub { adm1025_detect 1, @_ }
1009     },
1010     {
1011       name => "Analog Devices ADM1024",
1012       driver => "adm1024",
1013       i2c_addrs => [0x2c..0x2e],
1014       i2c_detect => sub { adm1024_detect 0, @_ }
1015     },
1016     {
1017       name => "Analog Devices ADM1021",
1018       driver => "adm1021",
1019       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1020       i2c_detect => sub { adm1021_detect 0, @_ },
1021     },
1022     {
1023       name => "Analog Devices ADM1021A/ADM1023",
1024       driver => "adm1021",
1025       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1026       i2c_detect => sub { adm1021_detect 1, @_ },
1027     },
1028     {
1029       name => "Maxim MAX1617",
1030       driver => "adm1021",
1031       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1032       i2c_detect => sub { adm1021_detect 2, @_ },
1033     },
1034     {
1035       name => "Maxim MAX1617A",
1036       driver => "adm1021",
1037       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1038       i2c_detect => sub { adm1021_detect 3, @_ },
1039     },
1040     {
1041       name => "TI THMC10",
1042       driver => "adm1021",
1043       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1044       i2c_detect => sub { adm1021_detect 4, @_ },
1045     },
1046     {
1047       name => "National Semiconductor LM84",
1048       driver => "adm1021",
1049       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1050       i2c_detect => sub { adm1021_detect 5, @_ },
1051     },
1052     {
1053       name => "Genesys Logic GL523SM",
1054       driver => "adm1021",
1055       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1056       i2c_detect => sub { adm1021_detect 6, @_ },
1057     },
1058     {
1059       name => "Onsemi MC1066",
1060       driver => "adm1021",
1061       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1062       i2c_detect => sub { adm1021_detect 7, @_ },
1063     },
1064     {
1065       name => "National Semiconductor LM82",
1066       driver => "to-be-written",
1067       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1068       i2c_detect => sub { lm83_detect 1, @_ },
1069     },
1070     {
1071       name => "National Semiconductor LM83",
1072       driver => "lm83",
1073       i2c_addrs => [0x18..0x1a,0x29..0x2b,0x4c..0x4e],
1074       i2c_detect => sub { lm83_detect 0, @_ },
1075     },
1076     {
1077       name => "National Semiconductor LM90",
1078       driver => "to-be-written",
1079       i2c_addrs => [0x4c],
1080       i2c_detect => sub { lm90_detect 0, @_ },
1081     },
1082     {
1083       name => "National Semiconductor LM89",
1084       driver => "to-be-written",
1085       i2c_addrs => [0x4c],
1086       i2c_detect => sub { lm90_detect 1, @_ },
1087     },
1088     {
1089       name => "National Semiconductor LM86",
1090       driver => "to-be-written",
1091       i2c_addrs => [0x4c],
1092       i2c_detect => sub { lm90_detect 2, @_ },
1093     },
1094     {
1095       name => "Analog Devices ADM1022",
1096       driver => "thmc50",
1097       i2c_addrs => [0x2c..0x2f],
1098       i2c_detect => sub { adm1022_detect 0, @_ },
1099     },
1100     {
1101       name => "Texas Instruments THMC50",
1102       driver => "thmc50",
1103       i2c_addrs => [0x2c..0x2f],
1104       i2c_detect => sub { adm1022_detect 1, @_ },
1105     },
1106     {
1107       name => "Silicon Integrated Systems SIS5595",
1108       driver => "sis5595",
1109       isa_addrs => [ 0 ],
1110       isa_detect => sub { sis5595_isa_detect @_ },
1111     },
1112     {
1113       name => "VIA Technologies VT82C686 Integrated Sensors",
1114       driver => "via686a",
1115       isa_addrs => [ 0 ],
1116       isa_detect => sub { via686a_isa_detect @_ },
1117     },
1118     {
1119       name => "VIA Technologies VT8231 Integrated Sensors",
1120       driver => "vt8231",
1121       isa_addrs => [ 0 ],
1122       isa_detect => sub { via8231_isa_detect @_ },
1123     },
1124     {
1125       name => "ITE IT8705F / IT8712F / SiS 950",
1126       driver => "it87",
1127       i2c_addrs => [0x20..0x2f],
1128       i2c_detect => sub { ite_detect 0, @_ },
1129       isa_addrs => [0x290],
1130       isa_detect => sub { ite_isa_detect 0, @_ },
1131     } ,
1132     {
1133       name => "Serial EEPROM",
1134       driver => "eeprom",
1135       i2c_addrs => [0x50..0x57],
1136       i2c_detect => sub { eeprom_detect @_ },
1137     },
1138     {
1139       name => "LTC1710",
1140       driver => "ltc1710",
1141       i2c_addrs => [0x58..0x5a],
1142       i2c_detect => sub { ltc1710_detect @_ },
1143     },
1144     {
1145       name => "DDC monitor",
1146       driver => "ddcmon",
1147       i2c_addrs => [0x50],
1148       i2c_detect => sub { ddcmonitor_detect @_ },
1149     },
1150     {
1151       name => "FSC poseidon chip",
1152       driver => "fscpos",
1153       i2c_addrs => [0x73],
1154       i2c_detect => sub { fscpos_detect @_ },
1155     },
1156     {
1157       name => "FSC Scylla chip",
1158       driver => "fscscy",
1159       i2c_addrs => [0x73],
1160       i2c_detect => sub { fscscy_detect @_ },
1161     },
1162     {
1163       name => "Philips Semiconductors PCF8591",
1164       driver => "pcf8591",
1165       i2c_addrs => [0x48..0x4f],
1166       i2c_detect => sub { pcf8591_detect 0, @_ },
1167     },
1168     {
1169       name => "Philips Semiconductors PCF8574",
1170       driver => "pcf8574",
1171       i2c_addrs => [0x20..0x27],
1172       i2c_detect => sub { pcf8591_detect 1, @_ },
1173     },
1174     {
1175       name => "Philips Semiconductors PCF8574A",
1176       driver => "pcf8574",
1177       i2c_addrs => [0x38..0x3f],
1178       i2c_detect => sub { pcf8591_detect 2, @_ },
1179     },
1180     {
1181       name => "Philips Semiconductors SAA1064",
1182       driver => "saa1064",
1183       i2c_addrs => [0x38..0x3b],
1184       i2c_detect => sub { saa1064_detect @_ },
1185     },
1186     {
1187       name => "SMBus 2.0 ARP-Capable Device",
1188       driver => "smbus-arp",
1189       i2c_addrs => [0x61],
1190       i2c_detect => sub { arp_detect @_},
1191     },
1192     {
1193       name => "IPMI BMC KCS",
1194       driver => "bmcsensors",
1195       isa_addrs => [ 0x0ca0 ],
1196       isa_detect => sub { ipmi_kcs_detect @_ },
1197     },
1198     {
1199       name => "IPMI BMC SMIC",
1200       driver => "bmcsensors",
1201       isa_addrs => [ 0x0ca8 ],
1202       isa_detect => sub { ipmi_smic_detect @_ },
1203     },
1204     {
1205       name => "Smart Battery",
1206       driver => "smartbatt",
1207       i2c_addrs => [0x0b],
1208       i2c_detect => sub { smartbatt_detect @_},
1209     },
1210);
1211
1212# This is a list of all recognized superio chips.
1213# Each entry must have the following fields:
1214#  name: The full chip name
1215#  driver: The driver name (without .o extension). Put in something like
1216#      "Unwritten: <drivername>" if it is not yet available.
1217#  addrreg: The address register
1218#  datareg: The data register
1219#  enter: The password sequence to write to the address register
1220#  devidreg: The device ID register(s)
1221#  devid: The device ID(s) we have to match (base device)
1222#  logdevreg: The logical device register
1223#  logdev: The logical device containing the sensors
1224#  actreg (optional): The activation register within the logical device
1225#  actmask (optional): The activation bit in the activation register
1226#  basereg: The I/O base register within the logical device
1227#  exitreg: The register to write the exit value to
1228#  exit: The value to write to the exit register to exit
1229#  alias_detect (optional): For chips which can be both on the ISA and the
1230#      I2C bus, a function which detectes whether two entries are the same.
1231#      The function should take three parameters: The ISA address, the
1232#      I2C bus number, and the I2C address.
1233@superio_ids = (
1234#     {
1235#       name => "ITE 8705 Super IO Sensors",
1236#       driver => "it87",
1237#       addrreg => 0x2e,
1238#       datareg => 0x2f,
1239#       enter => [0x55, 0x01, 0x55, 0x55].
1240# code doesn't handle multiple devid regs yet
1241#       devidreg => [0x20, 0x21],
1242#       devid => [0x87, 0x05],
1243#       logdevreg => 0x07,
1244#       logdev => 0x04,
1245#       actreg => 0x30,
1246#       actmask => 0x01,
1247#       basereg => 0x60,
1248# exit is writing 0x01 to reg 0x02. - not compatible with other superio chips
1249#       exitreg => 0x02,
1250#       exit => 0x01,
1251#     },
1252# Nat'l untested
1253#     {
1254#       name => "Nat. Semi. PC87366 Super I/O Sensors",
1255#       driver => "xxxx",
1256#       addrreg => 0x2e,
1257#       datareg => 0x2f,
1258#       enter => ?? none required?
1259#       devidreg => 0x20,
1260#       devid => 0xe9,
1261#       logdevreg => 0x07,
1262#       logdev => 0x09 # fans; temps at 0x0e
1263#       actreg => 0x30,
1264#       actmask => 0x01,
1265#       basereg => 0x60,
1266# exit is writing 0x01 to reg 0x02. - not compatible with other superio chips
1267#       exitreg => ?? none req'd??
1268#       exit => ??
1269#     },
1270     {
1271        name => "SMSC 47M1xx Super IO Fan Sensors",
1272        driver => "smsc47m1",
1273        addrreg => 0x2e,
1274        exitreg => 0x2e,
1275        datareg => 0x2f,
1276        enter => [0x55],
1277        devidreg => 0x20,
1278        devid => 0x59,
1279        logdevreg => 0x07,
1280        logdev => 0x0a,
1281        actreg => 0x20,
1282        actmask => 0x01,
1283        basereg => 0x60,
1284        exit => 0xaa,
1285     }, 
1286     {
1287        name => "VT1211 Super IO Sensors",
1288        driver => "vt1211",
1289        addrreg => 0x2e,
1290        exitreg => 0x2e,
1291        datareg => 0x2f,
1292        enter => [0x87, 0x87],
1293        devidreg => 0x20,
1294        devid => 0x3c,
1295        logdevreg => 0x07,
1296        logdev => 0x0b,
1297        actreg => 0x30,
1298        actmask => 0x01,
1299        basereg => 0x60,
1300        exit => 0xaa,
1301     }, 
1302     {
1303        name => "Winbond W83627HF Super IO Sensors",
1304        driver => "w83627hf",
1305        addrreg => 0x2e,
1306        exitreg => 0x2e,
1307        datareg => 0x2f,
1308        enter => [0x87, 0x87],
1309        devidreg => 0x20,
1310        devid => 0x52,
1311        logdevreg => 0x07,
1312        logdev => 0x0b,
1313        actreg => 0x30,
1314        actmask => 0x01,
1315        basereg => 0x60,
1316        exit => 0xaa,
1317     }, 
1318     {
1319        name => "Winbond W83627THF Super IO Sensors",
1320        driver => "w83627hf",
1321        addrreg => 0x2e,
1322        exitreg => 0x2e,
1323        datareg => 0x2f,
1324        enter => [0x87, 0x87],
1325        devidreg => 0x20,
1326        devid => 0x82,
1327        logdevreg => 0x07,
1328        logdev => 0x0b,
1329        actreg => 0x30,
1330        actmask => 0x01,
1331        basereg => 0x60,
1332        exit => 0xaa,
1333     }, 
1334     {
1335        name => "Winbond W83697HF Super IO Sensors",
1336        driver => "w83627hf",
1337        addrreg => 0x2e,
1338        exitreg => 0x2e,
1339        datareg => 0x2f,
1340        enter => [0x87, 0x87],
1341        devidreg => 0x20,
1342        devid => 0x60,
1343        logdevreg => 0x07,
1344        logdev => 0x0b,
1345        actreg => 0x30,
1346        actmask => 0x01,
1347        basereg => 0x60,
1348        exit => 0xaa,
1349     }, 
1350);
1351
1352#######################
1353# AUXILIARY FUNCTIONS #
1354#######################
1355
1356sub swap_bytes
1357{
1358  return (($_[0] & 0xff00) >> 8) + (($_[0] & 0x00ff) << 8)
1359}
1360
1361# $_[0] is the sought value
1362# @_[1..] is the list to seek in
1363# Returns: 0 on failure, 1 if found.
1364sub contains
1365{
1366  my $sought = shift;
1367  foreach (@_) {
1368    return 1 if $sought eq $_;
1369  }
1370  return 0;
1371}
1372
1373sub parse_not_to_scan
1374{
1375  my ($min,$max,$to_parse) = @_;
1376  my @ranges = split /\s*,\s*/, $to_parse;
1377  my @res = ();
1378  my $range;
1379  foreach $range (@ranges) {
1380    my ($start,$end) = split /\s*-s*/, $range;
1381    $start = oct $start if $start =~ /^0/;
1382    if (defined $end) {
1383      $end = oct $end if $end =~ /^0/;
1384      $start = $min if $start < $min;
1385      $end = $max if $end > $max;
1386      push @res, ($start+0..$end+0);
1387    } else {
1388      push @res, $start+0 if $start >= $min and $start <= $max;
1389    }
1390  }
1391  return sort { $a <=> $b } @res;
1392}
1393
1394# @_[0]: Reference to list 1
1395# @_[1]: Reference to list 2
1396# Result: 0 if they have no elements in common, 1 if they have
1397# Elements must be numeric.
1398sub any_list_match
1399{
1400  my ($list1,$list2) = @_;
1401  my ($el1,$el2);
1402  foreach $el1 (@$list1) {
1403    foreach $el2 (@$list2) {
1404      return 1 if $el1 == $el2;
1405    }
1406  }
1407  return 0;
1408}
1409
1410###################
1411# I/O port access #
1412###################
1413
1414sub initialize_ioports
1415{
1416  sysopen (IOPORTS, "/dev/port", O_RDWR)
1417    or die "/dev/port: $!\n";
1418  binmode IOPORTS;
1419}
1420
1421sub close_ioports
1422{
1423  close (IOPORTS)
1424    or print "Warning: $!\n";
1425}
1426
1427# $_[0]: port to read
1428# Returns: -1 on failure, read value on success.
1429sub inb
1430{
1431  my ($res,$nrchars);
1432  sysseek IOPORTS, $_[0], 0 or return -1;
1433  $nrchars = sysread IOPORTS, $res, 1;
1434  return -1 if not defined $nrchars or $nrchars != 1;
1435  $res = unpack "C",$res ;
1436  return $res;
1437}
1438
1439# $_[0]: port to write
1440# $_[1]: value to write
1441# Returns: -1 on failure, 0 on success.
1442sub outb
1443{
1444  if ($_[1] > 0xff)
1445  {
1446    my ($package, $filename, $line, $sub) = caller(1);
1447    print "\n*** Called outb with value=$_[1] from line $line\n",
1448          "*** (in $sub). PLEASE REPORT!\n",
1449          "*** Terminating.\n";
1450    exit(-1);
1451  }
1452  my $towrite = pack "C", $_[1];
1453  sysseek IOPORTS, $_[0], 0 or return -1;
1454  my $nrchars = syswrite IOPORTS, $towrite, 1;
1455  return -1 if not defined $nrchars or $nrchars != 1;
1456  return 0;
1457}
1458
1459# $_[0]: Address register
1460# $_[1]: Data register
1461# $_[2]: Register to read
1462# Returns: read value
1463sub isa_read_byte
1464{
1465  outb $_[0],$_[2];
1466  return inb $_[1];
1467}
1468
1469# $_[0]: Address register
1470# $_[1]: Data register
1471# $_[2]: Register to write
1472# $_[3}: Value to write
1473# Returns: nothing
1474sub isa_write_byte
1475{
1476  outb $_[0],$_[2];
1477  outb $_[1],$_[3];
1478}
1479
1480###########
1481# MODULES #
1482###########
1483
1484use vars qw(@modules_list);
1485
1486sub initialize_modules_list
1487{
1488  open INPUTFILE, "/proc/modules" or die "Can't access /proc/modules!";
1489  while (<INPUTFILE>) {
1490    push @modules_list, /^(\S*)/ ;
1491  }
1492  close INPUTFILE;
1493}
1494
1495##############
1496# PCI ACCESS #
1497##############
1498
1499use vars qw(@pci_list);
1500
1501# This function returns a list of hashes. Each hash has some PCI information
1502# (more than we will ever need, probably). The most important
1503# fields are 'bus', 'slot', 'func' (they uniquely identify a PCI device in
1504# a computer) and 'vendid','devid' (they uniquely identify a type of device).
1505# /proc/bus/pci/devices is only available on late 2.1 and 2.2 kernels.
1506sub read_proc_dev_pci
1507{
1508  my ($dfn,$vend,@pci_list);
1509  open INPUTFILE, "/proc/bus/pci/devices" or return;
1510  while (<INPUTFILE>) {
1511    my $record = {};
1512    ($dfn,$vend,$record->{irq},$record->{base_addr0},$record->{base_addr1},
1513          $record->{base_addr2},$record->{base_addr3},$record->{base_addr4},
1514          $record->{base_addr5},$record->{rom_base_addr}) = 
1515          map { oct "0x$_" } (split) [0..9];
1516    $record->{bus} = $dfn >> 8;
1517    $record->{slot} = ($dfn & 0xf8) >> 3;
1518    $record->{func} = $dfn & 0x07;
1519    $record->{vendid} = $vend >> 16;
1520    $record->{devid} = $vend & 0xffff;
1521  push @pci_list,$record;
1522  }
1523  close INPUTFILE or return;
1524  return @pci_list;
1525}
1526
1527# This function returns a list of hashes. Each hash has some PCI
1528# information. The important fields here are 'bus', 'slot', 'func' (they
1529# uniquely identify a PCI device in a computer) and 'desc' (a functional
1530# description of the PCI device). If this is an 'unknown device', the
1531# vendid and devid fields are set instead.
1532sub read_proc_pci
1533{
1534  my @pci_list;
1535  open INPUTFILE, "/proc/pci" or return;
1536  while (<INPUTFILE>) {
1537    my $record = {};
1538    if (($record->{bus},$record->{slot},$record->{func}) = 
1539        /^\s*Bus\s*(\S)+\s*,\s*device\s*(\S+)\s*,\s*function\s*(\S+)\s*:\s*$/) {
1540      my $desc = <INPUTFILE>;
1541      $_ = <INPUTFILE>;
1542      if (($desc =~ /Unknown device/) and
1543              (($record->{vendid},$record->{devid}) = 
1544                         /^\s*Vendor id=(\S+)\.\s*Device id=(\S+)\.$/)) {
1545        $record->{vendid} = hex $record->{vendid};
1546        $record->{devid} = hex $record->{devid};
1547      } else {
1548        $record->{desc} = $desc;
1549      }
1550      push @pci_list,$record;
1551    }
1552  }
1553  close INPUTFILE or return;
1554  return @pci_list;
1555}
1556
1557sub initialize_proc_pci
1558{
1559  @pci_list = read_proc_dev_pci;
1560  @pci_list = read_proc_pci     if not defined @pci_list;
1561  die "Can't access either /proc/bus/pci/ or /proc/pci!" 
1562                                    if not defined @pci_list;
1563}
1564
1565#####################
1566# ADAPTER DETECTION #
1567#####################
1568
1569sub all_available_adapters
1570{
1571  my @res = ();
1572  my ($module,$adapter);
1573  MODULES:
1574  foreach $module (@modules_list) {
1575    foreach $adapter (@pci_adapters) {
1576      if (exists $adapter->{driver} and $module eq $adapter->{driver}) {
1577        push @res, $module;
1578        next MODULES;
1579      }
1580    }
1581  }
1582  return @res;
1583}
1584
1585sub adapter_pci_detection
1586{
1587  my ($device,$try,@res);
1588  print "Probing for PCI bus adapters...\n";
1589
1590  foreach $device (@pci_list) {
1591    foreach $try (@pci_adapters) {
1592      if ((defined($device->{vendid}) and 
1593           $try->{vendid} == $device->{vendid} and
1594           $try->{devid} == $device->{devid} and
1595           $try->{func} == $device->{func}) or
1596          (! defined($device->{vendid}) and
1597           $device->{desc} =~ /$try->{procid}/ and
1598           $try->{func} == $device->{func})) {
1599        printf "Use driver `%s' for device %02x:%02x.%x: %s\n",
1600               $try->{driver}?$try->{driver}:"<To Be Written>",
1601               $device->{bus},$device->{slot},$device->{func},$try->{procid};
1602        push @res,$try->{driver};
1603      }
1604    }
1605  }
1606  if (! @res) {
1607    print ("Sorry, no PCI bus adapters found.\n");
1608  } else {
1609    printf ("Probe succesfully concluded.\n");
1610  }
1611  return @res;
1612}
1613
1614# $_[0]: Adapter description as found in /proc/bus/i2c
1615# $_[1]: Algorithm description as found in /proc/bus/i2c
1616sub find_adapter_driver
1617{
1618  my $adapter;
1619  for $adapter (@pci_adapters) {
1620    return $adapter->{driver} if &{$adapter->{match}} ($_[0],$_[1]);
1621  }
1622  return "UNKNOWN";
1623}
1624
1625#############################
1626# I2C AND SMBUS /DEV ACCESS #
1627#############################
1628
1629# This should really go into a separate module/package.
1630
1631# To do: support i2c-level access (through sysread/syswrite, probably).
1632# I can't test this at all (PIIX4 does not support this), so I have not
1633# included it.
1634
1635use vars qw($IOCTL_I2C_RETRIES $IOCTL_I2C_TIMEOUT $IOCTL_I2C_UDELAY
1636            $IOCTL_I2C_MDELAY $IOCTL_I2C_SLAVE $IOCTL_I2C_TENBIT
1637            $IOCTL_I2C_SMBUS);
1638
1639# These are copied from <linux/i2c.h> and <linux/smbus.h>
1640
1641# For bit-adapters:
1642$IOCTL_I2C_RETRIES = 0x0701;
1643$IOCTL_I2C_TIMEOUT = 0x0702;
1644$IOCTL_I2C_UDELAY = 0x0705;
1645$IOCTL_I2C_MDELAY = 0x0706;
1646
1647# General ones:
1648$IOCTL_I2C_SLAVE = 0x0703;
1649$IOCTL_I2C_TENBIT = 0x0704;
1650$IOCTL_I2C_SMBUS = 0x0720;
1651
1652
1653
1654use vars qw($SMBUS_READ $SMBUS_WRITE $SMBUS_QUICK $SMBUS_BYTE $SMBUS_BYTE_DATA
1655            $SMBUS_WORD_DATA $SMBUS_PROC_CALL $SMBUS_BLOCK_DATA);
1656
1657# These are copied from <linux/smbus.h>
1658
1659$SMBUS_READ = 1;
1660$SMBUS_WRITE = 0;
1661$SMBUS_QUICK = 0;
1662$SMBUS_BYTE = 1;
1663$SMBUS_BYTE_DATA  = 2;
1664$SMBUS_WORD_DATA  = 3;
1665$SMBUS_PROC_CALL = 4;
1666$SMBUS_BLOCK_DATA = 5;
1667
1668# Select the device to communicate with through its address.
1669# $_[0]: Reference to an opened filehandle
1670# $_[1]: Address to select
1671# Returns: 0 on failure, 1 on success.
1672sub i2c_set_slave_addr
1673{
1674  my ($file,$addr) = @_;
1675  ioctl $file, $IOCTL_I2C_SLAVE, $addr or return 0;
1676  return 1;
1677}
1678
1679# i2c_smbus_access is based upon the corresponding C function (see
1680# <linux/i2c-dev.h>). You should not need to call this directly.
1681# Exact calling conventions are intricate; read i2c-dev.c if you really need
1682# to know.
1683# $_[0]: Reference to an opened filehandle
1684# $_[1]: $SMBUS_READ for reading, $SMBUS_WRITE for writing
1685# $_[2]: Command (usually register number)
1686# $_[3]: Transaction kind ($SMBUS_BYTE, $SMBUS_BYTE_DATA, etc.)
1687# $_[4]: Reference to an array used for input/output of data
1688# Returns: 0 on failure, 1 on success.
1689# Note that we need to get back to Integer boundaries through the 'x2'
1690# in the pack. This is very compiler-dependent; I wish there was some other
1691# way to do this.
1692sub i2c_smbus_access
1693{
1694  my ($file,$read_write,$command,$size,$data) = @_;
1695  my $data_array = pack "C32", @$data;
1696  my $ioctl_data = pack "C2x2Ip", ($read_write,$command,$size,$data_array);
1697  ioctl $file, $IOCTL_I2C_SMBUS, $ioctl_data or return 0;
1698  $_[4] = [ unpack "C32",$data_array ];
1699  return 1;
1700}
1701
1702# $_[0]: Reference to an opened filehandle
1703# $_[1]: Either 0 or 1
1704# Returns: -1 on failure, the 0 on success.
1705sub i2c_smbus_write_quick
1706{
1707  my ($file,$value) = @_;
1708  my $data = [];
1709  i2c_smbus_access $file, $value, 0, $SMBUS_QUICK, $data 
1710         or return -1;
1711  return 0;
1712}
1713
1714# $_[0]: Reference to an opened filehandle
1715# Returns: -1 on failure, the read byte on success.
1716sub i2c_smbus_read_byte
1717{
1718  my ($file) = @_;
1719  my $data = [];
1720  i2c_smbus_access $file, $SMBUS_READ, 0, $SMBUS_BYTE, $data 
1721         or return -1;
1722  return $$data[0];
1723}
1724
1725# $_[0]: Reference to an opened filehandle
1726# $_[1]: Byte to write
1727# Returns: -1 on failure, 0 on success.
1728sub i2c_smbus_write_byte
1729{
1730  my ($file,$command) = @_;
1731  my $data = [$command];
1732  i2c_smbus_access $file, $SMBUS_WRITE, 0, $SMBUS_BYTE, $data 
1733         or return -1;
1734  return 0;
1735}
1736
1737# $_[0]: Reference to an opened filehandle
1738# $_[1]: Command byte (usually register number)
1739# Returns: -1 on failure, the read byte on success.
1740sub i2c_smbus_read_byte_data
1741{
1742  my ($file,$command) = @_;
1743  my $data = [];
1744  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BYTE_DATA, $data 
1745         or return -1;
1746  return $$data[0];
1747}
1748 
1749# $_[0]: Reference to an opened filehandle
1750# $_[1]: Command byte (usually register number)
1751# $_[2]: Byte to write
1752# Returns: -1 on failure, 0 on success.
1753sub i2c_smbus_write_byte_data
1754{
1755  my ($file,$command,$value) = @_;
1756  my $data = [$value];
1757  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BYTE_DATA, $data 
1758         or return -1;
1759  return 0;
1760}
1761
1762# $_[0]: Reference to an opened filehandle
1763# $_[1]: Command byte (usually register number)
1764# Returns: -1 on failure, the read word on success.
1765# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1766# this.
1767sub i2c_smbus_read_word_data
1768{
1769  my ($file,$command) = @_;
1770  my $data = [];
1771  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_WORD_DATA, $data 
1772         or return -1;
1773  return $$data[0] + 256 * $$data[1];
1774}
1775
1776# $_[0]: Reference to an opened filehandle
1777# $_[1]: Command byte (usually register number)
1778# $_[2]: Byte to write
1779# Returns: -1 on failure, 0 on success.
1780# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1781# this.
1782sub i2c_smbus_write_word_data
1783{
1784  my ($file,$command,$value) = @_;
1785  my $data = [$value & 0xff, $value >> 8];
1786  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_WORD_DATA, $data 
1787         or return -1;
1788  return 0;
1789}
1790
1791# $_[0]: Reference to an opened filehandle
1792# $_[1]: Command byte (usually register number)
1793# $_[2]: Word to write
1794# Returns: -1 on failure, read word on success.
1795# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1796# this.
1797sub i2c_smbus_process_call
1798{
1799  my ($file,$command,$value) = @_;
1800  my $data = [$value & 0xff, $value >> 8];
1801  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_PROC_CALL, $data 
1802         or return -1;
1803  return $$data[0] + 256 * $$data[1];
1804}
1805
1806# $_[0]: Reference to an opened filehandle
1807# $_[1]: Command byte (usually register number)
1808# Returns: Undefined on failure, a list of read bytes on success
1809# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1810# this.
1811sub i2c_smbus_read_block_data
1812{
1813  my ($file,$command) = @_;
1814  my $data = [];
1815  i2c_smbus_access $file, $SMBUS_READ, $command, $SMBUS_BLOCK_DATA, $data 
1816         or return;
1817  shift @$data;
1818  return @$data;
1819}
1820
1821# $_[0]: Reference to an opened filehandle
1822# $_[1]: Command byte (usually register number)
1823# @_[2..]: List of values to write
1824# Returns: -1 on failure, 0 on success.
1825# Note: some devices use the wrong endiannes; use swap_bytes to correct for
1826# this.
1827sub i2c_smbus_write_block_data
1828{
1829  my ($file,$command,@data) = @_;
1830  i2c_smbus_access $file, $SMBUS_WRITE, $command, $SMBUS_BLOCK_DATA, \@data 
1831         or return;
1832  return 0;
1833}
1834
1835####################
1836# ADAPTER SCANNING #
1837####################
1838
1839use vars qw(@chips_detected);
1840
1841# We will build a complicated structure @chips_detected here, being:
1842# A list of
1843#  references to hashes
1844#    with field 'driver', being a string with the driver name for this chip;
1845#    with field 'detected'
1846#      being a reference to a list of
1847#        references to hashes of type 'detect_data';
1848#    with field 'misdetected'
1849#      being a reference to a list of
1850#        references to hashes of type 'detect_data'
1851
1852# Type detect_data:
1853# A hash
1854#   with field 'i2c_adap' containing an adapter string as appearing
1855#        in /proc/bus/i2c (if this is an I2C detection)
1856#  with field 'i2c_algo' containing an algorithm string as appearing
1857#       in /proc/bus/i2c (if this is an I2C detection)
1858#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
1859#       adapter (if this is an I2C detection)
1860#  with field 'i2c_driver', containing the driver name for this adapter
1861#       (if this is an I2C detection)
1862#  with field 'i2c_addr', containing the I2C address of the detection;
1863#       (if this is an I2C detection)
1864#  with field 'i2c_sub_addrs', containing a reference to a list of
1865#       other I2C addresses (if this is an I2C detection)
1866#  with field 'i2c_extra' if this is an I2C detection and the address
1867#       is not normally probed by the kernel driver
1868#  with field 'isa_addr' containing the ISA address this chip is on
1869#       (if this is an ISA detection)
1870#  with field 'isa_extra' if this is an ISA detection and the address
1871#       is not normally probed by the kernel driver
1872#  with field 'conf', containing the confidence level of this detection
1873#  with field 'chipname', containing the chip name
1874
1875# This adds a detection to the above structure. We do no alias detection
1876# here; so you should do ISA detections *after* all I2C detections.
1877# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
1878# In all normal cases, it should be all right.
1879# $_[0]: chip driver
1880# $_[1]: reference to data hash
1881# Returns: Nothing
1882sub add_i2c_to_chips_detected
1883{
1884  my ($chipdriver,$datahash) = @_;
1885  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
1886      $main_entry,$detected_entry,$put_in_detected,@hash_addrs,@entry_addrs);
1887
1888  # First determine where the hash has to be added.
1889  for ($i = 0; $i < @chips_detected; $i++) {
1890    last if ($chips_detected[$i]->{driver} eq $chipdriver);
1891  }
1892  if ($i == @chips_detected) {
1893    push @chips_detected, { driver => $chipdriver,
1894                            detected => [],
1895                            misdetected => [] };
1896  }
1897  $new_detected_ref = $chips_detected[$i]->{detected};
1898  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
1899
1900  # Find out whether our new entry should go into the detected or the
1901  # misdetected list. We compare all i2c addresses; if at least one matches,
1902  # but our conf value is lower, we assume this is a misdetect.
1903  @hash_addrs = ($datahash->{i2c_addr});
1904  push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
1905       if exists $datahash->{i2c_sub_addrs};
1906  $put_in_detected = 1;
1907  FIND_LOOP:
1908  foreach $main_entry (@chips_detected) {
1909    foreach $detected_entry (@{$main_entry->{detected}}) {
1910      @entry_addrs = ($detected_entry->{i2c_addr});
1911      push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
1912               if exists $detected_entry->{i2c_sub_addrs};
1913      if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} and
1914          any_list_match \@entry_addrs, \@hash_addrs) {
1915        if ($detected_entry->{conf} >= $datahash->{conf}) {
1916          $put_in_detected = 0;
1917        }
1918        last FIND_LOOP;
1919      }
1920    }
1921  }
1922
1923  if ($put_in_detected) {
1924    # Here, we move all entries from detected to misdetected which
1925    # match at least in one main or sub address. This may not be the
1926    # best idea to do, as it may remove detections without replacing
1927    # them with second-best ones. Too bad.
1928    @hash_addrs = ($datahash->{i2c_addr});
1929    push @hash_addrs, @{$datahash->{i2c_sub_addrs}} 
1930         if exists $datahash->{i2c_sub_addrs};
1931    foreach $main_entry (@chips_detected) {
1932      $detected_ref = $main_entry->{detected};
1933      $misdetected_ref = $main_entry->{misdetected};
1934      for ($i = @$detected_ref-1; $i >=0; $i--) {
1935        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
1936        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
1937             if exists $detected_ref->[$i]->{i2c_sub_addrs};
1938        if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} and
1939            any_list_match \@entry_addrs, \@hash_addrs) {
1940          push @$misdetected_ref,$detected_ref->[$i];
1941          splice @$detected_ref, $i, 1;
1942        }
1943      }
1944    }
1945
1946    # Now add the new entry to detected
1947    push @$new_detected_ref, $datahash;
1948  } else {
1949    # No hard work here
1950    push @$new_misdetected_ref, $datahash;
1951  }
1952}
1953
1954# This adds a detection to the above structure. We also do alias detection
1955# here; so you should do ISA detections *after* all I2C detections.
1956# $_[0]: alias detection function
1957# $_[1]: chip driver
1958# $_[2]: reference to data hash
1959# Returns: 0 if it is not an alias, datahash reference if it is.
1960sub add_isa_to_chips_detected
1961{
1962  my ($alias_detect,$chipdriver,$datahash) = @_;
1963  my ($i,$new_detected_ref,$new_misdetected_ref,$detected_ref,$misdetected_ref,
1964      $main_entry,$isalias);
1965
1966  # First determine where the hash has to be added.
1967  $isalias=0;
1968  for ($i = 0; $i < @chips_detected; $i++) {
1969    last if ($chips_detected[$i]->{driver} eq $chipdriver);
1970  }
1971  if ($i == @chips_detected) {
1972    push @chips_detected, { driver => $chipdriver,
1973                            detected => [],
1974                            misdetected => [] };
1975  }
1976  $new_detected_ref = $chips_detected[$i]->{detected};
1977  $new_misdetected_ref = $chips_detected[$i]->{misdetected};
1978
1979  # Now, we are looking for aliases. An alias can only be the same chiptype.
1980  # If an alias is found in the misdetected list, we add the new information
1981  # and terminate this function. If it is found in the detected list, we
1982  # still have to check whether another chip has claimed this ISA address.
1983  # So we remove the old entry from the detected list and put it in datahash.
1984
1985  # Misdetected alias detection:
1986  for ($i = 0; $i < @$new_misdetected_ref; $i++) {
1987    if (exists $new_misdetected_ref->[$i]->{i2c_addr} and
1988        not exists $new_misdetected_ref->[$i]->{isa_addr} and
1989        defined $alias_detect and
1990        $new_misdetected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
1991      open FILE,"/dev/i2c-$new_misdetected_ref->[$i]->{i2c_devnr}" or
1992        open FILE,"/dev/i2c$new_misdetected_ref->[$i]->{i2c_devnr}" or
1993          open FILE,"/dev/i2c/$new_misdetected_ref->[$i]->{i2c_devnr}" or
1994             print("Can't open ",
1995                   "/dev/i2c[-/]$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
1996             next;
1997      binmode FILE;
1998      i2c_set_slave_addr \*FILE,$new_misdetected_ref->[$i]->{i2c_addr} or
1999           print("Can't set I2C address for ",
2000                 "/dev/i2c[-/]$new_misdetected_ref->[$i]->{i2c_devnr}?!?\n"),
2001           next;
2002      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2003                          $new_misdetected_ref->[$i]->{i2c_addr})) {
2004        $new_misdetected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2005        $new_misdetected_ref->[$i]->{isa_extra} = $datahash->{isa_extra} 
2006               if exists $datahash->{isa_extra};
2007        close FILE;
2008        return $new_misdetected_ref->[$i]; 
2009      }
2010      close FILE;
2011    }
2012  }
2013
2014  # Detected alias detection:
2015  for ($i = 0; $i < @$new_detected_ref; $i++) {
2016    if (exists $new_detected_ref->[$i]->{i2c_addr} and
2017        not exists $new_detected_ref->[$i]->{isa_addr} and
2018        defined $alias_detect and
2019        $new_detected_ref->[$i]->{chipname} eq $datahash->{chipname}) {
2020      open FILE,"/dev/i2c-$new_detected_ref->[$i]->{i2c_devnr}" or
2021        open FILE,"/dev/i2c$new_detected_ref->[$i]->{i2c_devnr}" or
2022          open FILE,"/dev/i2c/$new_detected_ref->[$i]->{i2c_devnr}" or
2023             print("Can't open ",
2024                   "/dev/i2c[-/]$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2025             next;
2026      binmode FILE;
2027      i2c_set_slave_addr \*FILE,$new_detected_ref->[$i]->{i2c_addr} or
2028           print("Can't set I2C address for ",
2029                 "/dev/i2c[-/]$new_detected_ref->[$i]->{i2c_devnr}?!?\n"),
2030           next;
2031      if (&$alias_detect ($datahash->{isa_addr},\*FILE,
2032                          $new_detected_ref->[$i]->{i2c_addr})) {
2033        $new_detected_ref->[$i]->{isa_addr} = $datahash->{isa_addr};
2034        $new_detected_ref->[$i]->{isa_extra} = $datahash->{isa_extra} 
2035               if exists $datahash->{isa_extra};
2036        ($datahash) = splice (@$new_detected_ref, $i, 1);
2037        close FILE;
2038        $isalias=1;
2039        last;
2040      }
2041      close FILE;
2042    }
2043  }
2044
2045
2046  # Find out whether our new entry should go into the detected or the
2047  # misdetected list. We only compare main isa_addr here, of course.
2048  foreach $main_entry (@chips_detected) {
2049    $detected_ref = $main_entry->{detected};
2050    $misdetected_ref = $main_entry->{misdetected};
2051    for ($i = 0; $i < @{$main_entry->{detected}}; $i++) {
2052      if (exists $detected_ref->[$i]->{isa_addr} and
2053          $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
2054        if ($detected_ref->[$i]->{conf} >= $datahash->{conf}) {
2055          push @$new_misdetected_ref, $datahash;
2056        } else {
2057          push @$misdetected_ref,$detected_ref->[$i];
2058          splice @$detected_ref, $i,1;
2059          push @$new_detected_ref, $datahash;
2060        }
2061        if ($isalias) {
2062          return $datahash;
2063        } else {
2064          return 0;
2065        }
2066      }
2067    }
2068  }
2069
2070  # Not found? OK, put it in the detected list
2071  push @$new_detected_ref, $datahash;
2072  if ($isalias) {
2073    return $datahash;
2074  } else {
2075    return 0;
2076  }
2077}
2078
2079# $_[0]: The number of the adapter to scan
2080# $_[1]: The name of the adapter, as appearing in /proc/bus/i2c
2081# $_[2]: The name of the algorithm, as appearing in /proc/bus/i2c
2082# $_[3]: The driver of the adapter
2083# @_[4..]: Addresses not to scan
2084sub scan_adapter
2085{
2086  my ( $adapter_nr,$adapter_name,$algorithm_name,$adapter_driver, 
2087       $not_to_scan) = @_;
2088  my ($chip, $addr, $conf,@chips,$new_hash,$other_addr);
2089
2090  # As we modify it, we need a copy
2091  my @not_to_scan = @$not_to_scan;
2092
2093  open FILE,"/dev/i2c-$adapter_nr" or 
2094    open FILE,"/dev/i2c$adapter_nr" or 
2095      open FILE,"/dev/i2c/$adapter_nr" or 
2096         (print "Can't open /dev/i2c[-/]$adapter_nr\n"), return;
2097  binmode FILE;
2098
2099  # Now scan each address in turn
2100  foreach $addr (0..0x7f) {
2101    # As the not_to_scan list is sorted, we can check it fast
2102    if (@not_to_scan and $not_to_scan[0] == $addr) {
2103      shift @not_to_scan;
2104      next;
2105    }
2106
2107    i2c_set_slave_addr(\*FILE,$addr) or 
2108        printf("Client at address 0x%02x can not be probed - unload all client drivers first!\n",$addr), next;
2109
2110    next unless i2c_smbus_write_quick(\*FILE,$SMBUS_WRITE) >= 0;
2111    printf "Client found at address 0x%02x\n",$addr;
2112    # Prevent 24RF08 corruption
2113    if($addr >= 0x54 and $addr <= 0x57) {
2114        i2c_smbus_write_quick(\*FILE,$SMBUS_WRITE);
2115    }
2116
2117    foreach $chip (@chip_ids) {
2118      if (exists $$chip{i2c_addrs} and contains $addr, @{$$chip{i2c_addrs}}) {
2119        print "Probing for `$$chip{name}'... ";
2120        if (($conf,@chips) = &{$$chip{i2c_detect}} (\*FILE ,$addr)) {
2121          print "Success!\n",
2122                "    (confidence $conf, driver `$$chip{driver}')";
2123          if (@chips) {
2124            print ", other addresses:";
2125            @chips = sort @chips;
2126            foreach $other_addr (sort @chips) {
2127              printf(" 0x%02x",$other_addr);
2128            }
2129          }
2130          printf "\n";
2131          $new_hash = { conf => $conf,
2132                        i2c_addr => $addr,
2133                        chipname =>  $$chip{name},
2134                        i2c_adap => $adapter_name,
2135                        i2c_algo => $algorithm_name,
2136                        i2c_driver => $adapter_driver,
2137                        i2c_devnr => $adapter_nr,
2138                      };
2139          if (@chips) {
2140            my @chips_copy = @chips;
2141            $new_hash->{i2c_sub_addrs} = \@chips_copy;
2142          }
2143          $new_hash->{i2c_extra} = 0 
2144                 if exists $chip->{i2c_driver_addrs} and
2145                    not contains( $addr , @{$chip->{i2c_driver_addrs}});
2146          add_i2c_to_chips_detected $$chip{driver}, $new_hash;
2147        } else {
2148          print "Failed!\n";
2149        }
2150      }
2151    }
2152  }
2153}
2154
2155sub scan_isa_bus
2156{
2157  my ($chip,$addr,$conf);
2158  foreach $chip (@chip_ids) {
2159    next if not exists $$chip{isa_addrs} or not exists $$chip{isa_detect};
2160    print "Probing for `$$chip{name}'\n";
2161    foreach $addr (@{$$chip{isa_addrs}}) {
2162      if ($addr) {
2163        printf "  Trying address 0x%04x... ", $addr;
2164      } else {
2165        print "  Trying general detect... ";
2166      }
2167      $conf = &{$$chip{isa_detect}} ($addr);
2168      print("Failed!\n"), next if not defined $conf;
2169      print "Success!\n";
2170      printf "    (confidence %d, driver `%s')\n", $conf, $$chip{driver};
2171      my $new_hash = { conf => $conf,
2172                       isa_addr => $addr,
2173                       chipname =>  $$chip{name}
2174                     };
2175      $new_hash->{isa_extra} = 0 
2176             if exists $chip->{isa_driver_addrs} and
2177                not contains ($addr, @{$chip->{isa_driver_addrs}});
2178      $new_hash = add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver},
2179                                            $new_hash;
2180      if ($new_hash) {
2181        printf "    Alias of the chip on I2C bus `%s', address 0x%04x\n",
2182                        $new_hash->{i2c_adap},$new_hash->{i2c_addr};
2183      }
2184    }
2185  }
2186}
2187
2188sub scan_superio
2189{
2190  my ($chip,$val,$addr,$conf);
2191  foreach $chip (@superio_ids) {
2192    print "Probing for `$$chip{name}'\n";
2193# write the password
2194    foreach $val (@{$$chip{enter}}) {
2195      outb($$chip{addrreg}, $val);
2196    }
2197# check the device ID
2198    outb($$chip{addrreg}, $$chip{devidreg});
2199    $val = inb($$chip{datareg});
2200    if($val == $$chip{devid}) {
2201      print "  Success...";
2202# switch to the sensor logical device
2203      outb($$chip{addrreg}, $$chip{logdevreg});
2204      outb($$chip{datareg}, $$chip{logdev});
2205# check the activation register
2206      if(exists $$chip{actreg}) {
2207        outb($$chip{addrreg}, $$chip{actreg});
2208        $val = inb($$chip{datareg});
2209        if(!($val & $$chip{actmask})) {
2210          print " but not activated, module may not find\n";
2211          outb($$chip{exitreg}, $$chip{exit});
2212          next;
2213        }
2214      }
2215# Get the IO base register
2216      outb($$chip{addrreg}, $$chip{basereg});
2217      $addr = inb($$chip{datareg});
2218      outb($$chip{addrreg}, $$chip{basereg} + 1);
2219      $addr = ($addr << 8) | inb($$chip{datareg});
2220      if($addr == 0) {
2221        print " but not activated, module may not find\n";
2222        outb($$chip{addrreg}, $$chip{exit});
2223        next;
2224      }         
2225      printf " found at address 0x%04x\n", $addr;
2226      my $new_hash = { conf => 8,
2227                       isa_addr => $addr,
2228                       chipname =>  $$chip{name}
2229                     };
2230      add_isa_to_chips_detected $$chip{alias_detect},$$chip{driver},
2231                                            $new_hash;
2232    } else {
2233      if($val == 0xff) {       
2234        print "  Failed!\n";
2235      } else {
2236        printf "  Failed! (0x%02x)\n", $val;
2237      }
2238    }
2239    outb($$chip{exitreg}, $$chip{exit});
2240  }
2241}
2242
2243
2244##################
2245# CHIP DETECTION #
2246##################
2247
2248# Each function returns a confidence value. The higher this value, the more
2249# sure we are about this chip. A Winbond W83781D, for example, will be
2250# detected as a LM78 too; but as the Winbond detection has a higher confidence
2251# factor, you should identify it as a Winbond.
2252
2253# Each function returns a list. The first element is the confidence value;
2254# Each element after it is an SMBus address. In this way, we can detect
2255# chips with several SMBus addresses. The SMBus address for which the
2256# function was called is never returned.
2257
2258# If there are devices which get confused if they are only read from, then
2259# this program will surely confuse them. But we guarantee never to write to
2260# any of these devices.
2261
2262
2263# $_[0]: A reference to the file descriptor to access this chip.
2264#        We may assume an i2c_set_slave_addr was already done.
2265# $_[1]: Address
2266# Returns: undef if not detected, (7) if detected.
2267# Registers used: 0x58
2268sub mtp008_detect
2269{
2270  my ($file,$addr) = @_;
2271  return if (i2c_smbus_read_byte_data($file,0x58)) != 0xac;
2272  return (8);
2273}
2274 
2275# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
2276# $_[1]: A reference to the file descriptor to access this chip.
2277#        We may assume an i2c_set_slave_addr was already done.
2278# $_[2]: Address
2279# Returns: undef if not detected, (7) if detected.
2280# Registers used:
2281#   0x40: Configuration
2282#   0x48: Full I2C Address
2283#   0x49: Device ID
2284# Note that this function is always called through a closure, so the
2285# arguments are shifted by one place.
2286sub lm78_detect
2287{
2288  my $reg;
2289  my ($chip,$file,$addr) = @_;
2290  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
2291  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
2292  $reg = i2c_smbus_read_byte_data($file,0x49);
2293  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
2294                    ($chip == 1 and $reg == 0x40) or
2295                    ($chip == 2 and ($reg & 0xfe) == 0xc0);
2296  return (7);
2297}
2298
2299# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
2300# $_[1]: Address
2301# Returns: undef if not detected, 7 if detected.
2302# Note: Only address 0x290 is scanned at this moment.
2303sub lm78_isa_detect
2304{
2305  my ($chip,$addr) = @_ ;
2306  my $val = inb ($addr + 1);
2307  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
2308            inb ($addr + 7) != $val;
2309
2310  $val = inb($addr + 5) & 0x7f;
2311  outb($addr + 5, ~$val & 0xff);
2312  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
2313    outb($addr+5,$val);
2314    return;
2315  }
2316  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
2317  return unless (&$readproc(0x40) & 0x80) == 0x00;
2318  my $reg = &$readproc(0x49);
2319  return unless ($chip == 0 and ($reg == 0x00 or $reg == 0x20)) or
2320                ($chip == 1 and $reg == 0x40) or
2321                ($chip == 2 and ($reg & 0xfe) == 0xc0);
2322  return 7;
2323}
2324
2325
2326# $_[0]: Chip to detect (0 = LM78, 1 = LM78-J, 2 = LM79)
2327# $_[1]: ISA address
2328# $_[2]: I2C file handle
2329# $_[3]: I2C address
2330sub lm78_alias_detect
2331{
2332  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
2333  my $i;
2334  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
2335  return 0 unless &$readproc(0x48) == $i2c_addr;
2336  for ($i = 0x2b; $i <= 0x3d; $i ++) {
2337    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
2338  }
2339  return 1;
2340}
2341
2342# $_[0]: A reference to the file descriptor to access this chip.
2343#        We may assume an i2c_set_slave_addr was already done.
2344# $_[1]: Address
2345# Returns: undef if not detected, 2 to 6 if detected;
2346#   6 means that the LM75 was found in its default power up state;
2347#   5 means that the LM75 was found in another known default state;
2348#   4 means that the LM75 was found in a probable state (temperatures
2349#       make sense);
2350#   3 means that the configuration register passes the test;
2351#   2 means that the configuration register test failed, so the chipset
2352#       is unlikely to be a LM75.
2353# Registers used:
2354#   0x01: Temperature
2355#   0x01: Configuration
2356#   0x02: Hysteresis
2357#   0x03: Overtemperature Shutdown
2358# The first detection step is only based on the fact that the LM75 has only
2359# four registers. Any other chip in the valid address range with only four
2360# registers will be detected too.
2361# Note that register $00 may change, so we can't use the modulo trick on it.
2362sub lm75_detect
2363{
2364  my $i;
2365  my ($file,$addr) = @_;
2366  my $cur = i2c_smbus_read_word_data($file,0x00);
2367  my $conf = i2c_smbus_read_byte_data($file,0x01);
2368  my $hyst = i2c_smbus_read_word_data($file,0x02);
2369  my $os = i2c_smbus_read_word_data($file,0x03);
2370  for ($i = 0x00; $i <= 0x1f; $i += 1) {
2371    return if i2c_smbus_read_byte_data($file,($i * 0x08) + 0x01) != $conf;
2372    return if i2c_smbus_read_word_data($file,($i * 0x08) + 0x02) != $hyst;
2373    return if i2c_smbus_read_word_data($file,($i * 0x08) + 0x03) != $os;
2374  }
2375  # Default power up state (from specs)
2376  return 6
2377    if $conf == 0 and ($hyst&0x80ff) == 0x004b and ($os&0x80ff) == 0x0050;
2378  # Default state as seen on the Asus TX97-E
2379  return 5
2380    if $conf == 0 and ($hyst&0x80ff) == 0x002d and ($os&0x80ff) == 0x0034;
2381  # Most probable value ranges
2382  return 4
2383    if ($conf&0xe0) == 0 and (($cur&0x00ff) <= 125 || ($cur&0x00ff) >= 201)
2384       and ($hyst&0x00ff) <= 125 and ($os&0x00ff) <= 125 and $hyst<$os;
2385  # Unused bits in conf register
2386  return 3
2387    if ($conf&0xe0) == 0;
2388  return 2;
2389}
2390 
2391# $_[0]: A reference to the file descriptor to access this chip.
2392#        We may assume an i2c_set_slave_addr was already done.
2393# $_[1]: Address
2394# Returns: undef if not detected, (3) if detected,
2395#   (6) or (9) if even more bits match.
2396# Registers used:
2397#   0xAC: Configuration
2398# Detection is weak. We check if Bit 3 is set and Bit 2 is clear.
2399# The DS1621 will aways have a config like 0x????10??. A even better
2400# match would be 0x0??01000.
2401sub ds1621_detect
2402{
2403  my $i;
2404  my ($file,$addr) = @_;
2405  my $conf = i2c_smbus_read_byte_data($file,0xAC);
2406  return (9) if ($conf & 0x9F) == 0x98;
2407  return (6) if ($conf & 0x0F) == 0x08;
2408  return (3) if ($conf & 0x0C) == 0x08;
2409  return ;
2410}
2411
2412# $_[0]: A reference to the file descriptor to access this chip.
2413#        We may assume an i2c_set_slave_addr was already done.
2414# $_[1]: Address
2415# Returns: undef if not detected, (3) if detected.
2416# Registers used:
2417#   0x02: Interrupt state register
2418# How to detect this beast?
2419sub lm80_detect
2420{
2421  my $i;
2422  my ($file,$addr) = @_;
2423  return if (i2c_smbus_read_byte_data($file,0x02) & 0xc0) != 0;
2424  for ($i = 0x2a; $i <= 0x3d; $i++) {
2425    my $reg = i2c_smbus_read_byte_data($file,$i);
2426    return if i2c_smbus_read_byte_data($file,$i+0x40) != $reg;
2427    return if i2c_smbus_read_byte_data($file,$i+0x80) != $reg;
2428    return if i2c_smbus_read_byte_data($file,$i+0xc0) != $reg;
2429  }
2430  return (3);
2431}
2432
2433# $_[0]: Chip to detect
2434#   (0 = LM83, 1 = LM82)
2435# $_[1]: A reference to the file descriptor to access this chip.
2436#        We may assume an i2c_set_slave_addr was already done.
2437# $_[2]: Address
2438# Returns: undef if not detected, 5 to 8 if detected.
2439# Registers used:
2440#   0x03: Configuration
2441#   0x04: Company ID of LM84
2442#   0xfe: Manufacturer ID
2443#   0xff: Chip ID / die revision
2444# We can use the LM84 Company ID register because the LM83 and the LM82 are
2445# compatible with the LM84.
2446# We give a lower confidence to the LM83 because it has no known Die Revision
2447# so far.
2448sub lm83_detect
2449{
2450  my ($chip, $file) = @_;
2451  return if $chip == 0 and i2c_smbus_read_byte_data($file,0xfe) != 0x01;
2452  return if $chip == 1 and i2c_smbus_read_byte_data($file,0xfe) != 0x01
2453                        || i2c_smbus_read_byte_data($file,0xff) != 0x01;
2454  return if (i2c_smbus_read_byte_data($file,0x03) & 0x41) != 0;
2455  return (7 + ($chip != 0))
2456        if i2c_smbus_read_byte_data($file,0x04) == 0x00;
2457  return (5 + ($chip != 0));
2458}
2459
2460# $_[0]: Chip to detect
2461#   (0 = LM90, 1=LM89, 2=LM86)
2462# $_[1]: A reference to the file descriptor to access this chip.
2463#        We may assume an i2c_set_slave_addr was already done.
2464# $_[2]: Address
2465# Returns: undef if not detected, 7 or 8 if detected.
2466# Registers used:
2467#   0x03: Configuration
2468#   0xfe: Manufacturer ID
2469#   0xff: Chip ID / die revision
2470sub lm90_detect
2471{
2472  my $reg;
2473  my ($chip, $file,$addr) = @_;
2474  return if i2c_smbus_read_byte_data($file,0xfe) != 0x01;
2475  return if (i2c_smbus_read_byte_data($file,0x03) & 0x2a) != 0;
2476  if ($chip == 0) {
2477    return 8
2478          if ($reg = i2c_smbus_read_byte_data($file,0xff)) == 0x21;
2479    return 7
2480      if $reg > 0x21 and $reg < 0x30;
2481  }
2482  if ($chip == 1) {
2483    return 8
2484          if ($reg = i2c_smbus_read_byte_data($file,0xff)) == 0x31;
2485    return 7
2486      if $reg > 0x31 and $reg < 0x40;
2487  }
2488  if ($chip == 2) {
2489    return 8
2490          if ($reg = i2c_smbus_read_byte_data($file,0xff)) == 0x11;
2491    return 7
2492      if $reg > 0x11 and $reg < 0x20;
2493  }
2494  return;
2495}
2496
2497# $_[0]: Vendor to check for
2498#   (0x01 = National Semi, 0x41 = Analog Dev)
2499# $_[1]: A reference to the file descriptor to access this chip.
2500# #_[2]: Base address.
2501# Returns: undef if not detected, (7) if detected.
2502# Registers used: 0x3e == Vendor register.
2503#                 0x3f == Version/Stepping register.
2504# Constants used: 0x01 == National Semiconductor Vendor Id.
2505#                 0x41 == Analog Devices Vendor Id.
2506#                 0x5c == SMSC Vendor Id.
2507#                 0x60 == Version number. The lower 4 stepping
2508#                         bits are masked and ignored.
2509sub lm85_detect
2510{
2511  my ($vendor,$file,$addr) = @_;
2512  return if (i2c_smbus_read_byte_data($file,0x3e)) != $vendor ;
2513  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) != 0x60;
2514  return (7);
2515}
2516
2517# $_[0]: A reference to the file descriptor to access this chip.
2518#        We may assume an i2c_set_slave_addr was already done.
2519# $_[1]: Address
2520# Returns: undef if not detected, (7) if detected.
2521# Registers used: 0x3E, 0x3F
2522#        Assume lower 2 bits of reg 0x3F are for revisions.
2523sub lm87_detect
2524{
2525  my ($file,$addr) = @_;
2526  return if (i2c_smbus_read_byte_data($file,0x3e)) != 0x02;
2527  return if (i2c_smbus_read_byte_data($file,0x3f) & 0xfc) != 0x04;
2528  return (7);
2529}
2530 
2531# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S,
2532#                        3 = W83627HF, 4 = AS99127F (rev.1),
2533#                        5 = AS99127F (rev.2), 6 = ASB100, 7 = W83791D
2534# $_[1]: A reference to the file descriptor to access this chip.
2535#        We may assume an i2c_set_slave_addr was already done.
2536# $_[2]: Address
2537# Returns: undef if not detected, (8,addr1,addr2) if detected, but only
2538#          if the LM75 chip emulation is enabled.
2539# Registers used:
2540#   0x48: Full I2C Address
2541#   0x4a: I2C addresses of emulated LM75 chips
2542#   0x4e: Vendor ID byte selection, and bank selection
2543#   0x4f: Vendor ID
2544#   0x58: Device ID (only when in bank 0); ignore LSB.
2545# Note: Fails if the W8378xD is not in bank 0!
2546# Note: Detection overrules a previous LM78 detection
2547# Note: Asus chips do not have their I2C address at register 0x48?
2548#       AS99127F rev.1 has 0x00, confirmation wanted for rev.2 and
2549#       ASB100.
2550sub w83781d_detect
2551{
2552  my ($reg1,$reg2,@res);
2553  my ($chip,$file,$addr) = @_;
2554
2555  return unless (i2c_smbus_read_byte_data($file,0x48) == $addr)
2556    or ($chip >= 4 && $chip <= 6);
2557
2558  $reg1 = i2c_smbus_read_byte_data($file,0x4e);
2559  $reg2 = i2c_smbus_read_byte_data($file,0x4f);
2560  if ($chip == 4) { # Asus AS99127F (rev.1)
2561    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or 
2562                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x12);
2563  } elsif ($chip == 6) { # Asus ASB100
2564    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0x94) or 
2565                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x06);
2566  } else { # Winbond and Asus AS99127F (rev.2)
2567    return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
2568                  (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
2569  }
2570
2571  return unless ($reg1 & 0x07) == 0x00;
2572
2573  $reg1 = i2c_smbus_read_byte_data($file,0x58);
2574  return if $chip == 0 and ($reg1 != 0x10 && $reg1 != 0x11);
2575  return if $chip == 1 and  $reg1 != 0x30;
2576  return if $chip == 2 and  $reg1 != 0x40;
2577  return if $chip == 3 and  $reg1 != 0x20;
2578  return if $chip == 4 and  $reg1 != 0x31;
2579  return if $chip == 5 and  $reg1 != 0x31;
2580  return if $chip == 6 and  $reg1 != 0x31;
2581  return if $chip == 7 and  $reg1 != 0x70;
2582  $reg1 = i2c_smbus_read_byte_data($file,0x4a);
2583  @res = (8);
2584  push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08 ;
2585  push @res, (($reg1 & 0x70) >> 4) + 0x48 unless ($reg1 & 0x80 or $chip == 2);
2586  return @res;
2587}
2588
2589# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 2 = W83783S, 3 = W83627HF)
2590# $_[1]: ISA address
2591# $_[2]: I2C file handle
2592# $_[3]: I2C address
2593sub w83781d_alias_detect
2594{
2595  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
2596  my $i;
2597  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
2598  return 0 unless &$readproc(0x48) == $i2c_addr;
2599  for ($i = 0x2b; $i <= 0x3d; $i ++) {
2600    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
2601  }
2602  return 1;
2603}
2604
2605# $_[0]: Chip to detect (0 = W83781D, 1 = W83782D, 3 = W83627HF, 5 = W83697HF)
2606#        (W83783S and AS99127F not on ISA bus)
2607# $_[1]: Address
2608# Returns: undef if not detected, (8) if detected.
2609sub w83781d_isa_detect
2610{
2611  my ($chip,$addr) = @_ ;
2612  my ($reg1,$reg2);
2613  my $val = inb ($addr + 1);
2614  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or
2615            inb ($addr + 7) != $val;
2616
2617  $val = inb($addr + 5) & 0x7f;
2618  outb($addr+5, ~$val & 0xff);
2619  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
2620    outb($addr+5,$val);
2621    return;
2622  }
2623
2624  my $read_proc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
2625  $reg1 = &$read_proc(0x4e);
2626  $reg2 = &$read_proc(0x4f);
2627  return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or 
2628                (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
2629  return unless ($reg1 & 0x07) == 0x00;
2630  $reg1 = &$read_proc(0x58) & 0xfe;
2631  return if $chip == 0 and  $reg1 != 0x10;
2632  return if $chip == 1 and  $reg1 != 0x30;
2633  return if $chip == 3 and  $reg1 != 0x20;
2634  return if $chip == 5 and  $reg1 != 0x60;
2635  return 8;
2636}
2637
2638# $_[0]: Chip to detect (0 = Revision 0x00, 1 = Revision 0x80)
2639# $_[1]: A reference to the file descriptor to access this chip.
2640#        We may assume an i2c_set_slave_addr was already done.
2641# $_[2]: Address
2642# Returns: undef if not detected, (6) if detected.
2643# Registers used:
2644#   0x00: Device ID
2645#   0x01: Revision ID
2646#   0x03: Configuration
2647# Mediocre detection
2648sub gl518sm_detect
2649{
2650  my $reg;
2651  my ($chip,$file,$addr) = @_;
2652  return unless i2c_smbus_read_byte_data($file,0x00) == 0x80;
2653  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
2654  $reg = i2c_smbus_read_byte_data($file,0x01);
2655  return unless ($chip == 0 and $reg == 0x00) or
2656                ($chip == 1 and $reg == 0x80);
2657  return (6);
2658}
2659
2660# $_[0]: A reference to the file descriptor to access this chip.
2661#        We may assume an i2c_set_slave_addr was already done.
2662# $_[1]: Address
2663# Returns: undef if not detected, (5) if detected.
2664# Registers used:
2665#   0x00: Device ID
2666#   0x01: Revision ID
2667#   0x03: Configuration
2668# Mediocre detection
2669sub gl520sm_detect
2670{
2671  my ($file,$addr) = @_;
2672  return unless i2c_smbus_read_byte_data($file,0x00) == 0x20;
2673  return unless (i2c_smbus_read_byte_data($file,0x03) & 0x80) == 0x00;
2674  # The line below must be better checked before I dare to use it.
2675  # return unless i2c_smbus_read_byte_data($file,0x01) == 0x00;
2676  return (5);
2677}
2678
2679# $_[0]: A reference to the file descriptor to access this chip.
2680#        We may assume an i2c_set_slave_addr was already done.
2681# $_[1]: Address
2682# Returns: undef if not detected, (5) if detected.
2683# Registers used:
2684#   0x00: Device ID
2685# Mediocre detection
2686sub gl525sm_detect
2687{
2688  my ($file,$addr) = @_;
2689  return unless i2c_smbus_read_byte_data($file,0x00) == 0x25;
2690  return (5);
2691}
2692
2693# $_[0]: Chip to detect (0 = ADM9240, 1 = DS1780, 2 = LM81)
2694# $_[1]: A reference to the file descriptor to access this chip.
2695#        We may assume an i2c_set_slave_addr was already done.
2696# $_[2]: Address
2697# Returns: undef if not detected, (7) if detected.
2698# Registers used:
2699#   0x3e: Company ID
2700#   0x40: Configuration
2701#   0x48: Full I2C Address
2702# Note: Detection overrules a previous LM78 detection
2703sub adm9240_detect
2704{
2705  my $reg;
2706  my ($chip, $file,$addr) = @_;
2707  $reg = i2c_smbus_read_byte_data($file,0x3e);
2708  return unless ($chip == 0 and $reg == 0x23) or
2709                ($chip == 1 and $reg == 0xda) or
2710                ($chip == 2 and $reg == 0x01);
2711  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
2712  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
2713 
2714  return (7);
2715}
2716
2717# $_[0]: Chip to detect (0 = ADM1022, 1 = THMC50)
2718# $_[1]: A reference to the file descriptor to access this chip.
2719#        We may assume an i2c_set_slave_addr was already done.
2720# $_[2]: Address
2721# Returns: undef if not detected, (8) if detected.
2722# Registers used:
2723#   0x3e: Company ID
2724#   0x3f: Revision
2725#   0x40: Configuration
2726# Note: Detection overrules a previous LM78 or ADM9240 detection
2727sub adm1022_detect
2728{
2729  my $reg;
2730  my ($chip, $file,$addr) = @_;
2731  $reg = i2c_smbus_read_byte_data($file,0x3e);
2732  return unless ($chip == 0 and $reg == 0x41) or
2733                ($chip == 1 and $reg == 0x49);
2734  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
2735  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xc0) == 0xc0;
2736  return (8);
2737}
2738
2739# $_[0]: Chip to detect (0 = ADM1025, 1 = NE1619)
2740# $_[1]: A reference to the file descriptor to access this chip.
2741#        We may assume an i2c_set_slave_addr was already done.
2742# $_[2]: Address
2743# Returns: undef if not detected, (8) if detected.
2744# Registers used:
2745#   0x3e: Company ID
2746#   0x3f: Revision
2747#   0x40: Configuration
2748# Note: Detection overrules a previous LM78 or ADM9240 detection
2749sub adm1025_detect
2750{
2751  my $reg;
2752  my ($chip, $file,$addr) = @_;
2753
2754  $reg = i2c_smbus_read_byte_data($file,0x3e);
2755  return if ($chip == 0) and ($reg != 0x41);
2756  return if ($chip == 1) and ($reg != 0xA1);
2757
2758  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
2759  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x20;
2760
2761  return (8);
2762}
2763
2764# $_[0]: Chip to detect (0 = ADM1026)
2765# $_[1]: A reference to the file descriptor to access this chip.
2766#        We may assume an i2c_set_slave_addr was already done.
2767# $_[2]: Address
2768# Returns: undef if not detected, (8) if detected.
2769# Registers used:
2770#   0x16: Company ID
2771#   0x17: Revision
2772sub adm1026_detect
2773{
2774  my $reg;
2775  my ($chip, $file,$addr) = @_;
2776  $reg = i2c_smbus_read_byte_data($file,0x16);
2777  return unless ($reg == 0x41);
2778  return unless (i2c_smbus_read_byte_data($file,0x17) & 0xf0) == 0x40;
2779  return (8);
2780}
2781
2782# $_[0]: Chip to detect (0 = ADM1024)
2783# $_[1]: A reference to the file descriptor to access this chip.
2784#        We may assume an i2c_set_slave_addr was already done.
2785# $_[2]: Address
2786# Returns: undef if not detected, (8) if detected.
2787# Registers used:
2788#   0x3e: Company ID
2789#   0x3f: Revision
2790#   0x40: Configuration
2791sub adm1024_detect
2792{
2793  my $reg;
2794  my ($chip, $file,$addr) = @_;
2795  $reg = i2c_smbus_read_byte_data($file,0x3e);
2796  return unless ($reg == 0x41);
2797  return unless (i2c_smbus_read_byte_data($file,0x40) & 0x80) == 0x00;
2798  return unless (i2c_smbus_read_byte_data($file,0x3f) & 0xf0) == 0x10;
2799  return (8);
2800}
2801
2802# $_[0]: Chip to detect
2803#   (0 = ADM1021, 1 = ADM1021A/ADM1023, 2 = MAX1617, 3 = MAX1617A, 4 = THMC10,
2804#    5 = LM84, 6 = GL523, 7 = MC1066)
2805# $_[1]: A reference to the file descriptor to access this chip.
2806#        We may assume an i2c_set_slave_addr was already done.
2807# $_[2]: Address
2808# Returns: undef if not detected, 3 if simply detected, 6 if detected and
2809#          manufacturer ID matches, 7 if detected and manufacturer ID and
2810#          revision match
2811# Registers used:
2812#   0x04: Company ID (LM84 only)
2813#   0xfe: Company ID (all but LM84 and MAX1617)
2814#   0xff: Revision (ADM1021, ADM1021A/ADM1023 and MAX1617A)
2815#   0x02: Status
2816# Note: Especially the MAX1617 has very bad detection; we give it a low
2817# confidence value.
2818sub adm1021_detect
2819{
2820  my ($chip, $file,$addr) = @_;
2821  return if $chip == 0 and i2c_smbus_read_byte_data($file,0xfe) != 0x41 ||
2822                          (i2c_smbus_read_byte_data($file,0xff) & 0xf0) != 0x00;
2823  return if $chip == 1 and i2c_smbus_read_byte_data($file,0xfe) != 0x41 ||
2824                          (i2c_smbus_read_byte_data($file,0xff) & 0xf0) != 0x30;
2825  return if $chip == 4 and i2c_smbus_read_byte_data($file,0xfe) != 0x49;
2826  return if $chip == 5 and i2c_smbus_read_byte_data($file,0x04) != 0x00;
2827  return if $chip == 6 and i2c_smbus_read_byte_data($file,0xfe) != 0x23;
2828  return if $chip == 3 and i2c_smbus_read_byte_data($file,0xfe) != 0x4d ||
2829                           i2c_smbus_read_byte_data($file,0xff) != 0x01;
2830  return if $chip == 7 and i2c_smbus_read_byte_data($file,0xfe) != 0x54;
2831  # The remaining things are flaky at best. Perhaps something can be done
2832  # with the fact that some registers are unreadable?
2833  return if (i2c_smbus_read_byte_data($file,0x02) & 0x03) != 0;
2834  return 3 if $chip == 2;
2835  return 7 if $chip <= 3;
2836  return 6;
2837}
2838
2839# $_[0]: Address
2840# Returns: undef if not detected, (9) if detected.
2841# Note: It is already 99% certain this chip exists if we find the PCI
2842# entry. The exact address is encoded in PCI space.
2843sub sis5595_isa_detect
2844{
2845  my ($addr) = @_;
2846  my ($adapter,$try,$local_try);
2847  my $found = 0;
2848  foreach $local_try (@pci_adapters) {
2849    if ($local_try->{procid} eq "Silicon Integrated Systems SIS5595") {
2850      $try = $local_try;
2851      $found = 1;
2852      last;
2853    }
2854  }
2855  return if not $found;
2856
2857  $found = 0;
2858  foreach $adapter (@pci_list) {
2859    if ((defined($adapter->{vendid}) and 
2860         $try->{vendid} == $adapter->{vendid} and
2861         $try->{devid} == $adapter->{devid} and
2862         $try->{func} == $adapter->{func}) or
2863        (! defined($adapter->{vendid}) and
2864         $adapter->{desc} =~ /$try->{procid}/ and
2865         $try->{func} == $adapter->{func})) {
2866      $found = 1;
2867      last;
2868    }
2869  }
2870  return if not $found;
2871
2872  return 9;
2873}
2874
2875# $_[0]: Address
2876# Returns: undef if not detected, (9) if detected.
2877# Note: It is already 99% certain this chip exists if we find the PCI
2878# entry. The exact address is encoded in PCI space.
2879sub via686a_isa_detect
2880{
2881  my ($addr) = @_;
2882  my ($adapter,$try,$local_try);
2883  my $found = 0;
2884  foreach $local_try (@pci_adapters) {
2885    if ($local_try->{procid} eq "VIA Technologies VT82C686 Apollo ACPI") {
2886      $try = $local_try;
2887      $found = 1;
2888      last;
2889    }
2890  }
2891  return if not $found;
2892
2893  $found = 0;
2894  foreach $adapter (@pci_list) {
2895    if ((defined($adapter->{vendid}) and 
2896         $try->{vendid} == $adapter->{vendid} and
2897         $try->{devid} == $adapter->{devid} and
2898         $try->{func} == $adapter->{func}) or
2899        (! defined($adapter->{vendid}) and
2900         $adapter->{desc} =~ /$try->{procid}/ and
2901         $try->{func} == $adapter->{func})) {
2902      $found = 1;
2903      last;
2904    }
2905  }
2906  return if not $found;
2907
2908  return 9;
2909}
2910
2911# $_[0]: Address
2912# Returns: undef if not detected, (9) if detected.
2913# Note: It is already 99% certain this chip exists if we find the PCI
2914# entry. The exact address is encoded in PCI space.
2915sub via8231_isa_detect
2916{
2917  my ($addr) = @_;
2918  my ($adapter,$try,$local_try);
2919  my $found = 0;
2920  foreach $local_try (@pci_adapters) {
2921    if ($local_try->{procid} eq "VIA Technologies VT8231 South Bridge") {
2922      $try = $local_try;
2923      $found = 1;
2924      last;
2925    }
2926  }
2927  return if not $found;
2928
2929  $found = 0;
2930  foreach $adapter (@pci_list) {
2931    if ((defined($adapter->{vendid}) and 
2932         $try->{vendid} == $adapter->{vendid} and
2933         $try->{devid} == $adapter->{devid} and
2934         $try->{func} == $adapter->{func}) or
2935        (! defined($adapter->{vendid}) and
2936         $adapter->{desc} =~ /$try->{procid}/ and
2937         $try->{func} == $adapter->{func})) {
2938      $found = 1;
2939      last;
2940    }
2941  }
2942  return if not $found;
2943
2944  return 9;
2945}
2946
2947# $_[0]: Chip to detect (0 = ..., 1 = ...)
2948# $_[1]: A reference to the file descriptor to access this chip.
2949#        We may assume an i2c_set_slave_addr was already done.
2950# $_[2]: Address
2951# Returns: undef if not detected, 8 if detected (tops LM78).
2952# Registers used:
2953#   0x00: Configuration
2954#   0x48: Full I2C Address
2955#   0x58: Mfr ID
2956# Note that this function is always called through a closure, so the
2957# arguments are shifted by one place.
2958sub ite_detect
2959{
2960  my $reg;
2961  my ($chip,$file,$addr) = @_;
2962  return unless i2c_smbus_read_byte_data($file,0x48) == $addr;
2963  return unless (i2c_smbus_read_byte_data($file,0x00) & 0x80) == 0x00;
2964  return unless i2c_smbus_read_byte_data($file,0x58) == 0x90;
2965  return (8);
2966}
2967
2968# $_[0]: Chip to detect (0 = ..., 1 = ...)
2969# $_[1]: Address
2970# Returns: undef if not detected, 8 if detected (tops LM78).
2971# Note: Only address 0x290 is scanned at this moment.
2972sub ite_isa_detect
2973{
2974  my ($chip,$addr) = @_ ;
2975  my $val = inb ($addr + 1);
2976  return if inb ($addr + 2) != $val or inb ($addr + 3) != $val or 
2977            inb ($addr + 7) != $val;
2978
2979  $val = inb($addr + 5) & 0x7f;
2980  outb($addr+5, ~$val & 0xff);
2981  if ((inb ($addr+5) & 0x7f) != (~ $val & 0x7f)) {
2982    outb($addr+5,$val);
2983    return;
2984  }
2985  my $readproc = sub { isa_read_byte $addr + 5, $addr + 6, @_ };
2986  return unless (&$readproc(0x00) & 0x80) == 0x00;
2987  my $reg = &$readproc(0x58);
2988  return unless ($reg == 0x90);
2989  return 8;
2990}
2991
2992
2993# $_[0]: Chip to detect (0 = ..., 1 = ...)
2994# $_[1]: ISA address
2995# $_[2]: I2C file handle
2996# $_[3]: I2C address
2997sub ite_alias_detect
2998{
2999  my ($chip,$isa_addr,$file,$i2c_addr) = @_;
3000  my $i;
3001  my $readproc = sub { isa_read_byte $isa_addr + 5, $isa_addr + 6, @_ };
3002  return 0 unless &$readproc(0x48) == $i2c_addr;
3003  for ($i = 0x2b; $i <= 0x3d; $i ++) {
3004    return 0 unless &$readproc($i) == i2c_smbus_read_byte_data($file,$i);
3005  }
3006  return 1;
3007}
3008
3009# $_[0]: A reference to the file descriptor to access this chip.
3010#        We may assume an i2c_set_slave_addr was already done.
3011# $_[1]: Address
3012# Returns: 8 for a memory eeprom, 6 or 8 for a Sony Vaio eeprom,
3013#          1 or 2 for an unknown eeprom
3014# Registers used:
3015#   0-63: PC-100 Data and Checksum
3016#   2-5, 128-131: Sony Vaio Data
3017sub eeprom_detect
3018{
3019  my ($file,$addr) = @_;
3020  # Check the checksum for validity (only works for PC-100 DIMMs)
3021  my $checksum = 0;
3022  for (my $i = 0; $i <= 62; $i ++) {
3023    $checksum += i2c_smbus_read_byte_data($file,$i);
3024  }
3025  $checksum &= 255;
3026  return 8
3027    if (i2c_smbus_read_byte_data($file,63) == $checksum);
3028  # Even if checksum test fails, it still may be an eeprom
3029  if (i2c_smbus_read_byte_data($file,2) == 0
3030   && i2c_smbus_read_byte_data($file,3) == 0
3031   && i2c_smbus_read_byte_data($file,4) == 0
3032   && i2c_smbus_read_byte_data($file,5) == 0)
3033  {
3034    if (i2c_smbus_read_byte_data($file,128) == ord 'P'
3035     && i2c_smbus_read_byte_data($file,129) == ord 'C'
3036     && i2c_smbus_read_byte_data($file,130) == ord 'G'
3037     && i2c_smbus_read_byte_data($file,131) == ord '-')
3038    {
3039      # Sony Vaio
3040      return 8 if ($addr == 0x57);
3041      return 6;
3042    }
3043    return 2;
3044  }
3045  return 1;
3046}
3047
3048# $_[0]: A reference to the file descriptor to access this chip.
3049#        We may assume an i2c_set_slave_addr was already done.
3050# $_[1]: Address
3051# Returns: undef if not detected, (1) if detected.
3052# Detection is impossible!
3053sub ltc1710_detect
3054{
3055  return (1);
3056}
3057
3058# $_[0]: A reference to the file descriptor to access this chip.
3059#        We may assume an i2c_set_slave_addr was already done.
3060# $_[1]: Address
3061# Returns: undef if not detected, (1) if detected.
3062# Registers used:
3063#   0x00..0x07: DDC signature
3064#   0x08..0x7E: checksumed area
3065#   0x7F:       checksum
3066### commented out additional location checks for now - don't work?
3067sub ddcmonitor_detect
3068{
3069  my ($file,$addr) = @_;
3070  my $i;
3071###  for ($i = 0; $i < 8; $i ++) {
3072###    i2c_set_slave_addr \*FILE,$addr+$i or goto FAILURE;
3073    i2c_smbus_read_byte_data($file,0x00) == 0x00 or goto FAILURE;
3074    i2c_smbus_read_byte_data($file,0x01) == 0xFF or goto FAILURE;
3075    i2c_smbus_read_byte_data($file,0x02) == 0xFF or goto FAILURE;
3076    i2c_smbus_read_byte_data($file,0x03) == 0xFF or goto FAILURE;
3077    i2c_smbus_read_byte_data($file,0x04) == 0xFF or goto FAILURE;
3078    i2c_smbus_read_byte_data($file,0x05) == 0xFF or goto FAILURE;
3079    i2c_smbus_read_byte_data($file,0x06) == 0xFF or goto FAILURE;
3080    i2c_smbus_read_byte_data($file,0x07) == 0x00 or goto FAILURE;
3081###  }
3082###  i2c_set_slave_addr \*FILE,$addr or return;
3083  # Check the checksum for validity. We should do this for all addresses,
3084  # but it would be too slow.
3085  my $checksum = 0;
3086  for ($i = 0; $i <= 127; $i = $i + 1) {
3087    $checksum = $checksum + i2c_smbus_read_byte_data($file,$i);
3088  }
3089  $checksum=$checksum & 255;
3090  if ($checksum != 0) {
3091    # I have one such monitor...
3092    return (2,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
3093  }
3094  return (8,$addr+1,$addr+2,$addr+3,$addr+4,$addr+5,$addr+6,$addr+7);
3095FAILURE:
3096  i2c_set_slave_addr \*FILE,$addr;
3097  return;
3098}
3099
3100# $_[0]: A reference to the file descriptor to access this chip.
3101#        We may assume an i2c_set_slave_addr was already done.
3102# $_[1]: Address
3103# Returns: undef if not detected, (8) if detected.
3104# Registers used:
3105#   0x00-0x02: Identification ('P','E','G' -> Pegasus ? :-)
3106sub fscpos_detect
3107{
3108  my ($file,$addr) = @_;
3109  # check the first 3 registers
3110  if (i2c_smbus_read_byte_data($file,0x00) != 0x50) {
3111        return;
3112  }
3113  if (i2c_smbus_read_byte_data($file,0x01) != 0x45) {
3114        return;
3115  }
3116  if (i2c_smbus_read_byte_data($file,0x02) != 0x47) {
3117        return;
3118  }
3119  return (8);
3120}
3121
3122# $_[0]: A reference to the file descriptor to access this chip.
3123#        We may assume an i2c_set_slave_addr was already done.
3124# $_[1]: Address
3125# Returns: undef if not detected, (8) if detected.
3126# Registers used:
3127#   0x00-0x02: Identification ('S','C','Y')
3128sub fscscy_detect
3129{
3130  my ($file,$addr) = @_;
3131  # check the first 3 registers
3132  if (i2c_smbus_read_byte_data($file,0x00) != 0x53) {
3133        return;
3134  }
3135  if (i2c_smbus_read_byte_data($file,0x01) != 0x43) {
3136        return;
3137  }
3138  if (i2c_smbus_read_byte_data($file,0x02) != 0x59) {
3139        return;
3140  }
3141  return (8);
3142}
3143
3144# $_[0]: Chip to detect (0 = PCF8591, 1 = PCF8574, 2 = PCF8574A).
3145# $_[1]: A reference to the file descriptor to access this chip.
3146#        We may assume an i2c_set_slave_addr was already done.
3147# $_[2]: Address
3148# Returns: 1
3149# Detection is impossible...
3150sub pcf8591_detect
3151{
3152  return (1);
3153}
3154
3155# $_[0]: A reference to the file descriptor to access this chip.
3156#        We may assume an i2c_set_slave_addr was already done.
3157# $_[1]: Address
3158# Returns: undef if not detected, 4 or 7 if detected
3159# Detection is based on the fact that the SAA1064 has only one readable
3160# register, and thus ignores the read address. This register can have value
3161# 0x80 (first read since power-up) or 0x00.
3162sub saa1064_detect
3163{
3164        my ($file,$addr) = @_;
3165        my $status = i2c_smbus_read_byte_data ($file, 0x00);
3166
3167        return if ($status & 0x7f) != 0x00;
3168
3169        for (my $i=0 ; $i<256; $i++) {
3170                return if i2c_smbus_read_byte_data ($file, $i) != 0x00;
3171        }
3172
3173        return 7
3174                if $status == 0x80;
3175        return 4;
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: 1
3182# This is a placeholder so we get a report if any device responds
3183# to the SMBus Device Default Address (0x61), which is used for
3184# ARP in SMBus 2.0.
3185sub arp_detect
3186{
3187  return (1);
3188}
3189
3190# $_[0]: A reference to the file descriptor to access this chip.
3191#        We may assume an i2c_set_slave_addr was already done.
3192# $_[1]: Address
3193# Returns: 1
3194sub smartbatt_detect
3195{
3196  my ($file,$addr) = @_;
3197  # check some registers
3198  if (i2c_smbus_read_byte_data($file,0x08) == 0xff) {
3199        return;
3200  }
3201  if (i2c_smbus_read_byte_data($file,0x09) != 0xff) {
3202        return;
3203  }
3204  if (i2c_smbus_read_byte_data($file,0x0a) != 0xff) {
3205        return;
3206  }
3207  return (3);
3208}
3209
3210# Returns: 4
3211# These are simple detectors that only look for a register at the
3212# standard location. No writes are performed.
3213# For KCS, use the STATUS register. For SMIC, use the FLAGS register.
3214sub ipmi_kcs_detect
3215{
3216  return if inb (0x0ca3) == 0xff;
3217  return (4);
3218}
3219
3220sub ipmi_smic_detect
3221{
3222  return if inb (0x0cab) == 0xff;
3223  return (4);
3224}
3225
3226# $_[0]: Chip to detect (0 = W83L784R/AR)
3227# $_[1]: A reference to the file descriptor to access this chip.
3228# $_[2]: Address
3229# Returns: undef if not detected, 8 if detected
3230# Registers used:
3231#   0x4a: Full I2C Address
3232#   0x4b: I2C addresses of emulated LM75 chips
3233#   0x4c: Winbond Vendor ID (Low Byte)
3234#   0x4d: Winbond Vendor ID (High Byte)
3235#   0x4e: Chip ID
3236# Note that this function is always called through a closure, so the
3237# arguments are shifted by one place.
3238sub w83l784r_detect
3239{
3240  my ($reg,@res);
3241  my ($chip,$file,$addr) = @_;
3242
3243  return unless i2c_smbus_read_byte_data($file,0x4a) == $addr;
3244  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
3245  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
3246  return unless i2c_smbus_read_byte_data($file,0x4e) == 0x50;
3247
3248  $reg = i2c_smbus_read_byte_data($file,0x4b);
3249  @res = (8);
3250  push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08 ;
3251  push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
3252  return @res;
3253}
3254
3255# $_[0]: Chip to detect (0 = W83L785TS-S)
3256# $_[1]: A reference to the file descriptor to access this chip.
3257#        We may assume an i2c_set_slave_addr was already done.
3258# $_[2]: Address
3259# Returns: undef if not detected, 8 if detected
3260# Registers used:
3261#   0x4C-4E: Mfr and Chip ID
3262# Note that this function is always called through a closure, so the
3263# arguments are shifted by one place.
3264sub w83l785ts_detect
3265{
3266  my ($chip,$file,$addr) = @_;
3267  return unless i2c_smbus_read_byte_data($file,0x4c) == 0xa3;
3268  return unless i2c_smbus_read_byte_data($file,0x4d) == 0x5c;
3269  return unless i2c_smbus_read_byte_data($file,0x4e) == 0x70;
3270  return (8);
3271}
3272
3273
3274
3275################
3276# MAIN PROGRAM #
3277################
3278
3279# $_[0]: reference to a list of chip hashes
3280sub print_chips_report 
3281{
3282  my ($listref) = @_;
3283  my $data;
3284 
3285  foreach $data (@$listref) {
3286    my $is_i2c = exists $data->{i2c_addr};
3287    my $is_isa = exists $data->{isa_addr};
3288    print "  * ";
3289    if ($is_i2c) {
3290      printf "Bus `%s' (%s)\n", $data->{i2c_adap}, $data->{i2c_algo};
3291      printf "    Busdriver `%s', I2C address 0x%02x", 
3292             $data->{i2c_driver}, $data->{i2c_addr};
3293      if (exists $data->{i2c_sub_addrs}) {
3294        print " (and";
3295        my $sub_addr;
3296        foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
3297          printf " 0x%02x",$sub_addr;
3298        }
3299        print ")"
3300      }
3301      print "\n";
3302    }
3303    if ($is_isa) {
3304      print "    " if  $is_i2c;
3305      if ($data->{isa_addr}) {
3306        printf "ISA bus address 0x%04x (Busdriver `i2c-isa')\n", 
3307               $data->{isa_addr};
3308      } else {
3309        printf "ISA bus, undetermined address (Busdriver `i2c-isa')\n"
3310      }
3311    }
3312    printf "    Chip `%s' (confidence: %d)\n",
3313           $data->{chipname},  $data->{conf};
3314  }
3315}
3316
3317# $_[0]: 1 if ISA bus is prefered, 0 for SMBus
3318# We build here an array adapters, indexed on the number the adapter has
3319# at this moment (we assume only loaded adapters are interesting at all;
3320# everything that got scanned also got loaded). Each entry is a reference
3321# to a hash containing:
3322#  driver: Name of the adapter driver
3323#  nr_now: Number of the bus now
3324#  nr_later: Number of the bus when the modprobes are done (not included if the
3325#        driver should not be loaded)
3326# A second array, called
3327sub generate_modprobes
3328{
3329  my ($prefer_isa) = @_;
3330
3331  my ($chip,$detection,$nr,$i,@optionlist,@probelist,$driver,$isa,$adap);
3332  my @adapters;
3333  my $modprobes = "";
3334  my $configfile = "";
3335
3336  # These are always needed
3337  $configfile .= "# I2C module options\n";
3338  $configfile .= "alias char-major-89 i2c-dev\n";
3339
3340  # Collect all loaded adapters
3341  open INPUTFILE,"/proc/bus/i2c" or die "Couldn't open /proc/bus/i2c?!?";
3342  while (<INPUTFILE>) {
3343    my ($dev_nr,$type,$adap,$algo) = /^i2c-(\S+)\s+(\S+)\s+(.*?)\s*\t\s*(.*?)\s+$/;
3344    next if ($type eq "dummy");
3345    $adapters[$dev_nr]->{driver} = find_adapter_driver($adap,$algo);
3346    $adapters[$dev_nr]->{adapname} = $adap;
3347    $adapters[$dev_nr]->{algoname} = $algo;
3348  }
3349  close INPUTFILE;
3350
3351  # Collect all adapters used
3352  $nr = 0;
3353  $isa = 0;
3354  $modprobes .= "# I2C adapter drivers\n";
3355  foreach $chip (@chips_detected) {
3356    foreach $detection (@{$chip->{detected}}) {
3357      # If there is more than one bus detected by a driver, they are
3358      # still all added. So we number them in the correct order
3359      if (exists $detection->{i2c_driver} and
3360          not exists $adapters[$detection->{i2c_devnr}]->{nr_later} and 
3361          not (exists $detection->{isa_addr} and $prefer_isa)) {
3362         foreach $adap (@adapters) {
3363           $adap->{nr_later} = $nr++ if $adap->{driver} eq $detection->{i2c_driver};
3364         }
3365      }
3366      if (exists $detection->{isa_addr} and
3367          not (exists $detection->{i2c_driver} and not $prefer_isa)) {
3368           $isa=1;
3369      }
3370    }
3371  }
3372
3373  for ($i = 0; $i < $nr; $i++) {
3374    foreach $adap (@adapters) {
3375      if ($adap->{driver} eq "UNKNOWN") {
3376        $modprobes .= "# modprobe unknown adapter ".$adap->{adapname}." using ". $adap->{algoname}."\n";
3377      } elsif ($adap->{driver} eq "DISABLED") {
3378        $modprobes .= "# modprobe disabled adapter ".$adap->{adapname}." using ". $adap->{algoname}."\n";
3379      } else {
3380        $modprobes .= "modprobe $adap->{driver}\n" if (defined($adap->{nr_later}) and $adap->{nr_later} == $i) and not $modprobes =~ /modprobe $adap->{driver}\n/;
3381      }
3382    }
3383  }
3384  $modprobes .= "modprobe i2c-isa\n" if ($isa);
3385
3386  # Now determine the chip probe lines
3387  $modprobes .= "# I2C chip drivers\n";
3388  foreach $chip (@chips_detected) {
3389    next if not @{$chip->{detected}};
3390    $modprobes .= "modprobe $chip->{driver}\n";
3391    @optionlist = ();
3392    @probelist = ();
3393
3394    # Handle detects at addresses normally not probed
3395    foreach $detection (@{$chip->{detected}}) {
3396      push @probelist, $adapters[$detection->{i2c_devnr}]->{nr_later},
3397                       $detection->{i2c_addr}
3398           if exists $detection->{i2c_addr} and
3399              exists $detection->{i2c_extra};
3400      push @probelist, -1, $detection->{isa_addr}
3401           if exists $detection->{isa_addr} and
3402              exists $detection->{isa_extra};
3403    }
3404
3405    # Handle misdetects
3406    foreach $detection (@{$chip->{misdetected}}) {
3407      push @optionlist, $adapters[$detection->{i2c_devnr}]->{nr_later},
3408                       $detection->{i2c_addr}
3409           if exists $detection->{i2c_addr} and
3410              exists $adapters[$detection->{i2c_devnr}]->{nr_later};
3411      push @optionlist, -1, $detection->{isa_addr}
3412           if exists $detection->{isa_addr} and $isa;
3413    }
3414
3415    # Handle aliases
3416    foreach $detection (@{$chip->{detected}}) {
3417      if (exists $detection->{i2c_driver} and 
3418          exists $detection->{isa_addr} and
3419          exists $adapters[$detection->{i2c_devnr}]->{nr_later} and
3420          $isa) {
3421        if ($prefer_isa) {
3422          push @optionlist,$adapters[$detection->{i2c_devnr}]->{nr_later},
3423                           $detection->{i2c_addr};
3424        } else {
3425          push @optionlist, -1, $detection->{isa_addr}
3426        }
3427      }
3428    }
3429
3430    next if not (@probelist or @optionlist);
3431    $configfile .= "options $chip->{driver}";
3432    $configfile .= sprintf " ignore=%d,0x%02x",shift @optionlist, 
3433                                               shift @optionlist
3434                  if @optionlist;
3435    $configfile .= sprintf ",%d,0x%02x",shift @optionlist, shift @optionlist
3436                  while @optionlist;
3437    $configfile .= sprintf " probe=%d,0x%02x",shift @probelist,
3438                                              shift @probelist
3439                  if @probelist;
3440    $configfile .= sprintf ",%d,0x%02x",shift @probelist, shift @probelist
3441                  while @probelist;
3442    $configfile .= "\n";
3443  }
3444
3445  return ($modprobes,$configfile);
3446 
3447}
3448
3449# returns:
3450# system id string (e.g. 'IBM'), unsafe system
3451# '1', safe system
3452# 0, could not determine
3453sub system_safeness_by_dmi
3454{
3455  my $opened = 0;
3456  foreach my $dmidecode (@dmidecode)
3457  {
3458    last if (-r $dmidecode && ($opened = open (DMI, "$dmidecode |")));
3459  }
3460
3461  unless ($opened)
3462  {
3463    print " Could not find dmidecode, which should have been installed with lm_sensors.\n",
3464          " Runing dmidecode would help us determining your system vendor, which allows\n",
3465          " safer operations. Please provide one of the following:\n  ";
3466    print join ("\n  ", @dmidecode);
3467    print "\n You can still go on, but you are encouraged to fix the problem first.\n\n";
3468    return 0;
3469  }
3470
3471  my ($dmitype, $biosversion, $systemvendor);
3472  while (<DMI>)
3473  {
3474    if (m/^\s*DMI type (\d+),/)
3475    {
3476      $dmitype = $1;
3477      next;
3478    }
3479    next unless defined $dmitype;
3480    if ($dmitype == 1 && m/^\s*(Vendor|Manufacturer): (.*)$/)
3481    {
3482      $systemvendor = $2;
3483    }
3484    elsif ($dmitype == 0 && m/^\s*Version: (.*)$/)
3485    {
3486      $biosversion = $1;
3487    }
3488    last if (defined $biosversion && defined $systemvendor);
3489  }
3490  close (DMI);
3491
3492  if (defined $systemvendor && $systemvendor !~ m/^\s*$/)
3493  {
3494    $systemvendor =~ s/\s*$//;
3495    print " System vendor (DMI): $systemvendor\n";
3496    if (defined $biosversion && $biosversion !~ m/^\s*$/)
3497    {
3498      $biosversion =~ s/\s*$//;
3499      print " BIOS version (DMI): $biosversion\n";
3500    }
3501    return 'IBM' if $systemvendor =~ /\bIBM\b/;
3502    return '1';
3503  }
3504
3505  return undef;
3506}
3507
3508# returns:
3509# system id string (e.g. 'IBM'), unsafe system
3510# '1', safe system
3511# 0, could not determine
3512sub system_safeness_by_acpi
3513{
3514  my $pos = 0xF0000;
3515  my $found = 0;
3516  my $oem = '';
3517
3518  return 0
3519    unless open MEM, '/dev/mem';
3520  binmode MEM;
3521  unless (seek MEM, $pos, SEEK_SET)
3522  {
3523    close MEM;
3524    return 0;
3525  }
3526  while ($pos <= 0xFFFF0 && !$found)
3527  {
3528    my $r = read (MEM, my $buf, 16);
3529    unless ($r == 16)
3530    {
3531      close MEM;
3532      return 0;
3533    }
3534    if (substr ($buf, 0, 8) eq 'RSD PTR ')
3535    {
3536      $oem = substr ($buf, 9, 6);
3537      $found++;
3538    }
3539    $pos += 16;
3540  }
3541  close MEM;
3542
3543  return 0 unless $found;
3544  print " BIOS vendor (ACPI): $oem\n";
3545  return 'IBM' if $oem eq 'IBM   ';
3546  return '1';
3547}
3548
3549# returns:
3550# 1 : the system is known to be safe
3551# 0 : the system safeness is unknown
3552# If the system is know to be unsafe (i.e. for now, IBM systems), never
3553#   return.
3554sub safe_system_vendor
3555{
3556  if ($> != 0)
3557  {
3558        print " As you are not root, we can't determine your system vendor.\n";
3559        return 0;
3560  }
3561
3562  # We now have two methods for detecting IBM systems: ACPI and DMI.
3563  # The ACPI scan is easy and handled internally. The DMI scan, being more
3564  # complex, is handled by dmidecode, externally. Each method can return
3565  # three status:
3566  #  * the system is known to be safe (returns '1');
3567  #  * the system is known to be unsafe (returns a string that identifies
3568  #    the system, e.g. 'IBM');
3569  #  * the method doesn't permit to detect wether the system is safe
3570  #    (returns 0).
3571  # We then combine both results to come to a conclusion. The rules we
3572  # follow are (in order):
3573  #  * if both methods return 0, we can't say anything and return 0 (meaning
3574  #    "system safeness is unknown");
3575  #  * else, if no method returns an identifier string (that is, each method
3576  #    returns either 0 or '1'), we assume that the system is safe and
3577  #    return 1 (meaning "system is safe");
3578  #  * else display an alert message and exit; if only one of the methods
3579  #    worked, ask the user to be kind and send us a report.
3580
3581  my $safeness_acpi = system_safeness_by_acpi();
3582  my $safeness_dmi = system_safeness_by_dmi();
3583
3584  return 0
3585        unless ($safeness_acpi || $safeness_dmi);
3586
3587  return 1
3588    if ((!$safeness_acpi || $safeness_acpi eq '1')
3589         && (!$safeness_dmi || $safeness_dmi eq '1'));
3590
3591  my $safeness = (!$safeness_acpi || $safeness_acpi eq '1')?
3592    $safeness_dmi:$safeness_acpi;
3593
3594  print " Sorry, we won't let you go on. $safeness systems are known to have\n",
3595        " serious problems with lm_sensors, resulting in hardware failures.\n",
3596        " For more information, see README.thinkpad or\n",
3597        " http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/README.thinkpad.\n";
3598
3599  if($safeness_acpi eq '1' || $safeness_dmi eq '1')
3600  {
3601    print " We used two methods to determine your system's vendor, and they led\n",
3602          " to different results. We'd appreciate to have feedback about such\n",
3603          " systems. Please, take some time and contact the lm_sensors mailing\n",
3604          " list at <sensors\@stimpy.netroedge.com>.\n",
3605          " We need the following information:\n",
3606          "  * The brand and model of your system\n",
3607          "  * The BIOS vendor (ACPI) displayed above\n",
3608          "  * The System vendor (DMI) displayed above\n",
3609          " Thanks!\n";
3610  }
3611
3612  exit;
3613}
3614
3615sub main
3616{
3617  my (@adapters,$res,$did_adapter_detection,$detect_others,$adapter);
3618
3619  initialize_proc_pci;
3620  initialize_modules_list;
3621
3622  print " This program will help you to determine which I2C/SMBus modules you ",
3623        "need to\n",
3624        " load to use lm_sensors most effectively.\n";
3625  print " You need to have done a `make install', issued a `depmod -a' and ",
3626        "made sure\n",
3627        " `/etc/conf.modules' (or `/etc/modules.conf') contains the ",
3628        "appropriate\n",
3629        " module path before you can use some functions of this utility. ",
3630        "Read\n",
3631        " doc/modules for more information.\n";
3632  print " Also, you need to be `root', or at least have access to the ",
3633        "/dev/i2c[-/]* files\n",
3634        " for some things. You can use prog/mkdev/mkdev.sh to create these ",
3635        "/dev files\n",
3636        " if you do not have them already.\n";
3637  print " If you have patched your kernel and have some drivers built-in ",
3638        "you can\n",
3639        " safely answer NO if asked to load some modules. In this case, ",
3640        "things may\n",
3641        " seem a bit confusing, but they will still work.\n\n";
3642
3643  unless (safe_system_vendor ())
3644  {
3645    print " IF THIS IS AN IBM THINKPAD, PRESS CTRL-C NOW!\n";
3646    print " IBM Thinkpads have a severely broken i2c/SMBus implementation, ";
3647    print "just scanning\n";
3648    print " the bus will break your Thinkpad forever!\n";
3649    print " If this is a non-Thinkpad IBM, we still suggest you press CTRL+C. We have\n";
3650    print " had users reporting system breakage on other IBM systems as well.\n\n";
3651  }
3652
3653  print " We can start with probing for (PCI) I2C or SMBus adapters.\n";
3654  print " You do not need any special privileges for this.\n";
3655  print " Do you want to probe now? (YES/no): ";
3656  @adapters = adapter_pci_detection
3657                        if ($did_adapter_detection = not <STDIN> =~ /\s*[Nn]/);
3658
3659  print "\n";
3660
3661  if (not $did_adapter_detection) {
3662    print " As you skipped adapter detection, we will only scan already ",
3663          "loaded adapter\n",
3664          " modules. You can still be prompted for non-detectable adapters.\n",
3665          " Do you want to? (yes/NO): ";
3666    $detect_others = <STDIN> =~ /^\s*[Yy]/;
3667  } elsif ($> != 0) {
3668    print " As you are not root, we can't load adapter modules. We will only ",
3669          "scan\n",
3670          " already loaded adapters.\n";
3671    $detect_others = 0;
3672  } else {
3673    print " We will now try to load each adapter module in turn.\n";
3674    foreach $adapter (@adapters) {
3675      next if $adapter eq "DISABLED";
3676      if (contains $adapter, @modules_list) {
3677        print "Module `$adapter' already loaded.\n";
3678      } else {
3679        print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
3680        unless (<STDIN> =~ /^\s*[Nn]/) {
3681          if (system ("modprobe", $adapter)) {
3682            print "Loading failed... skipping.\n";
3683            if ($adapter eq "rivatv") {
3684              print "** Note: rivatv module is available at http://rivatv.sourceforge.net/\n"; 
3685            }
3686          } else {
3687            print "Module loaded succesfully.\n";
3688          }
3689        }
3690      }
3691    }
3692    print " Do you now want to be prompted for non-detectable adapters? ",
3693          "(yes/NO): ";
3694    $detect_others = <STDIN> =~ /^\s*[Yy]/ ;
3695  }
3696
3697  if ($detect_others) {
3698    foreach $adapter (@undetectable_adapters) {
3699      print "Load `$adapter' (say NO if built into your kernel)? (YES/no): ";
3700      unless (<STDIN> =~ /^\s*[Nn]/) {
3701        if (system ("modprobe", $adapter)) {
3702          print "Loading failed... skipping.\n";
3703        } else {
3704          print "Module loaded succesfully.\n";
3705        }
3706      }
3707    }
3708  }
3709
3710  print " To continue, we need module `i2c-dev' to be loaded.\n";
3711  print " If it is built-in into your kernel, you can safely skip this.\n";
3712  if (contains "i2c-dev", @modules_list) {
3713    print "i2c-dev is already loaded.\n";
3714  } else {
3715    if ($> != 0) {
3716      print " i2c-dev is not loaded. As you are not root, we will just hope ",
3717            "you edited\n",
3718            " `/etc/conf.modules' (or `/etc/modules.conf') for automatic ",
3719            "loading of\n",
3720            " this module. If not, you won't be able to open any /dev/i2c[-/]* ",
3721            "file.\n";
3722    } else {
3723      print " i2c-dev is not loaded. Do you want to load it now? (YES/no): ";
3724      if (<STDIN> =~ /^\s*[Nn]/) {
3725        print " Well, you will know best. We will just hope you edited ",
3726              "`/etc/conf.modules'\n",
3727              " (or `/etc/modules.conf') for automatic loading of this ",
3728              "module. If not,\n",
3729              " you won't be able to open any /dev/i2c[-/]* file (unless you",
3730              "have it built-in\n",
3731              " into your kernel)\n";
3732      } elsif (system "modprobe","i2c-dev") {
3733        print " Loading failed, expect problems later on.\n";
3734      } else {
3735        print " Module loaded succesfully.\n";
3736      }
3737    }
3738  }
3739
3740  print "\n We are now going to do the adapter probings. Some adapters may ",
3741        "hang halfway\n",
3742        " through; we can't really help that. Also, some chips will be double ",
3743        "detected;\n",
3744        " we choose the one with the highest confidence value in that case.\n",
3745        " If you found that the adapter hung after probing a certain address, ",
3746        "you can\n",
3747        " specify that address to remain unprobed. That ",
3748        "often\n",
3749        " includes address 0x69 (clock chip).\n";
3750
3751  my ($inp,@not_to_scan,$inp2);
3752  open INPUTFILE,"/proc/bus/i2c" or die "Couldn't open /proc/bus/i2c?!?";
3753  while (<INPUTFILE>) {
3754    my ($dev_nr,$type,$adap,$algo) = /^i2c-(\S+)\s+(\S+)\s+(.*?)\s*\t\s*(.*?)\s+$/;
3755    next if ($type eq "dummy");
3756    print "\n";
3757    print "Next adapter: $adap ($algo)\n";
3758    print "Do you want to scan it? (YES/no/selectively): ";
3759   
3760    $inp = <STDIN>;
3761    @not_to_scan=();
3762    if ($inp =~ /^\s*[Ss]/) {
3763      print "Please enter one or more addresses not to scan. Separate them ",
3764            "with comma's.\n",
3765            "You can specify a range by using dashes. Addresses may be ",
3766            "decimal (like 54)\n",
3767            "or hexadecimal (like 0x33).\n",
3768            "Addresses: ";
3769      $inp2 = <STDIN>;
3770      chop $inp2;
3771      @not_to_scan = parse_not_to_scan 0,0x7f,$inp2;
3772    }
3773    scan_adapter $dev_nr, $adap, $algo, find_adapter_driver($adap,$algo),
3774                 \@not_to_scan   unless $inp =~ /^\s*[Nn]/;
3775  }
3776
3777  print "\n Some chips are also accessible through the ISA bus. ISA probes ",
3778        "are\n",
3779        " typically a bit more dangerous, as we have to write to I/O ports ",
3780        "to do\n",
3781        " this. ";
3782  if ($> != 0) {
3783    print "As you are not root, we shall skip this step.\n";
3784  } else {
3785    print " Do you want to scan the ISA bus? (YES/no): ";
3786    if (not <STDIN> =~ /^\s*[Nn]/) {
3787      initialize_ioports();
3788      scan_isa_bus();
3789      close_ioports();
3790    }
3791  }
3792
3793  print "\n Some Super I/O chips may also contain sensors. Super I/O probes ",
3794        "are\n",
3795        " typically a bit more dangerous, as we have to write to I/O ports ",
3796        "to do\n",
3797        " this. ";
3798  if ($> != 0) {
3799    print "As you are not root, we shall skip this step.\n";
3800  } else {
3801    print " Do you want to scan for Super I/O sensors? (YES/no): ";
3802    if (not <STDIN> =~ /^\s*[Nn]/) {
3803      initialize_ioports();
3804      scan_superio();
3805      close_ioports();
3806    }
3807  }
3808
3809  if(! @chips_detected) {
3810    print "\n Sorry, no chips were detected.\n",
3811        " Either your sensors are not supported, or they are\n",
3812        " connected to an I2C bus adapter that we do not support.\n",
3813        " See doc/FAQ, doc/lm_sensors-FAQ.html, or\n",
3814        " http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/doc/lm_sensors-FAQ.html\n",
3815        " (FAQ #4.24.3) for further information.\n",
3816        " If you find out what chips are on your board, see\n",
3817        " http://secure.netroedge.com/~lm78/newdrivers.html for driver status.\n";
3818    exit;
3819  }
3820
3821  print "\n Now follows a summary of the probes I have just done.\n";
3822  print " Just press ENTER to continue: ";
3823  <STDIN>;
3824
3825  my ($chip,$data);
3826  foreach $chip (@chips_detected) {
3827    print "\nDriver `$$chip{driver}' ";
3828    if (@{$$chip{detected}}) {
3829      if (@{$$chip{misdetected}}) {
3830        print "(should be inserted but causes problems):\n";
3831      } else {
3832        print "(should be inserted):\n";
3833      }
3834    } else {
3835      if (@{$$chip{misdetected}}) {
3836        print "(may not be inserted):\n";
3837      } else {
3838        print "(should not be inserted, but is harmless):\n";
3839      }
3840    }
3841    if (@{$$chip{detected}}) {
3842      print "  Detects correctly:\n";
3843      print_chips_report $chip->{detected};
3844    }
3845    if (@{$$chip{misdetected}}) {
3846      print "  Misdetects:\n";
3847      print_chips_report $chip->{misdetected};
3848    }
3849  }
3850
3851  print "\n\n",
3852        " I will now generate the commands needed to load the I2C modules.\n",
3853        " Sometimes, a chip is available both through the ISA bus and an ",
3854        "I2C bus.\n",
3855        " ISA bus access is faster, but you need to load an additional driver ",
3856        "module\n",
3857        " for it. If you have the choice, do you want to use the ISA bus or ",
3858        "the\n",
3859        " I2C/SMBus (ISA/smbus)? ";
3860  my $use_isa = not <STDIN> =~ /\s*[Ss]/;
3861     
3862  my ($modprobes,$configfile) = generate_modprobes $use_isa;
3863  print "\nTo make the sensors modules behave correctly, add these lines to either\n",
3864        "/etc/modules.conf or /etc/conf.modules:\n\n";
3865  print "#----cut here----\n";
3866  print $configfile;
3867  print "#----cut here----\n";
3868  print "\nTo load everything that is needed, add this to some /etc/rc* ",
3869        "file:\n\n";
3870  print "#----cut here----\n";
3871  print $modprobes;
3872  print "# sleep 2 # optional\n",
3873        "/usr/local/bin/sensors -s # recommended\n";
3874  print "#----cut here----\n";
3875  print "\nWARNING! If you have some things built into your kernel, the list above\n",
3876        "will contain too many modules. Skip the appropriate ones! You really should\n",
3877        "try these commands right now to make sure everything is working properly.\n",
3878        "Monitoring programs won't work until it's done.\n";
3879 
3880  my $have_sysconfig = -d '/etc/sysconfig';
3881  print "\nDo you want to generate /etc/sysconfig/lm_sensors? (".
3882    ($have_sysconfig?"YES/no":"yes/NO")."): ";
3883  if ($> != 0) {
3884    print "\nAs you are not root, we shall skip this step.\n";
3885  } else {
3886    if (($have_sysconfig and not <STDIN> =~ /^\s*[Nn]/) or <STDIN> =~ /^\s*[Yy]/) {
3887      unless ($have_sysconfig) {
3888        mkdir '/etc/sysconfig', 0777
3889          or die "Sorry, can't create /etc/sysconfig ($!)?!?";
3890      }
3891      open(SYSCONFIG, ">/etc/sysconfig/lm_sensors")
3892        or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)?!?";
3893      print SYSCONFIG <<'EOT';
3894#    /etc/sysconfig/sensors - Defines modules loaded by /etc/rc.d/init.d/lm_sensors
3895#    Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>
3896#
3897#    This program is free software; you can redistribute it and/or modify
3898#    it under the terms of the GNU General Public License as published by
3899#    the Free Software Foundation; either version 2 of the License, or
3900#    (at your option) any later version.
3901#
3902#    This program is distributed in the hope that it will be useful,
3903#    but WITHOUT ANY WARRANTY; without even the implied warranty of
3904#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3905#    GNU General Public License for more details.
3906#
3907#    You should have received a copy of the GNU General Public License
3908#    along with this program; if not, write to the Free Software
3909#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3910#
3911#
3912# See also the lm_sensors homepage at:
3913#     http://www2.lm-sensors.nu/~lm78/index.html
3914#
3915# This file is used by /etc/rc.d/init.d/lm_sensors and defines the modules to
3916# be loaded/unloaded. This file is sourced into /etc/rc.d/init.d/lm_sensors.
3917#
3918# The format of this file is a shell script that simply defines the modules
3919# in order as normal variables with the special names:
3920#    MODULE_0, MODULE_1, MODULE_2, etc.
3921#
3922# List the modules that are to be loaded for your system
3923#
3924EOT
3925      print SYSCONFIG
3926       "# Generated by sensors-detect on " . scalar localtime() . "\n";
3927      my @modules = grep /^modprobe /, split "\n", $modprobes;
3928      my $i = 0;
3929      my $sysconfig = "";
3930      foreach (@modules) {
3931        s/^modprobe //;
3932        $sysconfig .= "MODULE_$i=$_\n";
3933        $i++;
3934      }
3935      print SYSCONFIG $sysconfig;
3936      close(SYSCONFIG);
3937      print "Copy prog/init/lm_sensors.init to /etc/rc.d/init.d/lm_sensors\n";
3938      print "for initialization at boot time.\n";
3939    }
3940  }
3941}
3942
3943main;
Note: See TracBrowser for help on using the browser.