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

Revision 1673, 109.4 KB (checked in by mds, 10 years ago)

point w83627/697 to new driver

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