~ubuntu-branches/ubuntu/saucy/lm-sensors-3/saucy

« back to all changes in this revision

Viewing changes to .pc/09-sensors-detect-sch5524.patch/prog/detect/sensors-detect

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno
  • Date: 2011-02-06 14:46:28 UTC
  • mfrom: (1.1.4 upstream) (0.1.15 sid)
  • Revision ID: james.westby@ubuntu.com-20110206144628-14h2w8yva5p98vv9
Tags: 1:3.2.0-1
* New upstream version.
* Suggests fancontrol instead of recommending it in lm-sensors (closes:
  bug#567185).
* Suggests lm-sensors instead of recommending it in libsensors4 (closes:
  bug#602914).
* Suggests rrdtool in sensord (closes: bug#588132).
* Detect SMSC SCH5524-NS chip (closes: bug#588355).
* Bumped Standards-version to 3.9.1 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
#
 
3
#    sensors-detect - Detect hardware monitoring chips
 
4
#    Copyright (C) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>
 
5
#    Copyright (C) 2004 - 2009  Jean Delvare <khali@linux-fr.org>
 
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., 51 Franklin Street, Fifth Floor, Boston,
 
20
#    MA 02110-1301 USA.
 
21
#
 
22
 
 
23
require 5.004;
 
24
 
 
25
use strict;
 
26
use Fcntl;
 
27
use File::Basename;
 
28
 
 
29
# We will call modprobe, which typically lives in either /sbin,
 
30
# /usr/sbin or /usr/local/bin. So make sure these are all in the PATH.
 
31
foreach ('/usr/sbin', '/usr/local/sbin', '/sbin') {
 
32
        $ENV{PATH} = "$_:".$ENV{PATH}
 
33
                unless $ENV{PATH} =~ m/(^|:)$_\/?(:|$)/;
 
34
}
 
35
 
 
36
#########################
 
37
# CONSTANT DECLARATIONS #
 
38
#########################
 
39
 
 
40
use constant NO_CACHE => 1;
 
41
use vars qw(@pci_adapters @chip_ids @ipmi_ifs @non_hwmon_chip_ids
 
42
            $i2c_addresses_to_scan $revision @i2c_byte_cache);
 
43
 
 
44
$revision = '$Revision: 5861 $ ($Date: 2010-09-21 17:21:05 +0200 (mar. 21 sept. 2010) $)';
 
45
$revision =~ s/\$\w+: (.*?) \$/$1/g;
 
46
$revision =~ s/ \([^()]*\)//;
 
47
 
 
48
# This is the list of SMBus or I2C adapters we recognize by their PCI
 
49
# signature. This is an easy and fast way to determine which SMBus or I2C
 
50
# adapters should be present.
 
51
# Each entry must have a vendid (Vendor ID), devid (Device ID) and
 
52
# procid (Device name) and driver (Device driver).
 
53
@pci_adapters = (
 
54
        {
 
55
                vendid  => 0x8086,
 
56
                devid   => 0x7113,
 
57
                procid  => "Intel 82371AB PIIX4 ACPI",
 
58
                driver  => "i2c-piix4",
 
59
        }, {
 
60
                vendid  => 0x8086,
 
61
                devid   => 0x7603,
 
62
                procid  => "Intel 82372FB PIIX5 ACPI",
 
63
                driver  => "to-be-tested",
 
64
        }, {
 
65
                vendid  => 0x8086,
 
66
                devid   => 0x719b,
 
67
                procid  => "Intel 82443MX Mobile",
 
68
                driver  => "i2c-piix4",
 
69
        }, {
 
70
                vendid  => 0x8086,
 
71
                devid   => 0x2413,
 
72
                procid  => "Intel 82801AA ICH",
 
73
                driver  => "i2c-i801",
 
74
        }, {
 
75
                vendid  => 0x8086,
 
76
                devid   => 0x2423,
 
77
                procid  => "Intel 82801AB ICH0",
 
78
                driver  => "i2c-i801",
 
79
        }, {
 
80
                vendid  => 0x8086,
 
81
                devid   => 0x2443,
 
82
                procid  => "Intel 82801BA ICH2",
 
83
                driver  => "i2c-i801",
 
84
        }, {
 
85
                vendid  => 0x8086,
 
86
                devid   => 0x2483,
 
87
                procid  => "Intel 82801CA/CAM ICH3",
 
88
                driver  => "i2c-i801",
 
89
        }, {
 
90
                vendid  => 0x8086,
 
91
                devid   => 0x24C3,
 
92
                procid  => "Intel 82801DB ICH4",
 
93
                driver  => "i2c-i801",
 
94
        }, {
 
95
                vendid  => 0x8086,
 
96
                devid   => 0x24D3,
 
97
                procid  => "Intel 82801EB ICH5",
 
98
                driver  => "i2c-i801",
 
99
        }, {
 
100
                vendid  => 0x8086,
 
101
                devid   => 0x25A4,
 
102
                procid  => "Intel 6300ESB",
 
103
                driver  => "i2c-i801",
 
104
        }, {
 
105
                vendid  => 0x8086,
 
106
                devid   => 0x269B,
 
107
                procid  => "Intel Enterprise Southbridge - ESB2",
 
108
                driver  => "i2c-i801",
 
109
        }, {
 
110
                vendid  => 0x8086,
 
111
                devid   => 0x266A,
 
112
                procid  => "Intel 82801FB ICH6",
 
113
                driver  => "i2c-i801",
 
114
        }, {
 
115
                vendid  => 0x8086,
 
116
                devid   => 0x27DA,
 
117
                procid  => "Intel 82801G ICH7",
 
118
                driver  => "i2c-i801",
 
119
        }, {
 
120
                vendid  => 0x8086,
 
121
                devid   => 0x283E,
 
122
                procid  => "Intel 82801H ICH8",
 
123
                driver  => "i2c-i801",
 
124
        }, {
 
125
                vendid  => 0x8086,
 
126
                devid   => 0x2930,
 
127
                procid  => "Intel ICH9",
 
128
                driver  => "i2c-i801",
 
129
        }, {
 
130
                vendid  => 0x8086,
 
131
                devid   => 0x5032,
 
132
                procid  => "Intel Tolapai",
 
133
                driver  => "i2c-i801",
 
134
        }, {
 
135
                vendid  => 0x8086,
 
136
                devid   => 0x3A30,
 
137
                procid  => "Intel ICH10",
 
138
                driver  => "i2c-i801",
 
139
        }, {
 
140
                vendid  => 0x8086,
 
141
                devid   => 0x3A60,
 
142
                procid  => "Intel ICH10",
 
143
                driver  => "i2c-i801",
 
144
        }, {
 
145
                vendid  => 0x8086,
 
146
                devid   => 0x3B30,
 
147
                procid  => "Intel 3400/5 Series (PCH)",
 
148
                driver  => "i2c-i801",
 
149
        }, {
 
150
                vendid  => 0x8086,
 
151
                devid   => 0x1C22,
 
152
                procid  => "Intel Cougar Point (PCH)",
 
153
                driver  => "i2c-i801",
 
154
        }, {
 
155
                vendid  => 0x8086,
 
156
                devid   => 0x8119,
 
157
                procid  => "Intel SCH",
 
158
                driver  => "i2c-isch",
 
159
        }, {
 
160
                vendid  => 0x1106,
 
161
                devid   => 0x3040,
 
162
                procid  => "VIA Technologies VT82C586B Apollo ACPI",
 
163
                driver  => "i2c-via",
 
164
        }, {
 
165
                vendid  => 0x1106,
 
166
                devid   => 0x3050,
 
167
                procid  => "VIA Technologies VT82C596 Apollo ACPI",
 
168
                driver  => "i2c-viapro",
 
169
        }, {
 
170
                vendid  => 0x1106,
 
171
                devid   => 0x3051,
 
172
                procid  => "VIA Technologies VT82C596B ACPI",
 
173
                driver  => "i2c-viapro",
 
174
        }, {
 
175
                vendid  => 0x1106,
 
176
                devid   => 0x3057,
 
177
                procid  => "VIA Technologies VT82C686 Apollo ACPI",
 
178
                driver  => "i2c-viapro",
 
179
        }, {
 
180
                vendid  => 0x1106,
 
181
                devid   => 0x3074,
 
182
                procid  => "VIA Technologies VT8233 VLink South Bridge",
 
183
                driver  => "i2c-viapro",
 
184
        }, {
 
185
                vendid  => 0x1106,
 
186
                devid   => 0x3147,
 
187
                procid  => "VIA Technologies VT8233A South Bridge",
 
188
                driver  => "i2c-viapro",
 
189
        }, {
 
190
                vendid  => 0x1106,
 
191
                devid   => 0x3177,
 
192
                procid  => "VIA Technologies VT8233A/8235 South Bridge",
 
193
                driver  => "i2c-viapro",
 
194
        }, {
 
195
                vendid  => 0x1106,
 
196
                devid   => 0x3227,
 
197
                procid  => "VIA Technologies VT8237 South Bridge",
 
198
                driver  => "i2c-viapro",
 
199
        }, {
 
200
                vendid  => 0x1106,
 
201
                devid   => 0x3337,
 
202
                procid  => "VIA Technologies VT8237A South Bridge",
 
203
                driver  => "i2c-viapro",
 
204
        }, {
 
205
                vendid  => 0x1106,
 
206
                devid   => 0x8235,
 
207
                procid  => "VIA Technologies VT8231 South Bridge",
 
208
                driver  => "i2c-viapro",
 
209
        }, {
 
210
                vendid  => 0x1106,
 
211
                devid   => 0x3287,
 
212
                procid  => "VIA Technologies VT8251 South Bridge",
 
213
                driver  => "i2c-viapro",
 
214
        }, {
 
215
                vendid  => 0x1106,
 
216
                devid   => 0x8324,
 
217
                procid  => "VIA Technologies CX700 South Bridge",
 
218
                driver  => "i2c-viapro",
 
219
        }, {
 
220
                vendid  => 0x1106,
 
221
                devid   => 0x8353,
 
222
                procid  => "VIA Technologies VX800/VX820 South Bridge",
 
223
                driver  => "i2c-viapro",
 
224
        }, {
 
225
                vendid  => 0x1039,
 
226
                devid   => 0x0008,
 
227
                procid  => "Silicon Integrated Systems SIS5595",
 
228
                driver  => "i2c-sis5595",
 
229
        }, {
 
230
                vendid  => 0x1039,
 
231
                devid   => 0x0630,
 
232
                procid  => "Silicon Integrated Systems SIS630",
 
233
                driver  => "i2c-sis630",
 
234
        }, {
 
235
                vendid  => 0x1039,
 
236
                devid   => 0x0730,
 
237
                procid  => "Silicon Integrated Systems SIS730",
 
238
                driver  => "i2c-sis630",
 
239
        }, {
 
240
                vendid  => 0x1039,
 
241
                devid   => 0x0016,
 
242
                procid  => "Silicon Integrated Systems SMBus Controller",
 
243
                driver  => "i2c-sis96x",
 
244
        }, {
 
245
                # Both Ali chips below have same PCI ID. Can't be helped. Only one should load.
 
246
                vendid  => 0x10b9,
 
247
                devid   => 0x7101,
 
248
                procid  => "Acer Labs 1533/1543",
 
249
                driver  => "i2c-ali15x3",
 
250
        }, {
 
251
                vendid  => 0x10b9,
 
252
                devid   => 0x7101,
 
253
                procid  => "Acer Labs 1535",
 
254
                driver  => "i2c-ali1535",
 
255
        }, {
 
256
                vendid  => 0x10b9,
 
257
                devid   => 0x1563,
 
258
                procid  => "Acer Labs 1563",
 
259
                driver  => "i2c-ali1563",
 
260
        }, {
 
261
                vendid  => 0x1022,
 
262
                devid   => 0x740b,
 
263
                procid  => "AMD-756 Athlon ACPI",
 
264
                driver  => "i2c-amd756",
 
265
        }, {
 
266
                vendid  => 0x1022,
 
267
                devid   => 0x7413,
 
268
                procid  => "AMD-766 Athlon ACPI",
 
269
                driver  => "i2c-amd756",
 
270
        }, {
 
271
                vendid  => 0x1022,
 
272
                devid   => 0x7443,
 
273
                procid  => "AMD-768 System Management",
 
274
                driver  => "i2c-amd756",
 
275
        }, {
 
276
                vendid  => 0x1022,
 
277
                devid   => 0x746b,
 
278
                procid  => "AMD-8111 ACPI",
 
279
                driver  => "i2c-amd756",
 
280
        }, {
 
281
                vendid  => 0x1022,
 
282
                devid   => 0x746a,
 
283
                procid  => "AMD-8111 SMBus 2.0",
 
284
                driver  => "i2c-amd8111",
 
285
        }, {
 
286
                vendid  => 0x10de,
 
287
                devid   => 0x01b4,
 
288
                procid  => "nVidia nForce SMBus",
 
289
                driver  => "i2c-amd756",
 
290
        }, {
 
291
                vendid  => 0x10de,
 
292
                devid   => 0x0064,
 
293
                procid  => "nVidia Corporation nForce2 SMBus (MCP)",
 
294
                driver  => "i2c-nforce2",
 
295
        }, {
 
296
                vendid  => 0x10de,
 
297
                devid   => 0x0084,
 
298
                procid  => "nVidia Corporation nForce2 Ultra 400 SMBus (MCP)",
 
299
                driver  => "i2c-nforce2",
 
300
        }, {
 
301
                vendid  => 0x10de,
 
302
                devid   => 0x00D4,
 
303
                procid  => "nVidia Corporation nForce3 Pro150 SMBus (MCP)",
 
304
                driver  => "i2c-nforce2",
 
305
        }, {
 
306
                vendid  => 0x10de,
 
307
                devid   => 0x00E4,
 
308
                procid  => "nVidia Corporation nForce3 250Gb SMBus (MCP)",
 
309
                driver  => "i2c-nforce2",
 
310
        }, {
 
311
                vendid  => 0x10de,
 
312
                devid   => 0x0052,
 
313
                procid  => "nVidia Corporation nForce4 SMBus (MCP)",
 
314
                driver  => "i2c-nforce2",
 
315
        }, {
 
316
                vendid  => 0x10de,
 
317
                devid   => 0x0034,
 
318
                procid  => "nVidia Corporation nForce4 SMBus (MCP-04)",
 
319
                driver  => "i2c-nforce2",
 
320
        }, {
 
321
                vendid  => 0x10de,
 
322
                devid   => 0x0264,
 
323
                procid  => "nVidia Corporation nForce SMBus (MCP51)",
 
324
                driver  => "i2c-nforce2",
 
325
        }, {
 
326
                vendid  => 0x10de,
 
327
                devid   => 0x0368,
 
328
                procid  => "nVidia Corporation nForce SMBus (MCP55)",
 
329
                driver  => "i2c-nforce2",
 
330
        }, {
 
331
                vendid  => 0x10de,
 
332
                devid   => 0x03eb,
 
333
                procid  => "nVidia Corporation nForce SMBus (MCP61)",
 
334
                driver  => "i2c-nforce2",
 
335
        }, {
 
336
                vendid  => 0x10de,
 
337
                devid   => 0x0446,
 
338
                procid  => "nVidia Corporation nForce SMBus (MCP65)",
 
339
                driver  => "i2c-nforce2",
 
340
        }, {
 
341
                vendid  => 0x10de,
 
342
                devid   => 0x0542,
 
343
                procid  => "nVidia Corporation nForce SMBus (MCP67)",
 
344
                driver  => "i2c-nforce2",
 
345
        }, {
 
346
                vendid  => 0x10de,
 
347
                devid   => 0x07d8,
 
348
                procid  => "nVidia Corporation nForce SMBus (MCP73)",
 
349
                driver  => "i2c-nforce2",
 
350
        }, {
 
351
                vendid  => 0x10de,
 
352
                devid   => 0x0752,
 
353
                procid  => "nVidia Corporation nForce SMBus (MCP78S)",
 
354
                driver  => "i2c-nforce2",
 
355
        }, {
 
356
                vendid  => 0x10de,
 
357
                devid   => 0x0aa2,
 
358
                procid  => "nVidia Corporation nForce SMBus (MCP79)",
 
359
                driver  => "i2c-nforce2",
 
360
        }, {
 
361
                vendid  => 0x1166,
 
362
                devid   => 0x0200,
 
363
                procid  => "ServerWorks OSB4 South Bridge",
 
364
                driver  => "i2c-piix4",
 
365
        }, {
 
366
                vendid  => 0x1055,
 
367
                devid   => 0x9463,
 
368
                procid  => "SMSC Victory66 South Bridge",
 
369
                driver  => "i2c-piix4",
 
370
        }, {
 
371
                vendid  => 0x1166,
 
372
                devid   => 0x0201,
 
373
                procid  => "ServerWorks CSB5 South Bridge",
 
374
                driver  => "i2c-piix4",
 
375
        }, {
 
376
                vendid  => 0x1166,
 
377
                devid   => 0x0203,
 
378
                procid  => "ServerWorks CSB6 South Bridge",
 
379
                driver  => "i2c-piix4",
 
380
        }, {
 
381
                vendid  => 0x1166,
 
382
                devid   => 0x0205,
 
383
                procid  => "ServerWorks HT-1000 South Bridge",
 
384
                driver  => "i2c-piix4",
 
385
        }, {
 
386
                vendid  => 0x1002,
 
387
                devid   => 0x4353,
 
388
                procid  => "ATI Technologies Inc ATI SMBus",
 
389
                driver  => "i2c-piix4",
 
390
        }, {
 
391
                vendid  => 0x1002,
 
392
                devid   => 0x4363,
 
393
                procid  => "ATI Technologies Inc ATI SMBus",
 
394
                driver  => "i2c-piix4",
 
395
        }, {
 
396
                vendid  => 0x1002,
 
397
                devid   => 0x4372,
 
398
                procid  => "ATI Technologies Inc IXP SB400 SMBus Controller",
 
399
                driver  => "i2c-piix4",
 
400
        }, {
 
401
                vendid  => 0x1002,
 
402
                devid   => 0x4385,
 
403
                procid  => "ATI Technologies Inc SB600/SB700/SB800 SMBus",
 
404
                driver  => "i2c-piix4",
 
405
        }, {
 
406
                vendid  => 0x1022,
 
407
                devid   => 0x780b,
 
408
                procid  => "AMD Hudson-2 SMBus",
 
409
                driver  => "i2c-piix4",
 
410
        }, {
 
411
                vendid  => 0x100B,
 
412
                devid   => 0x0500,
 
413
                procid  => "SCx200 Bridge",
 
414
                driver  => "scx200_acb",
 
415
        }, {
 
416
                vendid  => 0x100B,
 
417
                devid   => 0x0510,
 
418
                procid  => "SC1100 Bridge",
 
419
                driver  => "scx200_acb",
 
420
        }, {
 
421
                vendid  => 0x100B,
 
422
                devid   => 0x002B,
 
423
                procid  => "CS5535 ISA bridge",
 
424
                driver  => "scx200_acb",
 
425
        }, {
 
426
                vendid  => 0x1022,
 
427
                devid   => 0x2090,
 
428
                procid  => "CS5536 [Geode companion] ISA",
 
429
                driver  => "scx200_acb",
 
430
        }
 
431
);
 
432
 
 
433
# Look-up table to find out an I2C bus' driver based on the bus name.
 
434
# The match field should contain a regular expression matching the I2C
 
435
# bus name as it would appear in sysfs.
 
436
# Note that new drivers probably don't need to be added to this table
 
437
# if they bind to their device, as we will be able to get the driver name
 
438
# from sysfs directly.
 
439
use vars qw(@i2c_adapter_names);
 
440
@i2c_adapter_names = (
 
441
        { driver => "i2c-piix4",        match => qr/^SMBus PIIX4 adapter at / },
 
442
        { driver => "i2c-i801",         match => qr/^SMBus I801 adapter at / },
 
443
        { driver => "i2c-via",          match => qr/^VIA i2c/ },
 
444
        { driver => "i2c-viapro",       match => qr/^SMBus V(IA|ia) Pro adapter at / },
 
445
        { driver => "i2c-sis5595",      match => qr/^SMBus SIS5595 adapter at / },
 
446
        { driver => "i2c-sis630",       match => qr/^SMBus SIS630 adapter at / },
 
447
        { driver => "i2c-sis96x",       match => qr/^SiS96x SMBus adapter at / },
 
448
        { driver => "i2c-ali15x3",      match => qr/^SMBus ALI15X3 adapter at / },
 
449
        { driver => "i2c-ali1535",      match => qr/^SMBus ALI1535 adapter at/ },
 
450
        { driver => "i2c-ali1563",      match => qr/^SMBus ALi 1563 Adapter @ / },
 
451
        { driver => "i2c-amd756",       match => qr/^SMBus (AMD756|AMD766|AMD768|AMD8111|nVidia nForce) adapter at / },
 
452
        { driver => "i2c-amd8111",      match => qr/^SMBus2 AMD8111 adapter at / },
 
453
        { driver => "i2c-nforce2",      match => qr/^SMBus nForce2 adapter at / },
 
454
        { driver => "scx200_acb",       match => qr/^(NatSemi SCx200 ACCESS\.bus|SCx200 ACB\d+|CS553[56] ACB\d+)/ },
 
455
);
 
456
 
 
457
# This is a list of all recognized I2C and ISA chips.
 
458
# Each entry must have the following fields:
 
459
#  name: The full chip name
 
460
#  driver: The driver name. Put in exactly:
 
461
#      * "to-be-written" if it is not yet available
 
462
#      * "use-isa-instead" if no i2c driver will be written
 
463
#  i2c_addrs (optional): For I2C chips, the list of I2C addresses to
 
464
#      probe.
 
465
#  i2c_detect (optional): For I2C chips, the function to call to detect
 
466
#      this chip. The function will be passed two parameters: an open file
 
467
#      descriptor to access the bus, and the I2C address to probe.
 
468
#  isa_addrs (optional): For ISA chips, the list of port addresses to
 
469
#      probe.
 
470
#  isa_detect (optional): For ISA chips, the function to call to detect
 
471
#      this chip. The function will be passed one parameter: the ISA address
 
472
#      to probe.
 
473
#  alias_detect (optional): For chips which can be both on the ISA and the
 
474
#      I2C bus, a function which detects whether two entries are the same.
 
475
#      The function will be passed three parameters: the ISA address, an
 
476
#      open file descriptor to access the I2C bus, and the I2C address.
 
477
@chip_ids = (
 
478
        {
 
479
                name => "Myson MTP008",
 
480
                driver => "mtp008",
 
481
                i2c_addrs => [0x2c..0x2e],
 
482
                i2c_detect => sub { mtp008_detect(@_); },
 
483
        }, {
 
484
                name => "National Semiconductor LM78",
 
485
                driver => "lm78",
 
486
                i2c_addrs => [0x28..0x2f],
 
487
                i2c_detect => sub { lm78_detect(@_, 0); },
 
488
                isa_addrs => [0x290],
 
489
                isa_detect => sub { lm78_isa_detect(@_, 0); },
 
490
                alias_detect => sub { winbond_alias_detect(@_, 0x2b, 0x3d); },
 
491
        }, {
 
492
                name => "National Semiconductor LM79",
 
493
                driver => "lm78",
 
494
                i2c_addrs => [0x28..0x2f],
 
495
                i2c_detect => sub { lm78_detect(@_, 2); },
 
496
                isa_addrs => [0x290],
 
497
                isa_detect => sub { lm78_isa_detect(@_, 2); },
 
498
                alias_detect => sub { winbond_alias_detect(@_, 0x2b, 0x3d); },
 
499
        }, {
 
500
                name => "National Semiconductor LM75",
 
501
                driver => "lm75",
 
502
                i2c_addrs => [0x48..0x4f],
 
503
                i2c_detect => sub { lm75_detect(@_, 0); },
 
504
        }, {
 
505
                name => "Dallas Semiconductor DS75",
 
506
                driver => "lm75",
 
507
                i2c_addrs => [0x48..0x4f],
 
508
                i2c_detect => sub { lm75_detect(@_, 1); },
 
509
        }, {
 
510
                name => "National Semiconductor LM77",
 
511
                driver => "lm77",
 
512
                i2c_addrs => [0x48..0x4b],
 
513
                i2c_detect => sub { lm77_detect(@_); },
 
514
        }, {
 
515
                name => "National Semiconductor LM80",
 
516
                driver => "lm80",
 
517
                i2c_addrs => [0x28..0x2f],
 
518
                i2c_detect => sub { lm80_detect(@_); },
 
519
        }, {
 
520
                name => "National Semiconductor LM85",
 
521
                driver => "lm85",
 
522
                i2c_addrs => [0x2c..0x2e],
 
523
                i2c_detect => sub { lm85_detect(@_, 0); },
 
524
        }, {
 
525
                name => "National Semiconductor LM96000 or PC8374L",
 
526
                driver => "lm85",
 
527
                i2c_addrs => [0x2c..0x2e],
 
528
                i2c_detect => sub { lm85_detect(@_, 1); },
 
529
        }, {
 
530
                name => "Analog Devices ADM1027",
 
531
                driver => "lm85",
 
532
                i2c_addrs => [0x2c..0x2e],
 
533
                i2c_detect => sub { lm85_detect(@_, 2); },
 
534
        }, {
 
535
                name => "Analog Devices ADT7460 or ADT7463",
 
536
                driver => "lm85",
 
537
                i2c_addrs => [0x2c..0x2e],
 
538
                i2c_detect => sub { lm85_detect(@_, 3); },
 
539
        }, {
 
540
                name => "SMSC EMC6D100 or EMC6D101",
 
541
                driver => "lm85",
 
542
                i2c_addrs => [0x2c..0x2e],
 
543
                i2c_detect => sub { lm85_detect(@_, 4); },
 
544
        }, {
 
545
                name => "SMSC EMC6D102",
 
546
                driver => "lm85",
 
547
                i2c_addrs => [0x2c..0x2e],
 
548
                i2c_detect => sub { lm85_detect(@_, 5); },
 
549
        }, {
 
550
                name => "SMSC EMC6D103",
 
551
                driver => "lm85",
 
552
                i2c_addrs => [0x2c..0x2e],
 
553
                i2c_detect => sub { lm85_detect(@_, 6); },
 
554
        }, {
 
555
                name => "Winbond WPCD377I",
 
556
                driver => "not-a-sensor",
 
557
                i2c_addrs => [0x2c..0x2e],
 
558
                i2c_detect => sub { lm85_detect(@_, 7); },
 
559
        }, {
 
560
                name => "Analog Devices ADT7462",
 
561
                driver => "adt7462",
 
562
                i2c_addrs => [0x5c, 0x58],
 
563
                i2c_detect => sub { adt7467_detect(@_, 2); },
 
564
        }, {
 
565
                name => "Analog Devices ADT7466",
 
566
                driver => "lm85",
 
567
                i2c_addrs => [0x4c],
 
568
                i2c_detect => sub { adt7467_detect(@_, 3); },
 
569
        }, {
 
570
                name => "Analog Devices ADT7467 or ADT7468",
 
571
                driver => "lm85",
 
572
                i2c_addrs => [0x2e],
 
573
                i2c_detect => sub { adt7467_detect(@_, 0); },
 
574
        }, {
 
575
                name => "Analog Devices ADT7470",
 
576
                driver => "adt7470",
 
577
                i2c_addrs => [0x2c, 0x2e, 0x2f],
 
578
                i2c_detect => sub { adt7467_detect(@_, 4); },
 
579
        }, {
 
580
                name => "Analog Devices ADT7473",
 
581
                driver => sub { kernel_version_at_least(2, 6, 33) ? "adt7475" : "adt7473" },
 
582
                i2c_addrs => [0x2c..0x2e],
 
583
                i2c_detect => sub { adt7473_detect(@_, 0); },
 
584
        }, {
 
585
                name => "Analog Devices ADT7475",
 
586
                driver => "adt7475",
 
587
                i2c_addrs => [0x2e],
 
588
                i2c_detect => sub { adt7473_detect(@_, 1); },
 
589
        }, {
 
590
                name => "Analog Devices ADT7476",
 
591
                driver => "adt7475",
 
592
                i2c_addrs => [0x2c..0x2e],
 
593
                i2c_detect => sub { adt7467_detect(@_, 1); },
 
594
        }, {
 
595
                name => "Analog Devices ADT7490",
 
596
                driver => "adt7475",
 
597
                i2c_addrs => [0x2c..0x2e],
 
598
                i2c_detect => sub { adt7490_detect(@_); },
 
599
        }, {
 
600
                name => "Analog Devices ADT7411",
 
601
                driver => "to-be-written",
 
602
                i2c_addrs => [0x48, 0x4a, 0x4b],
 
603
                i2c_detect => sub { adt7411_detect(@_); },
 
604
        }, {
 
605
                name => "Andigilog aSC7511",
 
606
                driver => "to-be-written",
 
607
                i2c_addrs => [0x4c],
 
608
                i2c_detect => sub { andigilog_aSC7511_detect(@_); },
 
609
        }, {
 
610
                name => "Andigilog aSC7512",
 
611
                driver => "to-be-written",
 
612
                i2c_addrs => [0x58],
 
613
                i2c_detect => sub { andigilog_detect(@_, 0); },
 
614
        }, {
 
615
                name => "Andigilog aSC7611",
 
616
                driver => "to-be-written",
 
617
                i2c_addrs => [0x2c..0x2e],
 
618
                i2c_detect => sub { andigilog_detect(@_, 1); },
 
619
        }, {
 
620
                name => "Andigilog aSC7621",
 
621
                driver => "asc7621",
 
622
                i2c_addrs => [0x2c..0x2e],
 
623
                i2c_detect => sub { andigilog_detect(@_, 2); },
 
624
        }, {
 
625
                name => "National Semiconductor LM87",
 
626
                driver => "lm87",
 
627
                i2c_addrs => [0x2c..0x2e],
 
628
                i2c_detect => sub { lm87_detect(@_, 0); },
 
629
        }, {
 
630
                name => "Analog Devices ADM1024",
 
631
                driver => "lm87",
 
632
                i2c_addrs => [0x2c..0x2e],
 
633
                i2c_detect => sub { lm87_detect(@_, 1); },
 
634
        }, {
 
635
                name => "National Semiconductor LM93",
 
636
                driver => "lm93",
 
637
                i2c_addrs => [0x2c..0x2e],
 
638
                i2c_detect => sub { lm93_detect(@_); },
 
639
        }, {
 
640
                name => "Winbond W83781D",
 
641
                driver => "w83781d",
 
642
                i2c_addrs => [0x28..0x2f],
 
643
                i2c_detect => sub { w83781d_detect(@_, 0); },
 
644
                isa_addrs => [0x290],
 
645
                isa_detect => sub { w83781d_isa_detect(@_, 0); },
 
646
                alias_detect => sub { winbond_alias_detect(@_, 0x2b, 0x3d); },
 
647
        }, {
 
648
                name => "Winbond W83782D",
 
649
                driver => "w83781d",
 
650
                i2c_addrs => [0x28..0x2f],
 
651
                i2c_detect => sub { w83781d_detect(@_, 1); },
 
652
                isa_addrs => [0x290],
 
653
                isa_detect => sub { w83781d_isa_detect(@_, 1); },
 
654
                alias_detect => sub { winbond_alias_detect(@_, 0x2b, 0x3d); },
 
655
        }, {
 
656
                name => "Winbond W83783S",
 
657
                driver => "w83781d",
 
658
                i2c_addrs => [0x2d],
 
659
                i2c_detect => sub { w83781d_detect(@_, 2); },
 
660
        }, {
 
661
                name => "Winbond W83791D",
 
662
                driver => "w83791d",
 
663
                i2c_addrs => [0x2c..0x2f],
 
664
                i2c_detect => sub { w83781d_detect(@_, 7); },
 
665
        }, {
 
666
                name => "Winbond W83792D",
 
667
                driver => "w83792d",
 
668
                i2c_addrs => [0x2c..0x2f],
 
669
                i2c_detect => sub { w83781d_detect(@_, 8); },
 
670
        }, {
 
671
                name => "Winbond W83793R/G",
 
672
                driver => "w83793",
 
673
                i2c_addrs => [0x2c..0x2f],
 
674
                i2c_detect => sub { w83793_detect(@_); },
 
675
        }, {
 
676
                name => "Nuvoton W83795G/ADG",
 
677
                driver => "w83795",
 
678
                i2c_addrs => [0x2c..0x2f],
 
679
                i2c_detect => sub { w83795_detect(@_); },
 
680
        }, {
 
681
                name => "Winbond W83627HF",
 
682
                driver => "use-isa-instead",
 
683
                i2c_addrs => [0x28..0x2f],
 
684
                i2c_detect => sub { w83781d_detect(@_, 3); },
 
685
        }, {
 
686
                name => "Winbond W83627EHF",
 
687
                driver => "use-isa-instead",
 
688
                i2c_addrs => [0x28..0x2f],
 
689
                i2c_detect => sub { w83781d_detect(@_, 9); },
 
690
        }, {
 
691
                name => "Winbond W83627DHG/W83667HG/W83677HG",
 
692
                driver => "use-isa-instead",
 
693
                i2c_addrs => [0x28..0x2f],
 
694
                i2c_detect => sub { w83781d_detect(@_, 10); },
 
695
        }, {
 
696
                name => "Asus AS99127F (rev.1)",
 
697
                driver => "w83781d",
 
698
                i2c_addrs => [0x28..0x2f],
 
699
                i2c_detect => sub { w83781d_detect(@_, 4); },
 
700
        }, {
 
701
                name => "Asus AS99127F (rev.2)",
 
702
                driver => "w83781d",
 
703
                i2c_addrs => [0x28..0x2f],
 
704
                i2c_detect => sub { w83781d_detect(@_, 5); },
 
705
        }, {
 
706
                name => "Asus ASB100 Bach",
 
707
                driver => "asb100",
 
708
                i2c_addrs => [0x28..0x2f],
 
709
                i2c_detect => sub { w83781d_detect(@_, 6); },
 
710
        }, {
 
711
                name => "Asus Mozart-2",
 
712
                driver => "to-be-written",
 
713
                i2c_addrs => [0x77],
 
714
                i2c_detect => sub { mozart_detect(@_); },
 
715
        }, {
 
716
                name => "Winbond W83L784R/AR/G",
 
717
                driver => "to-be-written",
 
718
                i2c_addrs => [0x2d],
 
719
                i2c_detect => sub { w83l784r_detect(@_, 0); },
 
720
        }, {
 
721
                name => "Winbond W83L785R/G",
 
722
                driver => "to-be-written",
 
723
                i2c_addrs => [0x2d],
 
724
                i2c_detect => sub { w83l784r_detect(@_, 1); },
 
725
        }, {
 
726
                name => "Winbond W83L786NR/NG/R/G",
 
727
                driver => "w83l786ng",
 
728
                i2c_addrs => [0x2e, 0x2f],
 
729
                i2c_detect => sub { w83l784r_detect(@_, 2); },
 
730
        }, {
 
731
                name => "Winbond W83L785TS-S",
 
732
                driver => "w83l785ts",
 
733
                i2c_addrs => [0x2e],
 
734
                i2c_detect => sub { w83l784r_detect(@_, 3); },
 
735
        }, {
 
736
                name => "Genesys Logic GL518SM",
 
737
                driver => "gl518sm",
 
738
                i2c_addrs => [0x2c, 0x2d],
 
739
                i2c_detect => sub { gl518sm_detect(@_, 0); },
 
740
        }, {
 
741
                name => "Genesys Logic GL520SM",
 
742
                driver => "gl520sm",
 
743
                i2c_addrs => [0x2c, 0x2d],
 
744
                i2c_detect => sub { gl518sm_detect(@_, 1); },
 
745
        }, {
 
746
                name => "Genesys Logic GL525SM",
 
747
                driver => "to-be-written",
 
748
                i2c_addrs => [0x2d],
 
749
                i2c_detect => sub { gl525sm_detect(@_); },
 
750
        }, {
 
751
                name => "Analog Devices ADM9240",
 
752
                driver => "adm9240",
 
753
                i2c_addrs => [0x2c..0x2f],
 
754
                i2c_detect => sub { adm9240_detect(@_, 0); },
 
755
        }, {
 
756
                name => "Dallas Semiconductor DS1621/DS1631",
 
757
                driver => "ds1621",
 
758
                i2c_addrs => [0x48..0x4f],
 
759
                i2c_detect => sub { ds1621_detect(@_); },
 
760
        }, {
 
761
                name => "Dallas Semiconductor DS1780",
 
762
                driver => "adm9240",
 
763
                i2c_addrs => [0x2c..0x2f],
 
764
                i2c_detect => sub { adm9240_detect(@_, 1); },
 
765
        }, {
 
766
                name => "National Semiconductor LM81",
 
767
                driver => "adm9240",
 
768
                i2c_addrs => [0x2c..0x2f],
 
769
                i2c_detect => sub { adm9240_detect(@_, 2); },
 
770
        }, {
 
771
                name => "Analog Devices ADM1026",
 
772
                driver => "adm1026",
 
773
                i2c_addrs => [0x2c..0x2e],
 
774
                i2c_detect => sub { adm1026_detect(@_); },
 
775
        }, {
 
776
                name => "Analog Devices ADM1025",
 
777
                driver => "adm1025",
 
778
                i2c_addrs => [0x2c..0x2e],
 
779
                i2c_detect => sub { adm1025_detect(@_, 0); },
 
780
        }, {
 
781
                name => "Philips NE1619",
 
782
                driver => "adm1025",
 
783
                i2c_addrs => [0x2c..0x2d],
 
784
                i2c_detect => sub { adm1025_detect(@_, 1); },
 
785
        }, {
 
786
                name => "Analog Devices ADM1021",
 
787
                driver => "adm1021",
 
788
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
789
                i2c_detect => sub { adm1021_detect(@_, 0); },
 
790
        }, {
 
791
                name => "Analog Devices ADM1021A/ADM1023",
 
792
                driver => "adm1021",
 
793
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
794
                i2c_detect => sub { adm1021_detect(@_, 1); },
 
795
        }, {
 
796
                name => "Maxim MAX1617",
 
797
                driver => "adm1021",
 
798
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
799
                i2c_detect => sub { adm1021_detect(@_, 2); },
 
800
        }, {
 
801
                name => "Maxim MAX1617A",
 
802
                driver => "adm1021",
 
803
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
804
                i2c_detect => sub { adm1021_detect(@_, 3); },
 
805
        }, {
 
806
                name => "Maxim MAX1668",
 
807
                driver => "max1668",
 
808
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
809
                i2c_detect => sub { max1668_detect(@_, 0); },
 
810
        }, {
 
811
                name => "Maxim MAX1805",
 
812
                driver => "max1668",
 
813
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
814
                i2c_detect => sub { max1668_detect(@_, 1); },
 
815
        }, {
 
816
                name => "Maxim MAX1989",
 
817
                driver => "max1668",
 
818
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
819
                i2c_detect => sub { max1668_detect(@_, 2); },
 
820
        }, {
 
821
                name => "Maxim MAX6650/MAX6651",
 
822
                driver => "max6650",
 
823
                i2c_addrs => [0x1b, 0x1f, 0x48, 0x4b],
 
824
                i2c_detect => sub { max6650_detect(@_); },
 
825
        }, {
 
826
                name => "Maxim MAX6655/MAX6656",
 
827
                driver => "max6655",
 
828
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
829
                i2c_detect => sub { max6655_detect(@_); },
 
830
        }, {
 
831
                name => "TI THMC10",
 
832
                driver => "adm1021",
 
833
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
834
                i2c_detect => sub { adm1021_detect(@_, 4); },
 
835
        }, {
 
836
                name => "National Semiconductor LM84",
 
837
                driver => "adm1021",
 
838
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
839
                i2c_detect => sub { adm1021_detect(@_, 5); },
 
840
        }, {
 
841
                name => "Genesys Logic GL523SM",
 
842
                driver => "adm1021",
 
843
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
844
                i2c_detect => sub { adm1021_detect(@_, 6); },
 
845
        }, {
 
846
                name => "Onsemi MC1066",
 
847
                driver => "adm1021",
 
848
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
849
                i2c_detect => sub { adm1021_detect(@_, 7); },
 
850
        }, {
 
851
                name => "Maxim MAX1618",
 
852
                driver => "max1619",
 
853
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
854
                i2c_detect => sub { max1619_detect(@_, 1); },
 
855
        }, {
 
856
                name => "Maxim MAX1619",
 
857
                driver => "max1619",
 
858
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
859
                i2c_detect => sub { max1619_detect(@_, 0); },
 
860
        }, {
 
861
                name => "National Semiconductor LM82/LM83",
 
862
                driver => "lm83",
 
863
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
864
                i2c_detect => sub { lm83_detect(@_); },
 
865
        }, {
 
866
                name => "National Semiconductor LM90",
 
867
                driver => "lm90",
 
868
                i2c_addrs => [0x4c],
 
869
                i2c_detect => sub { lm90_detect(@_, 0); },
 
870
        }, {
 
871
                name => "National Semiconductor LM89/LM99",
 
872
                driver => "lm90",
 
873
                i2c_addrs => [0x4c..0x4d],
 
874
                i2c_detect => sub { lm90_detect(@_, 1); },
 
875
        }, {
 
876
                name => "National Semiconductor LM86",
 
877
                driver => "lm90",
 
878
                i2c_addrs => [0x4c],
 
879
                i2c_detect => sub { lm90_detect(@_, 2); },
 
880
        }, {
 
881
                name => "Analog Devices ADM1032",
 
882
                driver => "lm90",
 
883
                i2c_addrs => [0x4c..0x4d],
 
884
                i2c_detect => sub { lm90_detect(@_, 3); },
 
885
        }, {
 
886
                name => "Maxim MAX6654",
 
887
                driver => "to-be-written", # probably lm90
 
888
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
889
                i2c_detect => sub { lm90_detect(@_, 4); },
 
890
        }, {
 
891
                name => "Maxim MAX6690",
 
892
                driver => "to-be-written", # probably lm90
 
893
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
894
                i2c_detect => sub { lm90_detect(@_, 12); },
 
895
        }, {
 
896
                name => "Maxim MAX6657/MAX6658/MAX6659",
 
897
                driver => "lm90",
 
898
                i2c_addrs => [0x4c],
 
899
                i2c_detect => sub { max6657_detect(@_); },
 
900
        }, {
 
901
                name => "Maxim MAX6659",
 
902
                driver => "lm90",
 
903
                i2c_addrs => [0x4d..0x4e], # 0x4c is handled above
 
904
                i2c_detect => sub { max6657_detect(@_); },
 
905
        }, {
 
906
                name => "Maxim MAX6646",
 
907
                driver => "lm90",
 
908
                i2c_addrs => [0x4d],
 
909
                i2c_detect => sub { lm90_detect(@_, 6); },
 
910
        }, {
 
911
                name => "Maxim MAX6647",
 
912
                driver => "lm90",
 
913
                i2c_addrs => [0x4e],
 
914
                i2c_detect => sub { lm90_detect(@_, 6); },
 
915
        }, {
 
916
                name => "Maxim MAX6648/MAX6649/MAX6692",
 
917
                driver => "lm90",
 
918
                i2c_addrs => [0x4c],
 
919
                i2c_detect => sub { lm90_detect(@_, 6); },
 
920
        }, {
 
921
                name => "Maxim MAX6680/MAX6681",
 
922
                driver => "lm90",
 
923
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
924
                i2c_detect => sub { max6680_95_detect(@_, 0); },
 
925
        }, {
 
926
                name => "Maxim MAX6695/MAX6696",
 
927
                driver => "lm90",
 
928
                i2c_addrs => [0x18..0x1a, 0x29..0x2b, 0x4c..0x4e],
 
929
                i2c_detect => sub { max6680_95_detect(@_, 1); },
 
930
        }, {
 
931
                name => "Winbond W83L771W/G",
 
932
                driver => "to-be-written",
 
933
                i2c_addrs => [0x4c],
 
934
                i2c_detect => sub { lm90_detect(@_, 8); },
 
935
        }, {
 
936
                name => "Winbond W83L771AWG/ASG",
 
937
                driver => "lm90",
 
938
                i2c_addrs => [0x4c],
 
939
                i2c_detect => sub { lm90_detect(@_, 11); },
 
940
        }, {
 
941
                name => "Texas Instruments TMP401",
 
942
                driver => "tmp401",
 
943
                i2c_addrs => [0x4c],
 
944
                i2c_detect => sub { lm90_detect(@_, 9); },
 
945
        }, {
 
946
                name => "Texas Instruments TMP411",
 
947
                driver => "tmp401",
 
948
                i2c_addrs => [0x4c..0x4e],
 
949
                i2c_detect => sub { lm90_detect(@_, 10); },
 
950
        }, {
 
951
                name => "Texas Instruments TMP421",
 
952
                driver => "tmp421",
 
953
                i2c_addrs => [0x2a, 0x4c..0x4f], # 0x1c-0x1f not probed.
 
954
                i2c_detect => sub { tmp42x_detect(@_, 0); },
 
955
        }, {
 
956
                name => "Texas Instruments TMP422",
 
957
                driver => "tmp421",
 
958
                i2c_addrs => [0x4c..0x4f],
 
959
                i2c_detect => sub { tmp42x_detect(@_, 1); },
 
960
        }, {
 
961
                name => "Texas Instruments TMP423",
 
962
                driver => "tmp421",
 
963
                i2c_addrs => [0x4c, 0x4d],
 
964
                i2c_detect => sub { tmp42x_detect(@_, 2); },
 
965
        }, {
 
966
                name => "Texas Instruments AMC6821",
 
967
                driver => "amc6821",
 
968
                i2c_addrs => [0x18..0x1a, 0x2c..0x2e, 0x4c..0x4e],
 
969
                i2c_detect => sub { amc6821_detect(@_); },
 
970
        }, {
 
971
                name => "National Semiconductor LM95231",
 
972
                driver => "to-be-written",
 
973
                i2c_addrs => [0x2b, 0x19, 0x2a],
 
974
                i2c_detect => sub { lm95231_detect(@_, 0); },
 
975
        }, {
 
976
                name => "National Semiconductor LM95241",
 
977
                driver => "lm95241",
 
978
                i2c_addrs => [0x2b, 0x19, 0x2a],
 
979
                i2c_detect => sub { lm95231_detect(@_, 1); },
 
980
        }, {
 
981
                name => "National Semiconductor LM63",
 
982
                driver => "lm63",
 
983
                i2c_addrs => [0x4c],
 
984
                i2c_detect => sub { lm63_detect(@_, 1); },
 
985
        }, {
 
986
                name => "National Semiconductor LM64",
 
987
                driver => "lm63",
 
988
                i2c_addrs => [0x18, 0x4e],
 
989
                i2c_detect => sub { lm63_detect(@_, 3); },
 
990
        }, {
 
991
                name => "Fintek F75363SG",
 
992
                driver => "lm63", # Not yet
 
993
                i2c_addrs => [0x4c],
 
994
                i2c_detect => sub { lm63_detect(@_, 2); },
 
995
        }, {
 
996
                name => "National Semiconductor LM73",
 
997
                driver => "lm73",
 
998
                i2c_addrs => [0x48..0x4a, 0x4c..0x4e],
 
999
                i2c_detect => sub { lm73_detect(@_); },
 
1000
        }, {
 
1001
                name => "National Semiconductor LM92",
 
1002
                driver => "lm92",
 
1003
                i2c_addrs => [0x48..0x4b],
 
1004
                i2c_detect => sub { lm92_detect(@_, 0); },
 
1005
        }, {
 
1006
                name => "National Semiconductor LM76",
 
1007
                driver => "lm92",
 
1008
                i2c_addrs => [0x48..0x4b],
 
1009
                i2c_detect => sub { lm92_detect(@_, 1); },
 
1010
        }, {
 
1011
                name => "Maxim MAX6633/MAX6634/MAX6635",
 
1012
                driver => "lm92",
 
1013
                i2c_addrs => [0x48..0x4f], # The MAX6633 can also use 0x40-0x47 but we
 
1014
                                           # don't want to probe these addresses, it's
 
1015
                                           # dangerous.
 
1016
                i2c_detect => sub { lm92_detect(@_, 2); },
 
1017
        }, {
 
1018
                name => "Analog Devices ADT7461",
 
1019
                driver => "lm90",
 
1020
                i2c_addrs => [0x4c..0x4d],
 
1021
                i2c_detect => sub { lm90_detect(@_, 5); },
 
1022
        }, {
 
1023
                name => "Analog Devices ADT7481",
 
1024
                driver => "to-be-written",
 
1025
                i2c_addrs => [0x4c, 0x4b],
 
1026
                i2c_detect => sub { adt7481_detect(@_); },
 
1027
        }, {
 
1028
                name => "Analog Devices ADM1029",
 
1029
                driver => "adm1029",
 
1030
                i2c_addrs => [0x28..0x2f],
 
1031
                i2c_detect => sub { adm1029_detect(@_); },
 
1032
        }, {
 
1033
                name => "Analog Devices ADM1030",
 
1034
                driver => "adm1031",
 
1035
                i2c_addrs => [0x2c..0x2e],
 
1036
                i2c_detect => sub { adm1031_detect(@_, 0); },
 
1037
        }, {
 
1038
                name => "Analog Devices ADM1031",
 
1039
                driver => "adm1031",
 
1040
                i2c_addrs => [0x2c..0x2e],
 
1041
                i2c_detect => sub { adm1031_detect(@_, 1); },
 
1042
        }, {
 
1043
                name => "Analog Devices ADM1033",
 
1044
                driver => "to-be-written",
 
1045
                i2c_addrs => [0x50..0x53],
 
1046
                i2c_detect => sub { adm1034_detect(@_, 0); },
 
1047
        }, {
 
1048
                name => "Analog Devices ADM1034",
 
1049
                driver => "to-be-written",
 
1050
                i2c_addrs => [0x50..0x53],
 
1051
                i2c_detect => sub { adm1034_detect(@_, 1); },
 
1052
        }, {
 
1053
                name => "Analog Devices ADM1022",
 
1054
                driver => "thmc50",
 
1055
                i2c_addrs => [0x2c..0x2e],
 
1056
                i2c_detect => sub { adm1022_detect(@_, 0); },
 
1057
        }, {
 
1058
                name => "Texas Instruments THMC50",
 
1059
                driver => "thmc50",
 
1060
                i2c_addrs => [0x2c..0x2e],
 
1061
                i2c_detect => sub { adm1022_detect(@_, 1); },
 
1062
        }, {
 
1063
                name => "Analog Devices ADM1028",
 
1064
                driver => "thmc50",
 
1065
                i2c_addrs => [0x2e],
 
1066
                i2c_detect => sub { adm1022_detect(@_, 2); },
 
1067
        }, {
 
1068
                name => "Texas Instruments THMC51",
 
1069
                driver => "to-be-written", # thmc50
 
1070
                i2c_addrs => [0x2e], # At least (no datasheet)
 
1071
                i2c_detect => sub { adm1022_detect(@_, 3); },
 
1072
        }, {
 
1073
                name => "VIA VT1211 (I2C)",
 
1074
                driver => "use-isa-instead",
 
1075
                i2c_addrs => [0x2d],
 
1076
                i2c_detect => sub { vt1211_i2c_detect(@_); },
 
1077
        }, {
 
1078
                name => "ITE IT8712F",
 
1079
                driver => "it87",
 
1080
                i2c_addrs => [0x28..0x2f],
 
1081
                i2c_detect => sub { it8712_i2c_detect(@_); },
 
1082
        }, {
 
1083
                name => "FSC Poseidon I",
 
1084
                driver => sub { kernel_version_at_least(2, 6, 24) ? "fschmd" : "fscpos" },
 
1085
                i2c_addrs => [0x73],
 
1086
                i2c_detect => sub { fsc_detect(@_, 0); },
 
1087
        }, {
 
1088
                name => "FSC Poseidon II",
 
1089
                driver => "to-be-written",
 
1090
                i2c_addrs => [0x73],
 
1091
                i2c_detect => sub { fsc_detect(@_, 1); },
 
1092
        }, {
 
1093
                name => "FSC Scylla",
 
1094
                driver => "fschmd",
 
1095
                i2c_addrs => [0x73],
 
1096
                i2c_detect => sub { fsc_detect(@_, 2); },
 
1097
        }, {
 
1098
                name => "FSC Hermes",
 
1099
                driver => sub { kernel_version_at_least(2, 6, 24) ? "fschmd" : "fscher" },
 
1100
                i2c_addrs => [0x73],
 
1101
                i2c_detect => sub { fsc_detect(@_, 3); },
 
1102
        }, {
 
1103
                name => "FSC Heimdal",
 
1104
                driver => "fschmd",
 
1105
                i2c_addrs => [0x73],
 
1106
                i2c_detect => sub { fsc_detect(@_, 4); },
 
1107
        }, {
 
1108
                name => "FSC Heracles",
 
1109
                driver => "fschmd",
 
1110
                i2c_addrs => [0x73],
 
1111
                i2c_detect => sub { fsc_detect(@_, 5); },
 
1112
        }, {
 
1113
                name => "FSC Hades",
 
1114
                driver => "fschmd",
 
1115
                i2c_addrs => [0x73],
 
1116
                i2c_detect => sub { fsc_detect(@_, 6); },
 
1117
        }, {
 
1118
                name => "FSC Syleus",
 
1119
                driver => "fschmd",
 
1120
                i2c_addrs => [0x73],
 
1121
                i2c_detect => sub { fsc_detect(@_, 7); },
 
1122
        }, {
 
1123
                name => "ALi M5879",
 
1124
                driver => "to-be-written",
 
1125
                i2c_addrs => [0x2c..0x2d],
 
1126
                i2c_detect => sub { m5879_detect(@_); },
 
1127
        }, {
 
1128
                name => "SMSC LPC47M15x/192/292/997",
 
1129
                driver => "smsc47m192",
 
1130
                i2c_addrs => [0x2c..0x2d],
 
1131
                i2c_detect => sub { smsc47m192_detect(@_); },
 
1132
        }, {
 
1133
                name => "SMSC DME1737",
 
1134
                driver => "dme1737",
 
1135
                i2c_addrs => [0x2c..0x2e],
 
1136
                i2c_detect => sub { dme1737_detect(@_, 1); },
 
1137
        }, {
 
1138
                name => "SMSC SCH5027D-NW",
 
1139
                driver => "dme1737",
 
1140
                i2c_addrs => [0x2c..0x2e],
 
1141
                i2c_detect => sub { dme1737_detect(@_, 2); },
 
1142
        }, {
 
1143
                name => "SMSC EMC2103",
 
1144
                driver => "emc2103",
 
1145
                i2c_addrs => [0x2e],
 
1146
                i2c_detect => sub { emc1403_detect(@_, 2); },
 
1147
        }, {
 
1148
                name => "Fintek F75121R/F75122R/RG (VID+GPIO)",
 
1149
                driver => "to-be-written",
 
1150
                i2c_addrs => [0x4e], # 0x37 not probed
 
1151
                i2c_detect => sub { fintek_detect(@_, 2); },
 
1152
        }, {
 
1153
                name => "Fintek F75373S/SG",
 
1154
                driver => "f75375s",
 
1155
                i2c_addrs => [0x2d..0x2e],
 
1156
                i2c_detect => sub { fintek_detect(@_, 3); },
 
1157
        }, {
 
1158
                name => "Fintek F75375S/SP",
 
1159
                driver => "f75375s",
 
1160
                i2c_addrs => [0x2d..0x2e],
 
1161
                i2c_detect => sub { fintek_detect(@_, 4); },
 
1162
        }, {
 
1163
                name => "Fintek F75387SG/RG",
 
1164
                driver => "to-be-written",
 
1165
                i2c_addrs => [0x2d..0x2e],
 
1166
                i2c_detect => sub { fintek_detect(@_, 5); },
 
1167
        }, {
 
1168
                name => "Fintek F75383S/M",
 
1169
                driver => "to-be-written",
 
1170
                i2c_addrs => [0x4c],
 
1171
                i2c_detect => sub { fintek_detect(@_, 6); },
 
1172
        }, {
 
1173
                name => "Fintek F75384S/M",
 
1174
                driver => "to-be-written",
 
1175
                i2c_addrs => [0x4d],
 
1176
                i2c_detect => sub { fintek_detect(@_, 6); },
 
1177
        }, {
 
1178
                name => "Fintek custom power control IC",
 
1179
                driver => "to-be-written",
 
1180
                i2c_addrs => [0x2f],
 
1181
                i2c_detect => sub { fintek_detect(@_, 7); },
 
1182
        }, {
 
1183
                name => "SMSC EMC1403",
 
1184
                driver => "emc1403",
 
1185
                i2c_addrs => [0x18, 0x2a, 0x4c, 0x4d],
 
1186
                i2c_detect => sub { emc1403_detect(@_, 0); },
 
1187
        }, {
 
1188
                name => "SMSC EMC1404",
 
1189
                driver => "to-be-written", # emc1403
 
1190
                i2c_addrs => [0x18, 0x2a, 0x4c, 0x4d],
 
1191
                i2c_detect => sub { emc1403_detect(@_, 1); },
 
1192
        }, {
 
1193
                name => "ST STTS424",
 
1194
                driver => "jc42",
 
1195
                i2c_addrs => [0x18..0x1f],
 
1196
                i2c_detect => sub { jedec_JC42_4_detect(@_, 0); },
 
1197
        }, {
 
1198
                name => "ST STTS424E",
 
1199
                driver => "jc42",
 
1200
                i2c_addrs => [0x18..0x1f],
 
1201
                i2c_detect => sub { jedec_JC42_4_detect(@_, 10); },
 
1202
        }, {
 
1203
                name => "NXP SE97/SE97B",
 
1204
                driver => "jc42",
 
1205
                i2c_addrs => [0x18..0x1f],
 
1206
                i2c_detect => sub { jedec_JC42_4_detect(@_, 1); },
 
1207
        }, {
 
1208
                name => "NXP SE98",
 
1209
                driver => "jc42",
 
1210
                i2c_addrs => [0x18..0x1f],
 
1211
                i2c_detect => sub { jedec_JC42_4_detect(@_, 2); },
 
1212
        }, {
 
1213
                name => "Analog Devices ADT7408",
 
1214
                driver => "jc42",
 
1215
                i2c_addrs => [0x18..0x1f],
 
1216
                i2c_detect => sub { jedec_JC42_4_detect(@_, 3); },
 
1217
        }, {
 
1218
                name => "IDT TS3000/TSE2002",
 
1219
                driver => "jc42",
 
1220
                i2c_addrs => [0x18..0x1f],
 
1221
                i2c_detect => sub { jedec_JC42_4_detect(@_, 4); },
 
1222
        }, {
 
1223
                name => "Maxim MAX6604",
 
1224
                driver => "jc42",
 
1225
                i2c_addrs => [0x18..0x1f],
 
1226
                i2c_detect => sub { jedec_JC42_4_detect(@_, 5); },
 
1227
        }, {
 
1228
                name => "Microchip MCP98242",
 
1229
                driver => "jc42",
 
1230
                i2c_addrs => [0x18..0x1f],
 
1231
                i2c_detect => sub { jedec_JC42_4_detect(@_, 6); },
 
1232
        }, {
 
1233
                name => "Microchip MCP98243",
 
1234
                driver => "jc42",
 
1235
                i2c_addrs => [0x18..0x1f],
 
1236
                i2c_detect => sub { jedec_JC42_4_detect(@_, 7); },
 
1237
        }, {
 
1238
                name => "Microchip MCP9843",
 
1239
                driver => "jc42",
 
1240
                i2c_addrs => [0x18..0x1f],
 
1241
                i2c_detect => sub { jedec_JC42_4_detect(@_, 8); },
 
1242
        }, {
 
1243
                name => "ON CAT6095/CAT34TS02",
 
1244
                driver => "jc42",
 
1245
                i2c_addrs => [0x18..0x1f],
 
1246
                i2c_detect => sub { jedec_JC42_4_detect(@_, 9); },
 
1247
        }, {
 
1248
                name => "Smart Battery",
 
1249
                driver => "sbs", # ACPI driver, not sure if it always works
 
1250
                i2c_addrs => [0x0b],
 
1251
                i2c_detect => sub { smartbatt_detect(@_); },
 
1252
        }
 
1253
);
 
1254
 
 
1255
# IPMI interfaces have their own array now
 
1256
@ipmi_ifs = (
 
1257
        {
 
1258
                name => "IPMI BMC KCS",
 
1259
                driver => "ipmisensors",
 
1260
                isa_addrs => [0x0ca0],
 
1261
                isa_detect => sub { ipmi_detect(@_); },
 
1262
        }, {
 
1263
                name => "IPMI BMC SMIC",
 
1264
                driver => "ipmisensors",
 
1265
                isa_addrs => [0x0ca8],
 
1266
                isa_detect => sub { ipmi_detect(@_); },
 
1267
        }
 
1268
);
 
1269
 
 
1270
# Here is a similar list, but for devices which are not hardware monitoring
 
1271
# chips. We only list popular devices which happen to live at the same I2C
 
1272
# address as recognized hardware monitoring chips. The idea is to make it
 
1273
# clear that the chip in question is of no interest for lm-sensors.
 
1274
@non_hwmon_chip_ids = (
 
1275
        {
 
1276
                name => "Winbond W83791SD",
 
1277
                i2c_addrs => [0x2c..0x2f],
 
1278
                i2c_detect => sub { w83791sd_detect(@_); },
 
1279
        }, {
 
1280
                name => "Fintek F75111R/RG/N (GPIO)",
 
1281
                i2c_addrs => [0x37, 0x4e],
 
1282
                i2c_detect => sub { fintek_detect(@_, 1); },
 
1283
        }, {
 
1284
                name => "ITE IT8201R/IT8203R/IT8206R/IT8266R",
 
1285
                i2c_addrs => [0x4e],
 
1286
                i2c_detect => sub { ite_overclock_detect(@_); },
 
1287
        }, {
 
1288
                name => "SPD EEPROM",
 
1289
                i2c_addrs => [0x50..0x57],
 
1290
                i2c_detect => sub { eeprom_detect(@_); },
 
1291
        }, {
 
1292
                name => "EDID EEPROM",
 
1293
                i2c_addrs => [0x50],
 
1294
                i2c_detect => sub { ddcmonitor_detect(@_); },
 
1295
        }
 
1296
);
 
1297
 
 
1298
# This is a list of all recognized superio chips.
 
1299
# Each entry must have the following fields:
 
1300
#  name: The full chip name
 
1301
#  driver: The driver name. Put in exactly:
 
1302
#      * "to-be-written" if it is not yet available
 
1303
#      * "not-a-sensor" if the chip doesn't have hardware monitoring
 
1304
#        capabilities (listing such chips here removes the need of manual
 
1305
#        lookup when people report them)
 
1306
#      * "via-smbus-only" if this is a Super-I/O chip whose hardware
 
1307
#        monitoring registers can only be accessed via the SMBus
 
1308
#  devid: The device ID we have to match (base device)
 
1309
#  devid_mask (optional): Bitmask to apply before checking the device ID
 
1310
#  logdev: The logical device containing the sensors
 
1311
#  check (optional): A function to refine the detection. Will be passed
 
1312
#      the index and data ports as parameters. Must return 1 for a matching
 
1313
#      device, 0 otherwise.
 
1314
#  features (optional): Features supported by this device, amongst:
 
1315
#      * FEAT_IN
 
1316
#      * FEAT_FAN
 
1317
#      * FEAT_TEMP
 
1318
use vars qw(@superio_ids_natsemi @superio_ids_smsc @superio_ids_smsc_ns
 
1319
            @superio_ids_winbond @superio_ids_ite @superio_ids);
 
1320
 
 
1321
use constant FEAT_IN    => (1 << 0);
 
1322
use constant FEAT_FAN   => (1 << 1);
 
1323
use constant FEAT_TEMP  => (1 << 2);
 
1324
use constant FEAT_SMBUS => (1 << 7);
 
1325
 
 
1326
@superio_ids_natsemi = (
 
1327
        {
 
1328
                name => "Nat. Semi. PC8374L Super IO Sensors",  # Also Nuvoton WPCD374L
 
1329
                driver => "to-be-written",
 
1330
                devid => 0xf1,
 
1331
                check => sub {
 
1332
                        outb($_[0], 0x27);
 
1333
                        # Guess work; seen so far: 0x11
 
1334
                        return (inb($_[1]) < 0x80);
 
1335
                },
 
1336
                logdev => 0x08,
 
1337
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1338
        }, {
 
1339
                name => "Nuvoton WPCD377I Super IO",    # Also WPCD376I
 
1340
                driver => "not-a-sensor",
 
1341
                devid => 0xf1,
 
1342
                check => sub {
 
1343
                        outb($_[0], 0x27);
 
1344
                        # Guess work; seen so far: 0x91 (twice)
 
1345
                        return (inb($_[1]) >= 0x80);
 
1346
                },
 
1347
        }, {
 
1348
                name => "Nat. Semi. PC87351 Super IO Fan Sensors",
 
1349
                driver => "to-be-written",
 
1350
                devid => 0xe2,
 
1351
                logdev => 0x08,
 
1352
        }, {
 
1353
                name => "Nat. Semi. PC87360 Super IO Fan Sensors",
 
1354
                driver => "pc87360",
 
1355
                devid => 0xe1,
 
1356
                logdev => 0x09,
 
1357
                features => FEAT_FAN,
 
1358
        }, {
 
1359
                name => "Nat. Semi. PC87363 Super IO Fan Sensors",
 
1360
                driver => "pc87360",
 
1361
                devid => 0xe8,
 
1362
                logdev => 0x09,
 
1363
                features => FEAT_FAN,
 
1364
        }, {
 
1365
                name => "Nat. Semi. PC87364 Super IO Fan Sensors",
 
1366
                driver => "pc87360",
 
1367
                devid => 0xe4,
 
1368
                logdev => 0x09,
 
1369
                features => FEAT_FAN,
 
1370
        }, {
 
1371
                name => "Nat. Semi. PC87365 Super IO Fan Sensors",
 
1372
                driver => "pc87360",
 
1373
                devid => 0xe5,
 
1374
                logdev => 0x09,
 
1375
                features => FEAT_FAN,
 
1376
        }, {
 
1377
                name => "Nat. Semi. PC87365 Super IO Voltage Sensors",
 
1378
                driver => "pc87360",
 
1379
                devid => 0xe5,
 
1380
                logdev => 0x0d,
 
1381
                features => FEAT_IN,
 
1382
        }, {
 
1383
                name => "Nat. Semi. PC87365 Super IO Thermal Sensors",
 
1384
                driver => "pc87360",
 
1385
                devid => 0xe5,
 
1386
                logdev => 0x0e,
 
1387
                features => FEAT_TEMP,
 
1388
        }, {
 
1389
                name => "Nat. Semi. PC87366 Super IO Fan Sensors",
 
1390
                driver => "pc87360",
 
1391
                devid => 0xe9,
 
1392
                logdev => 0x09,
 
1393
                features => FEAT_FAN,
 
1394
        }, {
 
1395
                name => "Nat. Semi. PC87366 Super IO Voltage Sensors",
 
1396
                driver => "pc87360",
 
1397
                devid => 0xe9,
 
1398
                logdev => 0x0d,
 
1399
                features => FEAT_IN,
 
1400
        }, {
 
1401
                name => "Nat. Semi. PC87366 Super IO Thermal Sensors",
 
1402
                driver => "pc87360",
 
1403
                devid => 0xe9,
 
1404
                logdev => 0x0e,
 
1405
                features => FEAT_TEMP,
 
1406
        }, {
 
1407
                name => "Nat. Semi. PC87372 Super IO Fan Sensors",
 
1408
                driver => "to-be-written",
 
1409
                devid => 0xf0,
 
1410
                logdev => 0x09,
 
1411
                features => FEAT_FAN,
 
1412
        }, {
 
1413
                name => "Nat. Semi. PC87373 Super IO Fan Sensors",
 
1414
                driver => "to-be-written",
 
1415
                devid => 0xf3,
 
1416
                logdev => 0x09,
 
1417
                features => FEAT_FAN,
 
1418
        }, {
 
1419
                name => "Nat. Semi. PC87591 Super IO",
 
1420
                driver => "to-be-written",
 
1421
                devid => 0xec,
 
1422
                logdev => 0x0f,
 
1423
        }, {
 
1424
                name => "Nat. Semi. PC87317 Super IO",
 
1425
                driver => "not-a-sensor",
 
1426
                devid => 0xd0,
 
1427
        }, {
 
1428
                name => "Nat. Semi. PC97317 Super IO",
 
1429
                driver => "not-a-sensor",
 
1430
                devid => 0xdf,
 
1431
        }, {
 
1432
                name => "Nat. Semi. PC8739x Super IO",
 
1433
                driver => "not-a-sensor",
 
1434
                devid => 0xea,
 
1435
        }, {
 
1436
                name => "Nat. Semi. PC8741x Super IO",
 
1437
                driver => "not-a-sensor",
 
1438
                devid => 0xee,
 
1439
        }, {
 
1440
                name => "Nat. Semi. PC87427 Super IO Fan Sensors",
 
1441
                driver => "pc87427",
 
1442
                devid => 0xf2,
 
1443
                logdev => 0x09,
 
1444
                features => FEAT_FAN,
 
1445
        }, {
 
1446
                name => "Nat. Semi. PC87427 Super IO Health Sensors",
 
1447
                driver => "to-be-written",
 
1448
                devid => 0xf2,
 
1449
                logdev => 0x14,
 
1450
                features => FEAT_IN | FEAT_TEMP,
 
1451
        }, {
 
1452
                # Shouldn't be in this family, but there it is
 
1453
                name => "ITE IT8512E/F Super IO",
 
1454
                driver => "not-a-sensor",
 
1455
                devid => 0x8512,
 
1456
        }
 
1457
);
 
1458
 
 
1459
@superio_ids_smsc = (
 
1460
        {
 
1461
                name => "SMSC DME1737 Super IO",
 
1462
                # Hardware monitoring features are accessed on the SMBus
 
1463
                driver => "via-smbus-only",
 
1464
                devid => 0x78,
 
1465
        }, {
 
1466
                name => "SMSC DME1737 Super IO",
 
1467
                # The DME1737 shows up twice in this list because it can return either
 
1468
                # 0x78 or 0x77 as its device ID.
 
1469
                # Hardware monitoring features are accessed on the SMBus
 
1470
                driver => "via-smbus-only",
 
1471
                devid => 0x77,
 
1472
        }, {
 
1473
                name => "SMSC EMC2700LPC Super IO",
 
1474
                # no datasheet
 
1475
                devid => 0x67,
 
1476
        }, {
 
1477
                name => "SMSC FDC37B72x Super IO",
 
1478
                driver => "not-a-sensor",
 
1479
                devid => 0x4c,
 
1480
        }, {
 
1481
                name => "SMSC FDC37B78x Super IO",
 
1482
                driver => "not-a-sensor",
 
1483
                devid => 0x44,
 
1484
        }, {
 
1485
                name => "SMSC FDC37C672 Super IO",
 
1486
                driver => "not-a-sensor",
 
1487
                devid => 0x40,
 
1488
        }, {
 
1489
                name => "SMSC FDC37M707 Super IO",
 
1490
                driver => "not-a-sensor",
 
1491
                devid => 0x42,
 
1492
        }, {
 
1493
                name => "SMSC FDC37M81x Super IO",
 
1494
                driver => "not-a-sensor",
 
1495
                devid => 0x4d,
 
1496
        }, {
 
1497
                name => "SMSC LPC47B27x Super IO Fan Sensors",
 
1498
                driver => "smsc47m1",
 
1499
                devid => 0x51,
 
1500
                logdev => 0x0a,
 
1501
                features => FEAT_FAN,
 
1502
        }, {
 
1503
                name => "SMSC LPC47B34x Super IO",
 
1504
                driver => "not-a-sensor",
 
1505
                devid => 0x56,
 
1506
        }, {
 
1507
                name => "SMSC LPC47B357/M967 Super IO",
 
1508
                driver => "not-a-sensor",
 
1509
                devid => 0x5d,
 
1510
        }, {
 
1511
                name => "SMSC LPC47B367-NC Super IO",
 
1512
                driver => "not-a-sensor",
 
1513
                devid => 0x6d,
 
1514
        }, {
 
1515
                name => "SMSC LPC47B37x Super IO Fan Sensors",
 
1516
                driver => "to-be-written",
 
1517
                devid => 0x52,
 
1518
                logdev => 0x0a,
 
1519
                features => FEAT_FAN,
 
1520
        }, {
 
1521
                name => "SMSC LPC47B397-NC Super IO",
 
1522
                driver => "smsc47b397",
 
1523
                devid => 0x6f,
 
1524
                logdev => 0x08,
 
1525
                features => FEAT_FAN | FEAT_TEMP,
 
1526
        }, {
 
1527
                name => "SMSC LPC47M10x/112/13x Super IO Fan Sensors",
 
1528
                driver => "smsc47m1",
 
1529
                devid => 0x59,
 
1530
                logdev => 0x0a,
 
1531
                features => FEAT_FAN,
 
1532
        }, {
 
1533
                name => "SMSC LPC47M14x Super IO Fan Sensors",
 
1534
                driver => "smsc47m1",
 
1535
                devid => 0x5f,
 
1536
                logdev => 0x0a,
 
1537
                features => FEAT_FAN,
 
1538
        }, {
 
1539
                name => "SMSC LPC47M15x/192/997 Super IO Fan Sensors",
 
1540
                driver => "smsc47m1",
 
1541
                devid => 0x60,
 
1542
                logdev => 0x0a,
 
1543
                features => FEAT_FAN,
 
1544
        }, {
 
1545
                name => "SMSC LPC47M172 Super IO Fan Sensors",
 
1546
                driver => "to-be-written",
 
1547
                devid => 0x14,
 
1548
                logdev => 0x0a,
 
1549
                features => FEAT_FAN,
 
1550
        }, {
 
1551
                name => "SMSC LPC47M182 Super IO Fan Sensors",
 
1552
                driver => "to-be-written",
 
1553
                devid => 0x74,
 
1554
                logdev => 0x0a,
 
1555
                features => FEAT_FAN,
 
1556
        }, {
 
1557
                name => "SMSC LPC47M233 Super IO Sensors",
 
1558
                driver => "to-be-written",
 
1559
                devid => 0x6b80,
 
1560
                devid_mask => 0xff80,
 
1561
                logdev => 0x0a,
 
1562
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1563
        }, {
 
1564
                name => "SMSC LPC47M292 Super IO Fan Sensors",
 
1565
                driver => "smsc47m1",
 
1566
                devid => 0x6b00,
 
1567
                devid_mask => 0xff80,
 
1568
                logdev => 0x0a,
 
1569
                features => FEAT_FAN,
 
1570
        }, {
 
1571
                name => "SMSC LPC47M584-NC Super IO",
 
1572
                # No datasheet
 
1573
                devid => 0x76,
 
1574
        }, {
 
1575
                name => "SMSC LPC47N252 Super IO Fan Sensors",
 
1576
                driver => "to-be-written",
 
1577
                devid => 0x0e,
 
1578
                logdev => 0x09,
 
1579
                features => FEAT_FAN,
 
1580
        }, {
 
1581
                name => "SMSC LPC47S42x Super IO Fan Sensors",
 
1582
                driver => "to-be-written",
 
1583
                devid => 0x57,
 
1584
                logdev => 0x0a,
 
1585
                features => FEAT_FAN,
 
1586
        }, {
 
1587
                name => "SMSC LPC47S45x Super IO Fan Sensors",
 
1588
                driver => "to-be-written",
 
1589
                devid => 0x62,
 
1590
                logdev => 0x0a,
 
1591
                features => FEAT_FAN,
 
1592
        }, {
 
1593
                name => "SMSC LPC47U32x Super IO Fan Sensors",
 
1594
                driver => "to-be-written",
 
1595
                devid => 0x58,
 
1596
                logdev => 0x0a,
 
1597
                features => FEAT_FAN,
 
1598
        }, {
 
1599
                name => "SMSC LPC47U33x Super IO Fan Sensors",
 
1600
                driver => "to-be-written",
 
1601
                devid => 0x54,
 
1602
                logdev => 0x0a,
 
1603
                features => FEAT_FAN,
 
1604
        }, {
 
1605
                name => "SMSC SCH3112 Super IO",
 
1606
                driver => "dme1737",
 
1607
                devid => 0x7c,
 
1608
                logdev => 0x0a,
 
1609
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1610
        }, {
 
1611
                name => "SMSC SCH3114 Super IO",
 
1612
                driver => "dme1737",
 
1613
                devid => 0x7d,
 
1614
                logdev => 0x0a,
 
1615
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1616
        }, {
 
1617
                name => "SMSC SCH3116 Super IO",
 
1618
                driver => "dme1737",
 
1619
                devid => 0x7f,
 
1620
                logdev => 0x0a,
 
1621
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1622
        }, {
 
1623
                name => "SMSC SCH4307 Super IO Fan Sensors",
 
1624
                driver => "to-be-written",
 
1625
                devid => 0x90,
 
1626
                logdev => 0x08,
 
1627
                features => FEAT_FAN,
 
1628
        }, {
 
1629
                name => "SMSC SCH5027D-NW Super IO",
 
1630
                # Hardware monitoring features are accessed on the SMBus
 
1631
                driver => "via-smbus-only",
 
1632
                devid => 0x89,
 
1633
        }, {
 
1634
                name => "SMSC SCH5127 Super IO",
 
1635
                driver => "dme1737",
 
1636
                devid => 0x86,
 
1637
                logdev => 0x0a,
 
1638
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1639
        }, {
 
1640
                name => "SMSC SCH5307-NS Super IO",
 
1641
                driver => "smsc47b397",
 
1642
                devid => 0x81,
 
1643
                logdev => 0x08,
 
1644
                features => FEAT_FAN | FEAT_TEMP,
 
1645
        }, {
 
1646
                name => "SMSC SCH5317 Super IO",
 
1647
                driver => "smsc47b397",
 
1648
                devid => 0x85,
 
1649
                logdev => 0x08,
 
1650
                features => FEAT_FAN | FEAT_TEMP,
 
1651
        }, {
 
1652
                name => "SMSC SCH5317 Super IO",
 
1653
                # The SCH5317 shows up twice in this list because it can return either
 
1654
                # 0x85 or 0x8c as its device ID.
 
1655
                driver => "smsc47b397",
 
1656
                devid => 0x8c,
 
1657
                logdev => 0x08,
 
1658
                features => FEAT_FAN | FEAT_TEMP,
 
1659
        }, {
 
1660
                name => "SMSC SCH5504-NS Super IO",
 
1661
                # No datasheet
 
1662
                driver => "not-a-sensor",
 
1663
                devid => 0x79,
 
1664
        }, {
 
1665
                name => "SMSC SCH5514D-NS Super IO",
 
1666
                # No datasheet
 
1667
                driver => "not-a-sensor",
 
1668
                devid => 0x83,
 
1669
        }
 
1670
);
 
1671
 
 
1672
# Non-standard SMSC chip list. These chips differ from the standard ones
 
1673
# listed above in that the device ID register address is 0x0d instead of
 
1674
# 0x20 (as specified by the ISA PNP spec).
 
1675
@superio_ids_smsc_ns = (
 
1676
        {
 
1677
                name => "SMSC FDC37C665 Super IO",
 
1678
                driver => "not-a-sensor",
 
1679
                devid => 0x65,
 
1680
        }, {
 
1681
                name => "SMSC FDC37C666 Super IO",
 
1682
                driver => "not-a-sensor",
 
1683
                devid => 0x66,
 
1684
        }, {
 
1685
                name => "SMSC FDC37C669 Super IO",
 
1686
                driver => "not-a-sensor",
 
1687
                devid => 0x03,
 
1688
        }, {
 
1689
                name => "SMSC FDC37N769 Super IO",
 
1690
                driver => "not-a-sensor",
 
1691
                devid => 0x28,
 
1692
        }, {
 
1693
                name => "SMSC LPC47N227 Super IO",
 
1694
                driver => "not-a-sensor",
 
1695
                devid => 0x5a,
 
1696
        }, {
 
1697
                name => "SMSC LPC47N237 Super IO",
 
1698
                driver => "not-a-sensor",
 
1699
                devid => 0x13,
 
1700
        }
 
1701
);
 
1702
 
 
1703
@superio_ids_winbond = (
 
1704
        {
 
1705
                name => "VIA VT1211 Super IO Sensors",
 
1706
                driver => "vt1211",
 
1707
                devid => 0x3c,
 
1708
                logdev => 0x0b,
 
1709
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1710
        }, {
 
1711
                name => "VIA VT1212 Super IO Lite",     # in 100 pin TQFP package
 
1712
                driver => "not-a-sensor",
 
1713
                devid => 0x3e,
 
1714
        }, {
 
1715
                name => "VIA VT1212 Super IO Lite",     # in 48 pin LQFP package
 
1716
                driver => "not-a-sensor",
 
1717
                devid => 0x3f,
 
1718
        }, {
 
1719
                name => "Winbond W83627HF/F/HG/G Super IO Sensors",
 
1720
                # Also SMSC LPC61W492
 
1721
                driver => "w83627hf",
 
1722
                devid => 0x52,
 
1723
                logdev => 0x0b,
 
1724
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1725
        }, {
 
1726
                name => "Winbond W83627THF/THG Super IO Sensors",
 
1727
                driver => "w83627hf",
 
1728
                devid => 0x82,
 
1729
                logdev => 0x0b,
 
1730
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1731
        }, {
 
1732
                name => "Winbond W83637HF/HG Super IO Sensors",
 
1733
                driver => "w83627hf",
 
1734
                devid => 0x70,
 
1735
                logdev => 0x0b,
 
1736
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1737
        }, {
 
1738
                name => "Winbond W83687THF Super IO Sensors",
 
1739
                driver => "w83627hf",
 
1740
                devid => 0x85,
 
1741
                logdev => 0x0b,
 
1742
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1743
        }, {
 
1744
                name => "Winbond W83697HF/F/HG Super IO Sensors",
 
1745
                driver => "w83627hf",
 
1746
                devid => 0x60,
 
1747
                logdev => 0x0b,
 
1748
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1749
        }, {
 
1750
                name => "Winbond W83697SF/UF/UG Super IO PWM",
 
1751
                driver => "to-be-written",
 
1752
                devid => 0x68,
 
1753
                logdev => 0x0b,
 
1754
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1755
        }, {
 
1756
                name => "Winbond W83627EHF/EF/EHG/EG Super IO Sensors",
 
1757
                driver => "w83627ehf",
 
1758
                # W83627EHF datasheet says 0x886x but 0x8853 was seen, thus the
 
1759
                # broader mask. W83627EHG was seen with ID 0x8863.
 
1760
                devid => 0x8840,
 
1761
                devid_mask => 0xFFC0,
 
1762
                logdev => 0x0b,
 
1763
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1764
        }, {
 
1765
                name => "Winbond W83627DHG Super IO Sensors",
 
1766
                driver => "w83627ehf",
 
1767
                devid => 0xA020,
 
1768
                devid_mask => 0xFFF0,
 
1769
                logdev => 0x0b,
 
1770
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1771
        }, {
 
1772
                name => "Winbond W83627DHG-P Super IO Sensors",
 
1773
                driver => "w83627ehf",
 
1774
                devid => 0xB070,
 
1775
                devid_mask => 0xFFF0,
 
1776
                logdev => 0x0b,
 
1777
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1778
        }, {
 
1779
                name => "Winbond W83627UHG Super IO Sensors",
 
1780
                driver => "to-be-written",
 
1781
                devid => 0xA230,
 
1782
                devid_mask => 0xFFF0,
 
1783
                logdev => 0x0b,
 
1784
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1785
        }, {
 
1786
                name => "Winbond W83667HG Super IO Sensors",
 
1787
                driver => "w83627ehf",
 
1788
                devid => 0xA510,
 
1789
                devid_mask => 0xFFF0,
 
1790
                logdev => 0x0b,
 
1791
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1792
        }, {
 
1793
                name => "Nuvoton W83667HG-B Super IO Sensors",
 
1794
                driver => "to-be-written",      # Probably w83627ehf
 
1795
                devid => 0xB350,
 
1796
                devid_mask => 0xFFF0,
 
1797
                logdev => 0x0b,
 
1798
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1799
        }, {
 
1800
                name => "Nuvoton W83677HG-I (NCT6771F/NCT6772F/NCT6775F) Super IO Sensors",
 
1801
                driver => "to-be-written",      # Probably w83627ehf
 
1802
                devid => 0xB470,
 
1803
                devid_mask => 0xFFF0,
 
1804
                logdev => 0x0b,
 
1805
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1806
        }, {
 
1807
                name => "Winbond W83L517D Super IO",
 
1808
                driver => "not-a-sensor",
 
1809
                devid => 0x61,
 
1810
        }, {
 
1811
                name => "Fintek F71805F/FG Super IO Sensors",
 
1812
                driver => "f71805f",
 
1813
                devid => 0x0406,
 
1814
                logdev => 0x04,
 
1815
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1816
        }, {
 
1817
                name => "Fintek F71808E Super IO Sensors",
 
1818
                driver => "f71882fg",
 
1819
                devid => 0x0901,
 
1820
                logdev => 0x04,
 
1821
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1822
        }, {
 
1823
                name => "Fintek F71862FG Super IO Sensors",
 
1824
                driver => "f71882fg",
 
1825
                devid => 0x0601,
 
1826
                logdev => 0x04,
 
1827
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1828
        }, {
 
1829
                name => "Fintek F71869FG Super IO Sensors",
 
1830
                driver => "to-be-written",
 
1831
                devid => 0x0814,
 
1832
                logdev => 0x04,
 
1833
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1834
        }, {
 
1835
                name => "Fintek F71806FG/F71872FG Super IO Sensors",
 
1836
                driver => "f71805f",
 
1837
                devid => 0x0341,
 
1838
                logdev => 0x04,
 
1839
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1840
        }, {
 
1841
                name => "Fintek F71858DG Super IO Sensors",
 
1842
                driver => "f71882fg",
 
1843
                devid => 0x0507,
 
1844
                logdev => 0x02,
 
1845
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1846
        }, {
 
1847
                name => "Fintek F71882FG/F71883FG Super IO Sensors",
 
1848
                driver => "f71882fg",
 
1849
                devid => 0x0541,
 
1850
                logdev => 0x04,
 
1851
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1852
        }, {
 
1853
                name => "Fintek F71889FG Super IO Sensors",
 
1854
                driver => "f71882fg",
 
1855
                devid => 0x0723,
 
1856
                logdev => 0x04,
 
1857
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1858
        }, {
 
1859
                name => "Fintek F71889E Super IO Sensors",
 
1860
                driver => "to-be-written",
 
1861
                devid => 0x0909,
 
1862
                logdev => 0x04,
 
1863
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1864
        }, {
 
1865
                name => "Fintek F81216D Super IO",
 
1866
                driver => "not-a-sensor",
 
1867
                devid => 0x0208,
 
1868
        }, {
 
1869
                name => "Fintek F81218D Super IO",
 
1870
                driver => "not-a-sensor",
 
1871
                devid => 0x0206,
 
1872
        }, {
 
1873
                name => "Asus F8000 Super IO",
 
1874
                driver => "f71882fg",
 
1875
                devid => 0x0581,
 
1876
                logdev => 0x04,
 
1877
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1878
        }, {
 
1879
                # Shouldn't be in this family, but seems to be still.
 
1880
                name => "ITE IT8708F Super IO",
 
1881
                driver => "not-a-sensor",
 
1882
                devid => 0x8708,
 
1883
        }, {
 
1884
                # Shouldn't be in this family, but seems to be still.
 
1885
                name => "ITE IT8710F Super IO",
 
1886
                driver => "not-a-sensor",
 
1887
                devid => 0x8710,
 
1888
        }
 
1889
);
 
1890
 
 
1891
@superio_ids_ite = (
 
1892
        {
 
1893
                name => "ITE IT8702F Super IO Fan Sensors",
 
1894
                driver => "to-be-written",
 
1895
                devid => 0x8702,
 
1896
                logdev => 0x04,
 
1897
                features => FEAT_FAN,
 
1898
        }, {
 
1899
                name => "ITE IT8705F Super IO Sensors",
 
1900
                driver => "it87",
 
1901
                devid => 0x8705,
 
1902
                logdev => 0x04,
 
1903
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1904
        }, {
 
1905
                name => "ITE IT8712F Super IO Sensors",
 
1906
                driver => "it87",
 
1907
                devid => 0x8712,
 
1908
                logdev => 0x04,
 
1909
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1910
        }, {
 
1911
                name => "ITE IT8716F Super IO Sensors",
 
1912
                driver => "it87",
 
1913
                devid => 0x8716,
 
1914
                logdev => 0x04,
 
1915
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1916
        }, {
 
1917
                name => "ITE IT8718F Super IO Sensors",
 
1918
                driver => "it87",
 
1919
                devid => 0x8718,
 
1920
                logdev => 0x04,
 
1921
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1922
        }, {
 
1923
                name => "ITE IT8720F Super IO Sensors",
 
1924
                driver => "it87",
 
1925
                devid => 0x8720,
 
1926
                logdev => 0x04,
 
1927
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1928
        }, {
 
1929
                name => "ITE IT8721F/IT8758E Super IO Sensors",
 
1930
                driver => "to-be-written",      # it87
 
1931
                devid => 0x8721,
 
1932
                logdev => 0x04,
 
1933
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1934
        }, {
 
1935
                name => "ITE IT8726F Super IO Sensors",
 
1936
                driver => "it87",
 
1937
                devid => 0x8726,
 
1938
                logdev => 0x04,
 
1939
                features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 
1940
        }
 
1941
);
 
1942
 
 
1943
# Entries are grouped by family. Each family entry has the following fields:
 
1944
#  family: The family name
 
1945
#  guess (optional): Typical logical device address. This lets us do
 
1946
#       generic probing if we fail to recognize the chip.
 
1947
#  enter: The password sequence to write to the address register
 
1948
#  chips: Array of chips
 
1949
# The order of families matters, because we stop as soon as one family
 
1950
# succeeds. So we have to list families with shorter password sequences
 
1951
# first.
 
1952
@superio_ids = (
 
1953
        {
 
1954
                family => "National Semiconductor",
 
1955
                enter =>
 
1956
                {
 
1957
                        0x2e => [],
 
1958
                        0x4e => [],
 
1959
                },
 
1960
                chips => \@superio_ids_natsemi,
 
1961
        }, {
 
1962
                family => "SMSC",
 
1963
                enter =>
 
1964
                {
 
1965
                        0x2e => [0x55],
 
1966
                        0x4e => [0x55],
 
1967
                },
 
1968
                chips => \@superio_ids_smsc,
 
1969
                ns_detect => \&smsc_ns_detect_superio,
 
1970
                ns_chips => \@superio_ids_smsc_ns,
 
1971
        }, {
 
1972
                family => "VIA/Winbond/Nuvoton/Fintek",
 
1973
                guess => 0x290,
 
1974
                enter =>
 
1975
                {
 
1976
                        0x2e => [0x87, 0x87],
 
1977
                        0x4e => [0x87, 0x87],
 
1978
                },
 
1979
                chips => \@superio_ids_winbond,
 
1980
        }, {
 
1981
                family => "ITE",
 
1982
                guess => 0x290,
 
1983
                enter =>
 
1984
                {
 
1985
                        0x2e => [0x87, 0x01, 0x55, 0x55],
 
1986
                        0x4e => [0x87, 0x01, 0x55, 0xaa],
 
1987
                },
 
1988
                chips => \@superio_ids_ite,
 
1989
        }
 
1990
);
 
1991
 
 
1992
# Drivers for bridge, CPU and memory embedded sensors
 
1993
# Each entry must have the following fields:
 
1994
#  name: The device name
 
1995
#  driver: The driver name. Put "to-be-written" if no driver is available.
 
1996
#  detect: Detection callback function. No parameter will be passed to
 
1997
#       this function, it must use global lists of PCI devices, CPU,
 
1998
#       etc. It must return a confidence value, undef if no supported
 
1999
#       CPU is found.
 
2000
use vars qw(@cpu_ids);
 
2001
 
 
2002
@cpu_ids = (
 
2003
        {
 
2004
                name => "Silicon Integrated Systems SIS5595",
 
2005
                driver => "sis5595",
 
2006
                detect => \&sis5595_pci_detect,
 
2007
        }, {
 
2008
                name => "VIA VT82C686 Integrated Sensors",
 
2009
                driver => "via686a",
 
2010
                detect => \&via686a_pci_detect,
 
2011
        }, {
 
2012
                name => "VIA VT8231 Integrated Sensors",
 
2013
                driver => "vt8231",
 
2014
                detect => \&via8231_pci_detect,
 
2015
        }, {
 
2016
                name => "AMD K8 thermal sensors",
 
2017
                driver => "k8temp",
 
2018
                detect => \&k8temp_pci_detect,
 
2019
        }, {
 
2020
                name => "AMD Family 10h thermal sensors",
 
2021
                driver => "k10temp",
 
2022
                detect => \&fam10h_pci_detect,
 
2023
        }, {
 
2024
                name => "AMD Family 11h thermal sensors",
 
2025
                driver => "k10temp",
 
2026
                detect => \&fam11h_pci_detect,
 
2027
        }, {
 
2028
                name => "Intel Core family thermal sensor",
 
2029
                driver => "coretemp",
 
2030
                detect => sub { coretemp_detect(0); },
 
2031
        }, {
 
2032
                name => "Intel Atom thermal sensor",
 
2033
                driver => "coretemp",
 
2034
                detect => sub { coretemp_detect(1); },
 
2035
        }, {
 
2036
                name => "Intel AMB FB-DIMM thermal sensor",
 
2037
                driver => "i5k_amb",
 
2038
                detect => \&intel_amb_detect,
 
2039
        }, {
 
2040
                name => "VIA C7 thermal sensor",
 
2041
                driver => "via-cputemp",
 
2042
                detect => \&via_c7_detect,
 
2043
        }, {
 
2044
                name => "VIA Nano thermal sensor",
 
2045
                driver => "via-cputemp",
 
2046
                detect => \&via_nano_detect,
 
2047
        }
 
2048
);
 
2049
 
 
2050
#######################
 
2051
# AUXILIARY FUNCTIONS #
 
2052
#######################
 
2053
 
 
2054
# $_[0] is the sought value
 
2055
# $_[1..] is the list to seek in
 
2056
# Returns: 1 if found, 0 if not.
 
2057
sub contains
 
2058
{
 
2059
        my $sought = shift;
 
2060
        local $_;
 
2061
 
 
2062
        foreach (@_) {
 
2063
                return 1 if $sought eq $_;
 
2064
        }
 
2065
        return 0;
 
2066
}
 
2067
 
 
2068
# Address can be decimal or hexadecimal
 
2069
sub valid_address
 
2070
{
 
2071
        my $value = shift;
 
2072
 
 
2073
        if ($value !~ m/^(0x[0-9a-f]+|[0-9]+)$/i) {
 
2074
                print "$value is not a valid address, sorry.\n";
 
2075
                exit -1;
 
2076
        }
 
2077
        $value = oct($value) if $value =~ m/^0x/i;
 
2078
 
 
2079
        return $value;
 
2080
}
 
2081
 
 
2082
sub parse_not_to_scan
 
2083
{
 
2084
        my ($min, $max, $to_parse) = @_;
 
2085
        my @ranges = split /\s*, \s*/, $to_parse;
 
2086
        my @res;
 
2087
        my $range;
 
2088
 
 
2089
        foreach $range (@ranges) {
 
2090
                my ($start, $end) = split /\s*-\s*/, $range;
 
2091
                $start = valid_address($start);
 
2092
                if (defined $end) {
 
2093
                        $end = valid_address($end);
 
2094
                        if ($end <= $start) {
 
2095
                                print "$start-$end is not a valid range, sorry.\n";
 
2096
                                exit -1;
 
2097
                        }
 
2098
                        $start = $min if $start < $min;
 
2099
                        $end = $max if $end > $max;
 
2100
                        push @res, ($start..$end);
 
2101
                } else {
 
2102
                        push @res, $start if $start >= $min and $start <= $max;
 
2103
                }
 
2104
        }
 
2105
 
 
2106
        return sort { $a <=> $b } @res;
 
2107
}
 
2108
 
 
2109
# $_[0]: Reference to list 1
 
2110
# $_[1]: Reference to list 2
 
2111
# Result: 0 if they have no elements in common, 1 if they have
 
2112
# Elements must be numeric.
 
2113
sub any_list_match
 
2114
{
 
2115
        my ($list1, $list2) = @_;
 
2116
        my ($el1, $el2);
 
2117
 
 
2118
        foreach $el1 (@$list1) {
 
2119
                foreach $el2 (@$list2) {
 
2120
                        return 1 if $el1 == $el2;
 
2121
                }
 
2122
        }
 
2123
        return 0;
 
2124
}
 
2125
 
 
2126
###################
 
2127
# I/O PORT ACCESS #
 
2128
###################
 
2129
 
 
2130
sub initialize_ioports
 
2131
{
 
2132
        sysopen(IOPORTS, "/dev/port", O_RDWR)
 
2133
                or die "/dev/port: $!\n";
 
2134
        binmode(IOPORTS);
 
2135
}
 
2136
 
 
2137
sub close_ioports
 
2138
{
 
2139
        close(IOPORTS);
 
2140
}
 
2141
 
 
2142
# $_[0]: port to read
 
2143
# Returns: -1 on failure, read value on success.
 
2144
sub inb
 
2145
{
 
2146
        my ($res, $nrchars);
 
2147
        sysseek(IOPORTS, $_[0], 0) or return -1;
 
2148
        $nrchars = sysread(IOPORTS, $res, 1);
 
2149
        return -1 if not defined $nrchars or $nrchars != 1;
 
2150
        $res = unpack("C", $res);
 
2151
        return $res;
 
2152
}
 
2153
 
 
2154
# $_[0]: port to write
 
2155
# $_[1]: value to write
 
2156
# We assume this can't fail.
 
2157
sub outb
 
2158
{
 
2159
        sysseek(IOPORTS, $_[0], 0);
 
2160
        syswrite(IOPORTS, pack("C", $_[1]), 1);
 
2161
}
 
2162
 
 
2163
# $_[0]: Address register
 
2164
# $_[1]: Data register
 
2165
# $_[2]: Register to read
 
2166
# Returns: read value
 
2167
sub isa_read_byte
 
2168
{
 
2169
        outb($_[0], $_[2]);
 
2170
        return inb($_[1]);
 
2171
}
 
2172
 
 
2173
# $_[0]: Base address
 
2174
# $_[1]: Register to read
 
2175
# Returns: read value
 
2176
# This one can be used for any ISA chip with index register at
 
2177
# offset 5 and data register at offset 6.
 
2178
sub isa_read_i5d6
 
2179
{
 
2180
        my ($addr, $reg) = @_;
 
2181
        return isa_read_byte($addr + 5, $addr + 6, $reg);
 
2182
}
 
2183
 
 
2184
#################
 
2185
# AUTODETECTION #
 
2186
#################
 
2187
 
 
2188
use vars qw($dev_i2c $sysfs_root);
 
2189
 
 
2190
sub initialize_conf
 
2191
{
 
2192
        my $use_devfs = 0;
 
2193
        open(local *INPUTFILE, "/proc/mounts") or die "Can't access /proc/mounts!";
 
2194
        local $_;
 
2195
        while (<INPUTFILE>) {
 
2196
                if (m@^\w+ /dev devfs @) {
 
2197
                        $use_devfs = 1;
 
2198
                        $dev_i2c = '/dev/i2c/';
 
2199
                }
 
2200
                if (m@^\S+ (/\w+) sysfs @) {
 
2201
                        $sysfs_root = $1;
 
2202
                }
 
2203
        }
 
2204
        close(INPUTFILE);
 
2205
 
 
2206
        # We need sysfs for many things
 
2207
        if (!defined $sysfs_root) {
 
2208
                print "Sysfs not mounted?\n";
 
2209
                exit -1;
 
2210
        }
 
2211
 
 
2212
        my $use_udev = 0;
 
2213
        if (open(*INPUTFILE, '/etc/udev/udev.conf')) {
 
2214
                while (<INPUTFILE>) {
 
2215
                        next unless m/^\s*udev_db\s*=\s*\"([^"]*)\"/
 
2216
                                 || m/^\s*udev_db\s*=\s*(\S+)/;
 
2217
                        if (-e $1) {
 
2218
                                $use_udev = 1;
 
2219
                                $dev_i2c = '/dev/i2c-';
 
2220
                        }
 
2221
                        last;
 
2222
                }
 
2223
                close(INPUTFILE);
 
2224
          }
 
2225
 
 
2226
        if (!$use_udev) {
 
2227
                # Try some known default udev db locations, just in case
 
2228
                if (-e '/dev/.udev.tdb' || -e '/dev/.udev'
 
2229
                 || -e '/dev/.udevdb') {
 
2230
                        $use_udev = 1;
 
2231
                        $dev_i2c = '/dev/i2c-';
 
2232
                }
 
2233
        }
 
2234
 
 
2235
        if (!($use_devfs || $use_udev)) {
 
2236
                if (! -c '/dev/i2c-0' && -x '/sbin/MAKEDEV') {
 
2237
                        system("/sbin/MAKEDEV i2c");
 
2238
                }
 
2239
                if (! -c '/dev/i2c-0' && -x '/dev/MAKEDEV') {
 
2240
                        system("/dev/MAKEDEV i2c");
 
2241
                }
 
2242
                if (-c '/dev/i2c-0') {
 
2243
                        $dev_i2c = '/dev/i2c-';
 
2244
                } else { # default
 
2245
                        print "No i2c device files found.\n";
 
2246
                        exit -1;
 
2247
                }
 
2248
        }
 
2249
}
 
2250
 
 
2251
# [0] -> VERSION
 
2252
# [1] -> PATCHLEVEL
 
2253
# [2] -> SUBLEVEL
 
2254
# [3] -> EXTRAVERSION
 
2255
#
 
2256
use vars qw(@kernel_version $kernel_arch);
 
2257
 
 
2258
sub initialize_kernel_version
 
2259
{
 
2260
        `uname -r` =~ /(\d+)\.(\d+)\.(\d+)(.*)/;
 
2261
        @kernel_version = ($1, $2, $3, $4);
 
2262
        chomp($kernel_arch = `uname -m`);
 
2263
 
 
2264
        # We only support kernels >= 2.6.5
 
2265
        if (!kernel_version_at_least(2, 6, 5)) {
 
2266
                print "Kernel version is unsupported (too old, >= 2.6.5 needed)\n";
 
2267
                exit -1;
 
2268
        }
 
2269
}
 
2270
 
 
2271
sub kernel_version_at_least
 
2272
{
 
2273
        my ($vers, $plvl, $slvl) = @_;
 
2274
        return 1 if ($kernel_version[0] > $vers ||
 
2275
                     ($kernel_version[0] == $vers &&
 
2276
                      ($kernel_version[1] > $plvl ||
 
2277
                       ($kernel_version[1] == $plvl &&
 
2278
                        ($kernel_version[2] >= $slvl)))));
 
2279
        return 0;
 
2280
}
 
2281
 
 
2282
# @cpu is a list of reference to hashes, one hash per CPU.
 
2283
# Each entry has the following keys: vendor_id, cpu family, model,
 
2284
# model name and stepping, directly taken from /proc/cpuinfo.
 
2285
use vars qw(@cpu);
 
2286
 
 
2287
sub initialize_cpu_list
 
2288
{
 
2289
        local $_;
 
2290
        my $entry;
 
2291
 
 
2292
        open(local *INPUTFILE, "/proc/cpuinfo") or die "Can't access /proc/cpuinfo!";
 
2293
        while (<INPUTFILE>) {
 
2294
                if (m/^processor\s*:\s*(\d+)/) {
 
2295
                        push @cpu, $entry if scalar keys(%{$entry}); # Previous entry
 
2296
                        $entry = {}; # New entry
 
2297
                        next;
 
2298
                }
 
2299
                if (m/^(vendor_id|cpu family|model|model name|stepping)\s*:\s*(.+)$/) {
 
2300
                        my $k = $1;
 
2301
                        my $v = $2;
 
2302
                        $v =~ s/\s+/ /g;        # Merge multiple spaces
 
2303
                        $v =~ s/ $//;           # Trim trailing space
 
2304
                        $entry->{$k} = $v;
 
2305
                        next;
 
2306
                }
 
2307
        }
 
2308
        close(INPUTFILE);
 
2309
        push @cpu, $entry if scalar keys(%{$entry}); # Last entry
 
2310
}
 
2311
 
 
2312
# @i2c_adapters is a list of references to hashes, one hash per I2C/SMBus
 
2313
# adapter present on the system. Each entry has the following keys: path,
 
2314
# parent, name (directly taken from sysfs), driver and autoload.
 
2315
use vars qw(@i2c_adapters);
 
2316
 
 
2317
# Find out whether the driver would be automatically loaded by the modalias
 
2318
# mechanism.
 
2319
sub device_driver_autoloads
 
2320
{
 
2321
        my $device = shift;
 
2322
        
 
2323
        my $modalias = sysfs_device_attribute($device, "modalias");
 
2324
        return 0 unless defined($modalias);
 
2325
 
 
2326
        # At the moment we only handle PCI and USB drivers. Other driver
 
2327
        # types, most notably platform and i2c drivers, do not follow the
 
2328
        # device driver model to the letter, and often create their own
 
2329
        # devices. Such drivers appear to be autoloaded when they are not.
 
2330
        return 0 unless $modalias =~ m/^(pci|usb):/;
 
2331
 
 
2332
        my $result = `modprobe -n -v --first-time $modalias 2>&1`;
 
2333
        return ($result =~ m/^insmod/ ||
 
2334
                $result =~ m/\balready in kernel\b/);
 
2335
}
 
2336
 
 
2337
sub initialize_i2c_adapters_list
 
2338
{
 
2339
        my ($entry, $base_dir, $have_i2c_adapter_class);
 
2340
        local $_;
 
2341
 
 
2342
        if (-d "${sysfs_root}/class/i2c-adapter") {
 
2343
                $base_dir = "${sysfs_root}/class/i2c-adapter";
 
2344
                $have_i2c_adapter_class = 1;
 
2345
        } else {
 
2346
                $base_dir = "${sysfs_root}/bus/i2c/devices";
 
2347
                $have_i2c_adapter_class = 0;
 
2348
        }
 
2349
        opendir(local *ADAPTERS, $base_dir) or return;
 
2350
 
 
2351
        while (defined($_ = readdir(ADAPTERS))) {
 
2352
                next unless m/^i2c-(\d+)$/;
 
2353
                my $nr = $1;
 
2354
                $entry = {}; # New entry
 
2355
 
 
2356
                # The layout in sysfs has changed over the years
 
2357
                if ($have_i2c_adapter_class) {
 
2358
                        my $link = readlink("${base_dir}/i2c-$nr/device");
 
2359
                        if (!defined $link) {
 
2360
                                $entry->{path} = "${base_dir}/i2c-$nr";
 
2361
                                $entry->{parent} = "${base_dir}/i2c-$nr";
 
2362
                        } elsif ($link =~ m/^(.*)\/i2c-$nr$/) {
 
2363
                                $entry->{path} = "${base_dir}/i2c-$nr/device";
 
2364
                                $entry->{parent} = "${base_dir}/i2c-$nr/$1";
 
2365
                        } else {
 
2366
                                $entry->{path} = "${base_dir}/i2c-$nr";
 
2367
                                $entry->{parent} = "$entry->{path}/device";
 
2368
                        }
 
2369
                } else {
 
2370
                        my $link = readlink("${base_dir}/i2c-$nr");
 
2371
                        $link =~ s/\/i2c-$nr$//;
 
2372
                        $entry->{path} = "${base_dir}/i2c-$nr";
 
2373
                        $entry->{parent} = "${base_dir}/$link";
 
2374
                }
 
2375
 
 
2376
                $entry->{name} = sysfs_device_attribute($entry->{path}, "name");
 
2377
                next if $entry->{name} eq "ISA main adapter";
 
2378
 
 
2379
                # First try to get the I2C adapter driver name from sysfs,
 
2380
                # and if it fails, fall back to searching our list of known
 
2381
                # I2C adapters.
 
2382
                $entry->{driver} = sysfs_device_driver($entry->{parent})
 
2383
                                || find_i2c_adapter_driver($entry->{name})
 
2384
                                || 'UNKNOWN';
 
2385
 
 
2386
                $entry->{autoload} = device_driver_autoloads($entry->{parent});
 
2387
                $i2c_adapters[$nr] = $entry;
 
2388
        }
 
2389
        closedir(ADAPTERS);
 
2390
}
 
2391
 
 
2392
# %hwmon_autoloaded is a list of hwmon drivers which are autoloaded
 
2393
# (typically by udev.) We don't need to load these drivers ourselves.
 
2394
use vars qw(%hwmon_autoloaded);
 
2395
 
 
2396
sub initialize_hwmon_autoloaded
 
2397
{
 
2398
        my $class_dir = "${sysfs_root}/class/hwmon";
 
2399
        opendir(local *HWMON, $class_dir) or return;
 
2400
 
 
2401
        my ($hwmon, $driver);
 
2402
        while (defined($hwmon = readdir(HWMON))) {
 
2403
                next unless $hwmon =~ m/^hwmon\d+$/;
 
2404
 
 
2405
                $driver = sysfs_device_driver("${class_dir}/$hwmon/device");
 
2406
                next unless defined($driver);
 
2407
 
 
2408
                if (device_driver_autoloads("${class_dir}/$hwmon/device")) {
 
2409
                        $driver =~ tr/-/_/;
 
2410
                        $hwmon_autoloaded{$driver}++
 
2411
                }
 
2412
        }
 
2413
        closedir(HWMON);
 
2414
}
 
2415
 
 
2416
sub hwmon_is_autoloaded
 
2417
{
 
2418
        my $driver = shift;
 
2419
        $driver =~ tr/-/_/;
 
2420
        return exists($hwmon_autoloaded{$driver});
 
2421
}
 
2422
 
 
2423
###########
 
2424
# MODULES #
 
2425
###########
 
2426
 
 
2427
use vars qw(%modules_list %modules_supported @modules_we_loaded);
 
2428
 
 
2429
sub initialize_modules_list
 
2430
{
 
2431
        local $_;
 
2432
 
 
2433
        open(local *INPUTFILE, "/proc/modules") or return;
 
2434
        while (<INPUTFILE>) {
 
2435
                tr/-/_/; # Probably not needed
 
2436
                $modules_list{$1} = 1 if m/^(\S*)/;
 
2437
        }
 
2438
}
 
2439
 
 
2440
sub is_module_loaded
 
2441
{
 
2442
        my $module = shift;
 
2443
        $module =~ tr/-/_/;
 
2444
        return exists $modules_list{$module}
 
2445
}
 
2446
 
 
2447
sub load_module
 
2448
{
 
2449
        my $module = shift;
 
2450
 
 
2451
        return if is_module_loaded($module);
 
2452
 
 
2453
        system("modprobe", $module);
 
2454
        if (($? >> 8) != 0) {
 
2455
                print "Failed to load module $module.\n";
 
2456
                return -1;
 
2457
        }
 
2458
 
 
2459
        print "Module $module loaded successfully.\n";
 
2460
        push @modules_we_loaded, $module;
 
2461
 
 
2462
        # Update the list of loaded modules
 
2463
        my $normalized = $module;
 
2464
        $normalized =~ tr/-/_/;
 
2465
        $modules_list{$normalized} = 1;
 
2466
}
 
2467
 
 
2468
sub initialize_modules_supported
 
2469
{
 
2470
        foreach my $chip (@chip_ids) {
 
2471
                next if $chip->{driver} eq "to-be-written";
 
2472
                next if $chip->{driver} eq "use-isa-instead";
 
2473
 
 
2474
                my $normalized = $chip->{driver};
 
2475
                $normalized =~ tr/-/_/;
 
2476
                $modules_supported{$normalized}++;
 
2477
        }
 
2478
}
 
2479
 
 
2480
sub unload_modules
 
2481
{
 
2482
        return unless @modules_we_loaded;
 
2483
 
 
2484
        # Attempt to unload all kernel drivers we loaded ourselves
 
2485
        while (my $module = pop @modules_we_loaded) {
 
2486
                print "Unloading $module... ";
 
2487
                system("modprobe -r $module 2> /dev/null");
 
2488
                if (($? >> 8) == 0) {
 
2489
                        print "OK\n";
 
2490
                } else {
 
2491
                        print "failed\n";
 
2492
                }
 
2493
        }
 
2494
        print "\n";
 
2495
}
 
2496
 
 
2497
############
 
2498
# DMI DATA #
 
2499
############
 
2500
 
 
2501
use vars qw(%dmi $dmidecode_ok);
 
2502
 
 
2503
# Returns: 1 if dmidecode is recent enough, 0 if not
 
2504
# Cache the result in case it is needed again later.
 
2505
sub check_dmidecode_version
 
2506
{
 
2507
        return $dmidecode_ok if defined $dmidecode_ok;
 
2508
 
 
2509
        my $version;
 
2510
        if (open(local *DMIDECODE, "dmidecode --version 2>/dev/null |")) {
 
2511
                $version = <DMIDECODE>;
 
2512
                close(DMIDECODE);
 
2513
                chomp $version if defined $version;
 
2514
        }
 
2515
 
 
2516
        if (!defined $version
 
2517
         || !($version =~ m/^(\d+).(\d+)$/)
 
2518
         || !(($1 == 2 && $2 >= 7) || $1 > 2)) {
 
2519
                print "# DMI data unavailable, please consider installing dmidecode 2.7\n".
 
2520
                      "# or later for better results.\n";
 
2521
                $dmidecode_ok = 0;
 
2522
        } else {
 
2523
                $dmidecode_ok = 1;
 
2524
        }
 
2525
 
 
2526
        return $dmidecode_ok;
 
2527
}
 
2528
 
 
2529
sub initialize_dmi_data
 
2530
{
 
2531
        my %items = (
 
2532
                # sysfs file name => dmidecode string name
 
2533
                sys_vendor => 'system-manufacturer',
 
2534
                product_name => 'system-product-name',
 
2535
                product_version => 'system-version',
 
2536
                board_vendor => 'baseboard-manufacturer',
 
2537
                board_name => 'baseboard-product-name',
 
2538
                board_version => 'baseboard-product-name',
 
2539
                chassis_type => 'chassis-type',
 
2540
        );
 
2541
        # Many BIOS have broken DMI data, filter it out
 
2542
        my %fake = (
 
2543
                'System Manufacturer' => 1,
 
2544
                'System Name' => 1,
 
2545
        );
 
2546
        my $dmi_id_dir;
 
2547
 
 
2548
        # First try reading the strings from sysfs if available
 
2549
        if (-d ($dmi_id_dir = "$sysfs_root/devices/virtual/dmi/id")     # kernel >= 2.6.28
 
2550
         || -d ($dmi_id_dir = "$sysfs_root/class/dmi/id")) {
 
2551
                foreach my $k (keys %items) {
 
2552
                        $dmi{$k} = sysfs_device_attribute($dmi_id_dir, $k);
 
2553
                }
 
2554
        } else {
 
2555
                # Else fallback on calling dmidecode
 
2556
                return unless check_dmidecode_version();
 
2557
 
 
2558
                foreach my $k (keys %items) {
 
2559
                        next unless open(local *DMIDECODE,
 
2560
                                         "dmidecode -s $items{$k} 2>/dev/null |");
 
2561
                        $dmi{$k} = <DMIDECODE>;
 
2562
                        close(DMIDECODE);
 
2563
                }
 
2564
        }
 
2565
 
 
2566
        # Strip trailing white-space, discard empty field
 
2567
        foreach my $k (keys %dmi) {
 
2568
                if (!defined $dmi{$k}) {
 
2569
                        delete $dmi{$k};
 
2570
                        next;
 
2571
                }
 
2572
                $dmi{$k} =~ s/\s*$//;
 
2573
                delete $dmi{$k} if $dmi{$k} eq '' || exists $fake{$dmi{$k}};
 
2574
        }
 
2575
}
 
2576
 
 
2577
sub print_dmi_summary
 
2578
{
 
2579
        my ($system, $board);
 
2580
        if (defined $dmi{sys_vendor} && defined $dmi{product_name}) {
 
2581
                $system = "$dmi{sys_vendor} $dmi{product_name}";
 
2582
        }
 
2583
        if (defined $dmi{board_vendor} && defined $dmi{board_name}) {
 
2584
                $board = "$dmi{board_vendor} $dmi{board_name}";
 
2585
        }
 
2586
        
 
2587
        if (defined $system) {
 
2588
                print "# System: $system";
 
2589
                print " (laptop)" if (is_laptop());
 
2590
                print "\n";
 
2591
        }
 
2592
        print "# Board: $board\n" if defined $board
 
2593
                                  && (!defined $system || $system ne $board);
 
2594
}
 
2595
 
 
2596
sub dmi_match
 
2597
{
 
2598
        my $key = shift;
 
2599
        my $value;
 
2600
 
 
2601
        return unless defined $dmi{$key};
 
2602
        while (defined ($value = shift)) {
 
2603
                return 1 if $dmi{$key} =~ m/\b$value\b/i;
 
2604
        }
 
2605
        return 0;
 
2606
}
 
2607
 
 
2608
sub is_laptop
 
2609
{
 
2610
        return 0 unless $dmi{chassis_type};
 
2611
        return 1 if $dmi{chassis_type} =~ m/(Laptop|Notebook|Hand Held)/i;
 
2612
        return 1 if $dmi{chassis_type} =~ m/^(9|10|11|14)$/;
 
2613
        return 0;
 
2614
}
 
2615
 
 
2616
#################
 
2617
# SYSFS HELPERS #
 
2618
#################
 
2619
 
 
2620
# From a sysfs device path, return the driver (module) name, or undef
 
2621
sub sysfs_device_driver
 
2622
{
 
2623
        my $device = shift;
 
2624
 
 
2625
        my $link = readlink("$device/driver/module");
 
2626
        return unless defined $link;
 
2627
        return basename($link);
 
2628
}
 
2629
 
 
2630
# From a sysfs device path, return the subsystem name, or undef
 
2631
sub sysfs_device_subsystem
 
2632
{
 
2633
        my $device = shift;
 
2634
 
 
2635
        my $link = readlink("$device/subsystem");
 
2636
        return unless defined $link;
 
2637
        return basename($link);
 
2638
}
 
2639
 
 
2640
# From a sysfs device path and an attribute name, return the attribute
 
2641
# value, or undef
 
2642
sub sysfs_device_attribute
 
2643
{
 
2644
        my ($device, $attr) = @_;
 
2645
        my $value;
 
2646
 
 
2647
        open(local *FILE, "$device/$attr") or return;
 
2648
        $value = <FILE>;
 
2649
        close(FILE);
 
2650
        return unless defined $value;
 
2651
 
 
2652
        chomp($value);
 
2653
        return $value;
 
2654
}
 
2655
 
 
2656
##############
 
2657
# PCI ACCESS #
 
2658
##############
 
2659
 
 
2660
use vars qw(%pci_list);
 
2661
 
 
2662
# This function returns a list of hashes. Each hash has some PCI information:
 
2663
# 'domain', 'bus', 'slot' and 'func' uniquely identify a PCI device in a
 
2664
# computer; 'vendid' and 'devid' uniquely identify a type of device.
 
2665
# 'class' lets us spot unknown SMBus adapters.
 
2666
sub read_sys_dev_pci
 
2667
{
 
2668
        my $devices = shift;
 
2669
        my ($dev, @pci_list);
 
2670
 
 
2671
        opendir(local *DEVICES, "$devices")
 
2672
                or die "$devices: $!";
 
2673
 
 
2674
        while (defined($dev = readdir(DEVICES))) {
 
2675
                my %record;
 
2676
                next unless $dev =~
 
2677
                        m/^(?:([\da-f]+):)?([\da-f]+):([\da-f]+)\.([\da-f]+)$/;
 
2678
 
 
2679
                $record{domain} = hex $1;
 
2680
                $record{bus} = hex $2;
 
2681
                $record{slot} = hex $3;
 
2682
                $record{func} = hex $4;
 
2683
 
 
2684
                $record{vendid} = oct sysfs_device_attribute("$devices/$dev",
 
2685
                                                             "vendor");
 
2686
                $record{devid} = oct sysfs_device_attribute("$devices/$dev",
 
2687
                                                            "device");
 
2688
                $record{class} = (oct sysfs_device_attribute("$devices/$dev",
 
2689
                                                             "class")) >> 8;
 
2690
 
 
2691
                push @pci_list, \%record;
 
2692
        }
 
2693
 
 
2694
        return \@pci_list;
 
2695
}
 
2696
 
 
2697
sub initialize_pci
 
2698
{
 
2699
        my $pci_list;
 
2700
        local $_;
 
2701
 
 
2702
        $pci_list = read_sys_dev_pci("$sysfs_root/bus/pci/devices");
 
2703
 
 
2704
        # Note that we lose duplicate devices at this point, but we don't
 
2705
        # really care. What matters to us is which unique devices are present,
 
2706
        # not how many of each.
 
2707
        %pci_list = map {
 
2708
                sprintf("%04x:%04x", $_->{vendid}, $_->{devid}) => $_
 
2709
        } @{$pci_list};
 
2710
}
 
2711
 
 
2712
#####################
 
2713
# ADAPTER DETECTION #
 
2714
#####################
 
2715
 
 
2716
# Build and return a PCI device's bus ID
 
2717
sub pci_busid
 
2718
{
 
2719
        my $device = shift;
 
2720
        my $busid;
 
2721
 
 
2722
        $busid = sprintf("\%02x:\%02x.\%x",
 
2723
                         $device->{bus}, $device->{slot}, $device->{func});
 
2724
        $busid = sprintf("\%04x:", $device->{domain}) . $busid
 
2725
                if defined $device->{domain};
 
2726
 
 
2727
        return $busid;
 
2728
}
 
2729
 
 
2730
sub adapter_pci_detection
 
2731
{
 
2732
        my ($key, $device, $try, %smbus, $count);
 
2733
 
 
2734
        # Build a list of detected SMBus devices
 
2735
        foreach $key (keys %pci_list) {
 
2736
                $device = $pci_list{$key};
 
2737
                $smbus{$key}++
 
2738
                        if exists $device->{class} &&
 
2739
                           ($device->{class} == 0x0c01 ||       # Access Bus
 
2740
                            $device->{class} == 0x0c05);        # SMBus
 
2741
        }
 
2742
 
 
2743
        # Loop over the known I2C/SMBus adapters
 
2744
        foreach $try (@pci_adapters) {
 
2745
                $key = sprintf("%04x:%04x", $try->{vendid}, $try->{devid});
 
2746
                next unless exists $pci_list{$key};
 
2747
 
 
2748
                $device = $pci_list{$key};
 
2749
                if ($try->{driver} eq "to-be-tested") {
 
2750
                        print "\nWe are currently looking for testers for this adapter!\n".
 
2751
                              "Please check http://www.lm-sensors.org/wiki/Devices\n".
 
2752
                              "and/or contact us if you want to help.\n\n".
 
2753
                              "Continue... ";
 
2754
                        <STDIN>;
 
2755
                        print "\n";
 
2756
                }
 
2757
 
 
2758
                if ($try->{driver} =~ m/^to-be-/) {
 
2759
                        printf "No known driver for device \%s: \%s\n",
 
2760
                               pci_busid($device), $try->{procid};
 
2761
                } else {
 
2762
                        printf "Using driver `\%s' for device \%s: \%s\n",
 
2763
                               $try->{driver}, pci_busid($device),
 
2764
                               $try->{procid};
 
2765
                        $count++;
 
2766
                        load_module($try->{driver});
 
2767
                }
 
2768
 
 
2769
                # Delete from detected SMBus device list
 
2770
                delete $smbus{$key};
 
2771
        }
 
2772
 
 
2773
        # Now see if there are unknown SMBus devices left
 
2774
        foreach $key (keys %smbus) {
 
2775
                $device = $pci_list{$key};
 
2776
                printf "Found unknown SMBus adapter \%04x:\%04x at \%s.\n",
 
2777
                       $device->{vendid}, $device->{devid}, pci_busid($device);
 
2778
        }
 
2779
 
 
2780
        print "Sorry, no supported PCI bus adapters found.\n"
 
2781
                unless $count;
 
2782
}
 
2783
 
 
2784
# $_[0]: Adapter description as found in sysfs
 
2785
sub find_i2c_adapter_driver
 
2786
{
 
2787
        my $name = shift;
 
2788
        my $entry;
 
2789
 
 
2790
        foreach $entry (@i2c_adapter_names) {
 
2791
                return $entry->{driver}
 
2792
                        if $name =~ $entry->{match};
 
2793
        }
 
2794
}
 
2795
 
 
2796
#############################
 
2797
# I2C AND SMBUS /DEV ACCESS #
 
2798
#############################
 
2799
 
 
2800
# This should really go into a separate module/package.
 
2801
 
 
2802
# These are copied from <linux/i2c-dev.h>
 
2803
 
 
2804
use constant IOCTL_I2C_SLAVE    => 0x0703;
 
2805
use constant IOCTL_I2C_FUNCS    => 0x0705;
 
2806
use constant IOCTL_I2C_SMBUS    => 0x0720;
 
2807
 
 
2808
use constant SMBUS_READ         => 1;
 
2809
use constant SMBUS_WRITE        => 0;
 
2810
 
 
2811
use constant SMBUS_QUICK        => 0;
 
2812
use constant SMBUS_BYTE         => 1;
 
2813
use constant SMBUS_BYTE_DATA    => 2;
 
2814
use constant SMBUS_WORD_DATA    => 3;
 
2815
 
 
2816
use constant I2C_FUNC_SMBUS_QUICK       => 0x00010000;
 
2817
use constant I2C_FUNC_SMBUS_READ_BYTE   => 0x00020000;
 
2818
use constant I2C_FUNC_SMBUS_READ_BYTE_DATA      => 0x00080000;
 
2819
 
 
2820
# Get the i2c adapter's functionalities
 
2821
# $_[0]: Reference to an opened filehandle
 
2822
# Returns: -1 on failure, functionality bitfield on success.
 
2823
sub i2c_get_funcs
 
2824
{
 
2825
        my $file = shift;
 
2826
        my $funcs = pack("L", 0); # Allocate space
 
2827
 
 
2828
        ioctl($file, IOCTL_I2C_FUNCS, $funcs) or return -1;
 
2829
        $funcs = unpack("L", $funcs);
 
2830
 
 
2831
        return $funcs;
 
2832
}
 
2833
 
 
2834
# Select the device to communicate with through its address.
 
2835
# $_[0]: Reference to an opened filehandle
 
2836
# $_[1]: Address to select
 
2837
# Returns: 0 on failure, 1 on success.
 
2838
sub i2c_set_slave_addr
 
2839
{
 
2840
        my ($file, $addr) = @_;
 
2841
 
 
2842
        # Reset register data cache
 
2843
        @i2c_byte_cache = ();
 
2844
 
 
2845
        $addr += 0; # Make sure it's a number not a string
 
2846
        ioctl($file, IOCTL_I2C_SLAVE, $addr) or return 0;
 
2847
        return 1;
 
2848
}
 
2849
 
 
2850
# i2c_smbus_access is based upon the corresponding C function (see
 
2851
# <linux/i2c-dev.h>). You should not need to call this directly.
 
2852
# $_[0]: Reference to an opened filehandle
 
2853
# $_[1]: SMBUS_READ for reading, SMBUS_WRITE for writing
 
2854
# $_[2]: Command (usually register number)
 
2855
# $_[3]: Transaction kind (SMBUS_BYTE, SMBUS_BYTE_DATA, etc.)
 
2856
# $_[4]: Reference to an array used for input/output of data
 
2857
# Returns: 0 on failure, 1 on success.
 
2858
# Note that we need to get back to Integer boundaries through the 'x2'
 
2859
# in the pack. This is very compiler-dependent; I wish there was some other
 
2860
# way to do this.
 
2861
sub i2c_smbus_access
 
2862
{
 
2863
        my ($file, $read_write, $command, $size, $data) = @_;
 
2864
        my $data_array = pack("C32", @$data);
 
2865
        my $ioctl_data = pack("C2x2Ip", $read_write, $command, $size,
 
2866
                              $data_array);
 
2867
 
 
2868
        ioctl($file, IOCTL_I2C_SMBUS, $ioctl_data) or return 0;
 
2869
        @{$_[4]} = unpack("C32", $data_array);
 
2870
        return 1;
 
2871
}
 
2872
 
 
2873
# $_[0]: Reference to an opened filehandle
 
2874
# Returns: -1 on failure, the read byte on success.
 
2875
sub i2c_smbus_read_byte
 
2876
{
 
2877
        my ($file) = @_;
 
2878
        my @data;
 
2879
 
 
2880
        i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE, \@data)
 
2881
                or return -1;
 
2882
        return $data[0];
 
2883
}
 
2884
 
 
2885
# $_[0]: Reference to an opened filehandle
 
2886
# $_[1]: Command byte (usually register number)
 
2887
# Returns: -1 on failure, the read byte on success.
 
2888
# Read byte data values are cached by default. As we keep reading the
 
2889
# same registers over and over again in the detection functions, and
 
2890
# SMBus can be slow, caching results in a big performance boost.
 
2891
sub i2c_smbus_read_byte_data
 
2892
{
 
2893
        my ($file, $command, $nocache) = @_;
 
2894
        my @data;
 
2895
 
 
2896
        return $i2c_byte_cache[$command]
 
2897
                if !$nocache && exists $i2c_byte_cache[$command];
 
2898
 
 
2899
        i2c_smbus_access($file, SMBUS_READ, $command, SMBUS_BYTE_DATA, \@data)
 
2900
                or return -1;
 
2901
        return ($i2c_byte_cache[$command] = $data[0]);
 
2902
}
 
2903
 
 
2904
# $_[0]: Reference to an opened filehandle
 
2905
# $_[1]: Command byte (usually register number)
 
2906
# Returns: -1 on failure, the read word on success.
 
2907
# Use this function with care, some devices don't like word reads,
 
2908
# so you should do as much of the detection as possible using byte reads,
 
2909
# and only start using word reads when there is a good chance that
 
2910
# the detection will succeed.
 
2911
# Note: some devices use the wrong endianness.
 
2912
sub i2c_smbus_read_word_data
 
2913
{
 
2914
        my ($file, $command) = @_;
 
2915
        my @data;
 
2916
        i2c_smbus_access($file, SMBUS_READ, $command, SMBUS_WORD_DATA, \@data)
 
2917
                or return -1;
 
2918
        return $data[0] + 256 * $data[1];
 
2919
}
 
2920
 
 
2921
# $_[0]: Reference to an opened filehandle
 
2922
# $_[1]: Address
 
2923
# $_[2]: Functionalities of this i2c adapter
 
2924
# Returns: 1 on successful probing, 0 else.
 
2925
# This function is meant to prevent AT24RF08 corruption and write-only
 
2926
# chips locks. This is done by choosing the best probing method depending
 
2927
# on the address range.
 
2928
sub i2c_probe
 
2929
{
 
2930
        my ($file, $addr, $funcs) = @_;
 
2931
 
 
2932
        if (($addr >= 0x50 && $addr <= 0x5F)
 
2933
         || ($addr >= 0x30 && $addr <= 0x37)) {
 
2934
                # This covers all EEPROMs we know of, including page protection
 
2935
                # addresses. Note that some page protection addresses will not
 
2936
                # reveal themselves with this, because they ack on write only,
 
2937
                # but this is probably better since some EEPROMs write-protect
 
2938
                # themselves permanently on almost any write to their page
 
2939
                # protection address.
 
2940
                return 0 unless ($funcs & I2C_FUNC_SMBUS_READ_BYTE);
 
2941
                return i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE, []);
 
2942
        } elsif ($addr == 0x73) {
 
2943
                # Special case for FSC chips, as at least the Syleus locks
 
2944
                # up with our regular probe code. Note that to our current
 
2945
                # knowledge only FSC chips live on this address, and for them
 
2946
                # this probe method is safe.
 
2947
                return 0 unless ($funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA);
 
2948
                return i2c_smbus_access($file, SMBUS_READ, 0, SMBUS_BYTE_DATA, []);
 
2949
        } else {
 
2950
                return 0 unless ($funcs & I2C_FUNC_SMBUS_QUICK);
 
2951
                return i2c_smbus_access($file, SMBUS_WRITE, 0, SMBUS_QUICK, []);
 
2952
        }
 
2953
}
 
2954
 
 
2955
# $_[0]: Reference to an opened file handle
 
2956
# Returns: 1 if the device is safe to access, 0 else.
 
2957
# This function is meant to prevent access to 1-register-only devices,
 
2958
# which are designed to be accessed with SMBus receive byte and SMBus send
 
2959
# byte transactions (i.e. short reads and short writes) and treat SMBus
 
2960
# read byte as a real write followed by a read. The device detection
 
2961
# routines would write random values to the chip with possibly very nasty
 
2962
# results for the hardware. Note that this function won't catch all such
 
2963
# chips, as it assumes that reads and writes relate to the same register,
 
2964
# but that's the best we can do.
 
2965
sub i2c_safety_check
 
2966
{
 
2967
        my ($file) = @_;
 
2968
        my $data;
 
2969
 
 
2970
        # First we receive a byte from the chip, and remember it.
 
2971
        $data = i2c_smbus_read_byte($file);
 
2972
        return 1 if ($data < 0);
 
2973
 
 
2974
        # We receive a byte again; very likely to be the same for
 
2975
        # 1-register-only devices.
 
2976
        return 1 if (i2c_smbus_read_byte($file) != $data);
 
2977
 
 
2978
        # Then we try a standard byte read, with a register offset equal to
 
2979
        # the byte we received; we should receive the same byte value in return.
 
2980
        return 1 if (i2c_smbus_read_byte_data($file, $data) != $data);
 
2981
 
 
2982
        # Then we try a standard byte read, with a slightly different register
 
2983
        # offset; we should again receive the same byte value in return.
 
2984
        return 1 if (i2c_smbus_read_byte_data($file, $data ^ 1) != ($data ^ 1));
 
2985
 
 
2986
        # Apprently this is a 1-register-only device, restore the original
 
2987
        # register value and leave it alone.
 
2988
        i2c_smbus_read_byte_data($file, $data);
 
2989
        return 0;
 
2990
}
 
2991
 
 
2992
####################
 
2993
# ADAPTER SCANNING #
 
2994
####################
 
2995
 
 
2996
use vars qw(%chips_detected);
 
2997
 
 
2998
# We will build a complicated structure %chips_detected here, being a hash
 
2999
# where keys are driver names and values are detected chip information in
 
3000
# the form of a list of hashes of type 'detect_data'.
 
3001
 
 
3002
# Type detect_data:
 
3003
# A hash
 
3004
#  with field 'i2c_devnr', contianing the /dev/i2c-* number of this
 
3005
#       adapter (if this is an I2C detection)
 
3006
#  with field 'i2c_addr', containing the I2C address of the detection;
 
3007
#       (if this is an I2C detection)
 
3008
#  with field 'i2c_sub_addrs', containing a reference to a list of
 
3009
#       other I2C addresses (if this is an I2C detection)
 
3010
#  with field 'isa_addr' containing the ISA address this chip is on
 
3011
#       (if this is an ISA detection)
 
3012
#  with field 'conf', containing the confidence level of this detection
 
3013
#  with field 'chipname', containing the chip name
 
3014
#  with optional field 'alias_detect', containing a reference to an alias
 
3015
#       detection function for this chip
 
3016
 
 
3017
# This adds a detection to the above structure.
 
3018
# Not all possibilities of i2c_addr and i2c_sub_addrs are exhausted.
 
3019
# In all normal cases, it should be all right.
 
3020
# $_[0]: chip driver
 
3021
# $_[1]: reference to data hash
 
3022
# Returns: Nothing
 
3023
sub add_i2c_to_chips_detected
 
3024
{
 
3025
        my ($chipdriver, $datahash) = @_;
 
3026
        my ($i, $detected_ref, $detected_entry, $driver,
 
3027
            $put_in_detected, @hash_addrs, @entry_addrs);
 
3028
 
 
3029
        # Find out whether our new entry should go into the detected list
 
3030
        # or not. We compare all i2c addresses; if at least one matches,
 
3031
        # but our confidence value is lower, we assume this is a misdetection,
 
3032
        # in which case we simply discard our new entry.
 
3033
        @hash_addrs = ($datahash->{i2c_addr});
 
3034
        push @hash_addrs, @{$datahash->{i2c_sub_addrs}}
 
3035
                if exists $datahash->{i2c_sub_addrs};
 
3036
        $put_in_detected = 1;
 
3037
 FIND_LOOP:
 
3038
        foreach $detected_ref (values %chips_detected) {
 
3039
                foreach $detected_entry (@{$detected_ref}) {
 
3040
                        next unless defined $detected_entry->{i2c_addr};
 
3041
                        @entry_addrs = ($detected_entry->{i2c_addr});
 
3042
                        push @entry_addrs, @{$detected_entry->{i2c_sub_addrs}}
 
3043
                                if exists $detected_entry->{i2c_sub_addrs};
 
3044
                        if ($detected_entry->{i2c_devnr} == $datahash->{i2c_devnr} &&
 
3045
                            any_list_match(\@entry_addrs, \@hash_addrs)) {
 
3046
                                if ($detected_entry->{conf} >= $datahash->{conf}) {
 
3047
                                        $put_in_detected = 0;
 
3048
                                }
 
3049
                                last FIND_LOOP;
 
3050
                        }
 
3051
                }
 
3052
        }
 
3053
 
 
3054
        return unless $put_in_detected;
 
3055
 
 
3056
        # Here, we discard all entries which match at least in one main or
 
3057
        # sub address. This may not be the best idea to do, as it may remove
 
3058
        # detections without replacing them with second-best ones. Too bad.
 
3059
        foreach $driver (keys %chips_detected) {
 
3060
                $detected_ref = $chips_detected{$driver};
 
3061
                for ($i = @$detected_ref-1; $i >=0; $i--) {
 
3062
                        next unless defined $detected_ref->[$i]->{i2c_addr};
 
3063
                        @entry_addrs = ($detected_ref->[$i]->{i2c_addr});
 
3064
                        push @entry_addrs, @{$detected_ref->[$i]->{i2c_sub_addrs}}
 
3065
                                if exists $detected_ref->[$i]->{i2c_sub_addrs};
 
3066
                        if ($detected_ref->[$i]->{i2c_devnr} == $datahash->{i2c_devnr} &&
 
3067
                            any_list_match(\@entry_addrs, \@hash_addrs)) {
 
3068
                                splice @$detected_ref, $i, 1;
 
3069
                                delete $chips_detected{$driver}
 
3070
                                        if (!@$detected_ref);
 
3071
                        }
 
3072
                }
 
3073
        }
 
3074
 
 
3075
        # Now add the new entry to detected
 
3076
        $chips_detected{$chipdriver} = []
 
3077
                unless exists $chips_detected{$chipdriver};
 
3078
        push @{$chips_detected{$chipdriver}}, $datahash;
 
3079
}
 
3080
 
 
3081
# Fake i2c drivers such as "not-a-sensor" or "use-isa-instead" have to be
 
3082
# inserted so that confidence comparison can be performed. But then we have
 
3083
# to filter them out so that the user doesn't get confused.
 
3084
sub filter_out_fake_i2c_drivers
 
3085
{
 
3086
        delete $chips_detected{"not-a-sensor"};
 
3087
        delete $chips_detected{"use-isa-instead"};
 
3088
}
 
3089
 
 
3090
# This adds a detection to the above structure.
 
3091
# $_[0]: chip driver
 
3092
# $_[1]: reference to data hash
 
3093
sub add_isa_to_chips_detected
 
3094
{
 
3095
        my ($chipdriver, $datahash) = @_;
 
3096
        my ($i, $new_detected_ref, $detected_ref);
 
3097
 
 
3098
        # First determine where the hash has to be added.
 
3099
        $chips_detected{$chipdriver} = []
 
3100
                unless exists $chips_detected{$chipdriver};
 
3101
        $new_detected_ref = $chips_detected{$chipdriver};
 
3102
 
 
3103
        # Find out whether our new entry should go into the detected list
 
3104
        # or not. We only compare main isa_addr here, of course.
 
3105
        foreach $detected_ref (values %chips_detected) {
 
3106
                for ($i = 0; $i < @{$detected_ref}; $i++) {
 
3107
                        if (exists $detected_ref->[$i]->{isa_addr} and
 
3108
                            exists $datahash->{isa_addr} and
 
3109
                            $detected_ref->[$i]->{isa_addr} == $datahash->{isa_addr}) {
 
3110
                                if ($detected_ref->[$i]->{conf} < $datahash->{conf}) {
 
3111
                                        splice @$detected_ref, $i, 1;
 
3112
                                        push @$new_detected_ref, $datahash;
 
3113
                                }
 
3114
                                return;
 
3115
                        }
 
3116
                }
 
3117
        }
 
3118
 
 
3119
        # Not found? OK, put it in the detected list
 
3120
        push @$new_detected_ref, $datahash;
 
3121
}
 
3122
 
 
3123
# $_[0]: reference to an array of chips which may be aliases of each other
 
3124
sub find_aliases
 
3125
{
 
3126
        my $detected = shift;
 
3127
        my ($isa, $i2c, $dev, $alias_detect, $is_alias);
 
3128
 
 
3129
        for ($isa = 0; $isa < @{$detected}; $isa++) {
 
3130
                # Look for chips with an ISA address but no I2C address
 
3131
                next unless defined $detected->[$isa];
 
3132
                next unless $detected->[$isa]->{isa_addr};
 
3133
                next if defined $detected->[$isa]->{i2c_addr};
 
3134
                # Additionally, the chip must possibly have I2C aliases
 
3135
                next unless defined $detected->[$isa]->{alias_detect};
 
3136
 
 
3137
                for ($i2c = 0; $i2c < @{$detected}; $i2c++) {
 
3138
                        # Look for chips with an I2C address but no ISA address
 
3139
                        next unless defined $detected->[$i2c];
 
3140
                        next unless defined $detected->[$i2c]->{i2c_addr};
 
3141
                        next if $detected->[$i2c]->{isa_addr};
 
3142
                        # Additionally, it must have the same chip name
 
3143
                        next unless $detected->[$i2c]->{chipname} eq
 
3144
                                    $detected->[$isa]->{chipname};
 
3145
 
 
3146
                        # We have potential aliases, check if they actually are
 
3147
                        $dev = $dev_i2c.$detected->[$i2c]->{i2c_devnr};
 
3148
                        open(local *FILE, $dev) or
 
3149
                                print("Can't open $dev\n"),
 
3150
                                next;
 
3151
                        binmode(FILE);
 
3152
                        i2c_set_slave_addr(\*FILE, $detected->[$i2c]->{i2c_addr}) or
 
3153
                                print("Can't set I2C address for $dev\n"),
 
3154
                                next;
 
3155
 
 
3156
                        initialize_ioports();
 
3157
                        $alias_detect = $detected->[$isa]->{alias_detect};
 
3158
                        $is_alias = &$alias_detect($detected->[$isa]->{isa_addr},
 
3159
                                                   \*FILE,
 
3160
                                                   $detected->[$i2c]->{i2c_addr});
 
3161
                        close(FILE);
 
3162
                        close_ioports();
 
3163
 
 
3164
                        next unless $is_alias;
 
3165
                        # This is an alias: copy the I2C data into the ISA
 
3166
                        # entry, then discard the I2C entry
 
3167
                        $detected->[$isa]->{i2c_devnr} = $detected->[$i2c]->{i2c_devnr};
 
3168
                        $detected->[$isa]->{i2c_addr} = $detected->[$i2c]->{i2c_addr};
 
3169
                        $detected->[$isa]->{i2c_sub_addr} = $detected->[$i2c]->{i2c_sub_addr};
 
3170
                        undef $detected->[$i2c];
 
3171
                        last;
 
3172
                }
 
3173
        }
 
3174
 
 
3175
        # The loops above may have made the chip list sparse, make it
 
3176
        # compact again
 
3177
        for ($isa = 0; $isa < @{$detected}; ) {
 
3178
                if (defined($detected->[$isa])) {
 
3179
                        $isa++;
 
3180
                } else {
 
3181
                        splice @{$detected}, $isa, 1;
 
3182
                }
 
3183
        }
 
3184
}
 
3185
 
 
3186
# From the list of known I2C/SMBus devices, build a list of I2C addresses
 
3187
# which are worth probing. There's no point in probing an address for which
 
3188
# we don't know a single device, and probing some addresses has caused
 
3189
# random trouble in the past.
 
3190
sub i2c_addresses_to_scan
 
3191
{
 
3192
        my @used;
 
3193
        my @addresses;
 
3194
        my $addr;
 
3195
 
 
3196
        foreach my $chip (@chip_ids) {
 
3197
                next unless defined $chip->{i2c_addrs};
 
3198
                foreach $addr (@{$chip->{i2c_addrs}}) {
 
3199
                        $used[$addr]++;
 
3200
                }
 
3201
        }
 
3202
 
 
3203
        for ($addr = 0x03; $addr <= 0x77; $addr++) {
 
3204
                push @addresses, $addr if $used[$addr];
 
3205
        }
 
3206
        return \@addresses;
 
3207
}
 
3208
 
 
3209
# $_[0]: The number of the adapter to scan
 
3210
# $_[1]: Address
 
3211
sub add_busy_i2c_address
 
3212
{
 
3213
        my ($adapter_nr, $addr) = @_;
 
3214
        # If the address is busy, we can normally find out which driver
 
3215
        # requested it (if the kernel is recent enough, at least 2.6.16 and
 
3216
        # later are known to work), and we assume it is the right one.
 
3217
        my ($device, $driver, $new_hash);
 
3218
 
 
3219
        $device = sprintf("$sysfs_root/bus/i2c/devices/\%d-\%04x",
 
3220
                          $adapter_nr, $addr);
 
3221
        $driver = sysfs_device_driver($device);
 
3222
 
 
3223
        if (!defined($driver)) {
 
3224
                printf("Client at address 0x%02x can not be probed - ".
 
3225
                       "unload all client drivers first!\n", $addr);
 
3226
                return;
 
3227
        }
 
3228
 
 
3229
        $new_hash = {
 
3230
                conf => 6, # Arbitrary confidence
 
3231
                i2c_addr => $addr,
 
3232
                chipname => sysfs_device_attribute($device, "name")
 
3233
                         || "unknown",
 
3234
                i2c_devnr => $adapter_nr,
 
3235
        };
 
3236
 
 
3237
        printf "Client found at address 0x\%02x\n", $addr;
 
3238
        printf "Handled by driver `\%s' (already loaded), chip type `\%s'\n",
 
3239
               $driver, $new_hash->{chipname};
 
3240
 
 
3241
        # Only add it to the list if this is something we would have detected,
 
3242
        # else we end up with random i2c chip drivers listed (for example
 
3243
        # media/video drivers.)
 
3244
        if (exists $modules_supported{$driver}) {
 
3245
                add_i2c_to_chips_detected($driver, $new_hash);
 
3246
        } else {
 
3247
                print "    (note: this is probably NOT a sensor chip!)\n";
 
3248
        }
 
3249
}
 
3250
 
 
3251
# $_[0]: The number of the adapter to scan
 
3252
# $_[1]: Address
 
3253
# $_[2]: Chip being probed
 
3254
sub probe_free_i2c_address
 
3255
{
 
3256
        my ($adapter_nr, $addr, $chip) = @_;
 
3257
        my ($conf, @other_addr, $new_hash);
 
3258
 
 
3259
        printf("\%-60s", sprintf("Probing for `\%s'... ", $chip->{name}));
 
3260
        if (($conf, @other_addr) = &{$chip->{i2c_detect}} (\*FILE, $addr)) {
 
3261
                if ($chip->{driver} eq "not-a-sensor") {
 
3262
                        print "Yes\n",
 
3263
                              "    (confidence $conf, not a hardware monitoring chip";
 
3264
                } else {
 
3265
                        print "Success!\n",
 
3266
                              "    (confidence $conf, driver `$chip->{driver}'";
 
3267
                }
 
3268
                if (@other_addr) {
 
3269
                        print ", other addresses:";
 
3270
                        @other_addr = sort @other_addr;
 
3271
                        foreach my $other_addr (@other_addr) {
 
3272
                                printf(" 0x%02x", $other_addr);
 
3273
                        }
 
3274
                }
 
3275
                print ")\n";
 
3276
 
 
3277
                $new_hash = {
 
3278
                        conf => $conf,
 
3279
                        i2c_addr => $addr,
 
3280
                        chipname => $chip->{name},
 
3281
                        i2c_devnr => $adapter_nr,
 
3282
                };
 
3283
                if (@other_addr) {
 
3284
                        my @other_addr_copy = @other_addr;
 
3285
                        $new_hash->{i2c_sub_addrs} = \@other_addr_copy;
 
3286
                }
 
3287
                add_i2c_to_chips_detected($chip->{driver}, $new_hash);
 
3288
        } else {
 
3289
                print "No\n";
 
3290
        }
 
3291
}
 
3292
 
 
3293
# $_[0]: The device to check (PCI or not)
 
3294
# Returns: PCI class of the adapter if available, 0 if not
 
3295
sub get_pci_class
 
3296
{
 
3297
        my ($device) = @_;
 
3298
        my ($subsystem, $class);
 
3299
 
 
3300
        $subsystem = sysfs_device_subsystem($device);
 
3301
        return 0 unless defined $subsystem && $subsystem eq "pci";
 
3302
 
 
3303
        $class = sysfs_device_attribute($device, "class");
 
3304
        return 0 unless defined $class;
 
3305
        $class = oct($class) if $class =~ /^0/;
 
3306
        return $class >> 8;
 
3307
}
 
3308
 
 
3309
# $_[0]: The number of the adapter to scan
 
3310
sub scan_i2c_adapter
 
3311
{
 
3312
        my ($adapter_nr, $smbus_default) = @_;
 
3313
        my ($funcs, $chip, $addr, $class, $default, $input, @not_to_scan);
 
3314
 
 
3315
        $class = get_pci_class($i2c_adapters[$adapter_nr]->{parent});
 
3316
        if (($class & 0xff00) == 0x0400) {
 
3317
                # Do not probe adapters on PCI multimedia cards by default
 
3318
                $default = 0;
 
3319
        } elsif ($class == 0x0c01 || $class == 0x0c05
 
3320
              || find_i2c_adapter_driver($i2c_adapters[$adapter_nr]->{name})) {
 
3321
                $default = $smbus_default;
 
3322
        } else {
 
3323
                $default = 1;
 
3324
        }
 
3325
 
 
3326
        printf "Next adapter: $i2c_adapters[$adapter_nr]->{name} (i2c-$adapter_nr)\n".
 
3327
               "Do you want to scan it? (\%s/selectively): ",
 
3328
               $default ? "YES/no" : "yes/NO";
 
3329
 
 
3330
        $input = <STDIN>;
 
3331
        if ($input =~ /^\s*n/i
 
3332
         || (!$default && $input !~ /^\s*[ys]/i)) {
 
3333
                print "\n";
 
3334
                return;
 
3335
        }
 
3336
 
 
3337
        if ($input =~ /^\s*s/i) {
 
3338
                print "Please enter one or more addresses not to scan. Separate them with commas.\n",
 
3339
                      "You can specify a range by using dashes. Example: 0x58-0x5f,0x69.\n",
 
3340
                      "Addresses: ";
 
3341
                $input = <STDIN>;
 
3342
                chomp($input);
 
3343
                @not_to_scan = parse_not_to_scan(0x03, 0x77, $input);
 
3344
        }
 
3345
 
 
3346
        open(local *FILE, "$dev_i2c$adapter_nr") or
 
3347
                (print "Can't open $dev_i2c$adapter_nr\n"), return;
 
3348
        binmode(FILE);
 
3349
 
 
3350
        # Can we probe this adapter?
 
3351
        $funcs = i2c_get_funcs(\*FILE);
 
3352
        if ($funcs < 0) {
 
3353
                print "Adapter failed to provide its functionalities, skipping.\n";
 
3354
                return;
 
3355
        }
 
3356
        if (!($funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA))) {
 
3357
                print "Adapter cannot be probed, skipping.\n";
 
3358
                return;
 
3359
        }
 
3360
        if (~$funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
 
3361
                print "Adapter doesn't support all probing functions.\n",
 
3362
                      "Some addresses won't be probed.\n";
 
3363
        }
 
3364
 
 
3365
        # Now scan each address in turn
 
3366
        foreach $addr (@{$i2c_addresses_to_scan}) {
 
3367
                # As the not_to_scan list is sorted, we can check it fast
 
3368
                shift @not_to_scan # User skipped an address which we didn't intend to probe anyway
 
3369
                        while (@not_to_scan and $not_to_scan[0] < $addr);
 
3370
                if (@not_to_scan and $not_to_scan[0] == $addr) {
 
3371
                        shift @not_to_scan;
 
3372
                        next;
 
3373
                }
 
3374
 
 
3375
                if (!i2c_set_slave_addr(\*FILE, $addr)) {
 
3376
                        add_busy_i2c_address($adapter_nr, $addr);
 
3377
                        next;
 
3378
                }
 
3379
 
 
3380
                next unless i2c_probe(\*FILE, $addr, $funcs);
 
3381
                printf "Client found at address 0x%02x\n", $addr;
 
3382
                if (!i2c_safety_check(\*FILE)) {
 
3383
                        print "Seems to be a 1-register-only device, skipping.\n";
 
3384
                        next;
 
3385
                }
 
3386
 
 
3387
                $| = 1;
 
3388
                foreach $chip (@chip_ids, @non_hwmon_chip_ids) {
 
3389
                        next unless exists $chip->{i2c_addrs}
 
3390
                                 && contains($addr, @{$chip->{i2c_addrs}});
 
3391
                        probe_free_i2c_address($adapter_nr, $addr, $chip);
 
3392
                }
 
3393
                $| = 0;
 
3394
        }
 
3395
        print "\n";
 
3396
}
 
3397
 
 
3398
sub scan_isa_bus
 
3399
{
 
3400
        my $chip_list_ref = shift;
 
3401
        my ($chip, $addr, $conf);
 
3402
 
 
3403
        $| = 1;
 
3404
        foreach $chip (@{$chip_list_ref}) {
 
3405
                next if not exists $chip->{isa_addrs} or not exists $chip->{isa_detect};
 
3406
                foreach $addr (@{$chip->{isa_addrs}}) {
 
3407
                        printf("\%-60s", sprintf("Probing for `\%s' at 0x\%x... ",
 
3408
                                                 $chip->{name}, $addr));
 
3409
                        $conf = &{$chip->{isa_detect}} ($addr);
 
3410
                        print("No\n"), next if not defined $conf;
 
3411
                        print "Success!\n";
 
3412
                        printf "    (confidence %d, driver `%s')\n", $conf, $chip->{driver};
 
3413
                        my $new_hash = {
 
3414
                                conf => $conf,
 
3415
                                isa_addr => $addr,
 
3416
                                chipname => $chip->{name},
 
3417
                                alias_detect => $chip->{alias_detect},
 
3418
                        };
 
3419
                        add_isa_to_chips_detected($chip->{driver}, $new_hash);
 
3420
                }
 
3421
        }
 
3422
        $| = 0;
 
3423
}
 
3424
 
 
3425
use vars qw(%superio);
 
3426
 
 
3427
# The following are taken from the PNP ISA spec (so it's supposed
 
3428
# to be common to all Super I/O chips):
 
3429
#  devidreg: The device ID register(s)
 
3430
#  logdevreg: The logical device register
 
3431
#  actreg: The activation register within the logical device
 
3432
#  actmask: The activation bit in the activation register
 
3433
#  basereg: The I/O base register within the logical device
 
3434
%superio = (
 
3435
        devidreg => 0x20,
 
3436
        logdevreg => 0x07,
 
3437
        actreg => 0x30,
 
3438
        actmask => 0x01,
 
3439
        basereg => 0x60,
 
3440
);
 
3441
 
 
3442
sub exit_superio
 
3443
{
 
3444
        my ($addrreg, $datareg) = @_;
 
3445
 
 
3446
        # Some chips (SMSC, Winbond) want this
 
3447
        outb($addrreg, 0xaa);
 
3448
 
 
3449
        # Return to "Wait For Key" state (PNP-ISA spec)
 
3450
        outb($addrreg, 0x02);
 
3451
        outb($datareg, 0x02);
 
3452
}
 
3453
 
 
3454
# Guess if an unknown Super-I/O chip has sensors
 
3455
sub guess_superio_ld
 
3456
{
 
3457
        my ($addrreg, $datareg, $typical_addr) = @_;
 
3458
        my ($oldldn, $ldn, $addr);
 
3459
 
 
3460
        # Save logical device number
 
3461
        outb($addrreg, $superio{logdevreg});
 
3462
        $oldldn = inb($datareg);
 
3463
 
 
3464
        for ($ldn = 0; $ldn < 16; $ldn++) {
 
3465
                # Select logical device
 
3466
                outb($addrreg, $superio{logdevreg});
 
3467
                outb($datareg, $ldn);
 
3468
 
 
3469
                # Read base I/O address
 
3470
                outb($addrreg, $superio{basereg});
 
3471
                $addr = inb($datareg) << 8;
 
3472
                outb($addrreg, $superio{basereg} + 1);
 
3473
                $addr |= inb($datareg);
 
3474
                next unless ($addr & 0xfff8) == $typical_addr;
 
3475
 
 
3476
                printf "    (logical device \%X has address 0x\%x, could be sensors)\n",
 
3477
                       $ldn, $addr;
 
3478
                last;
 
3479
        }
 
3480
 
 
3481
        # Be nice, restore original logical device
 
3482
        outb($addrreg, $superio{logdevreg});
 
3483
        outb($datareg, $oldldn);
 
3484
}
 
3485
 
 
3486
# Returns: features bitmask if device added to chips_detected, 0 if not
 
3487
sub probe_superio
 
3488
{
 
3489
        my ($addrreg, $datareg, $chip) = @_;
 
3490
        my ($val, $addr);
 
3491
 
 
3492
        if (exists $chip->{check}) {
 
3493
                return 0 unless $chip->{check}($addrreg, $datareg);
 
3494
        }
 
3495
 
 
3496
        printf "\%-60s", "Found `$chip->{name}'";
 
3497
 
 
3498
        # Does it have hardware monitoring capabilities?
 
3499
        if (!exists $chip->{driver}) {
 
3500
                print "\n    (no information available)\n";
 
3501
                return 0;
 
3502
        }
 
3503
        if ($chip->{driver} eq "not-a-sensor") {
 
3504
                print "\n    (no hardware monitoring capabilities)\n";
 
3505
                return 0;
 
3506
        }
 
3507
        if ($chip->{driver} eq "via-smbus-only") {
 
3508
                print "\n    (hardware monitoring capabilities accessible via SMBus only)\n";
 
3509
                return FEAT_SMBUS;
 
3510
        }
 
3511
 
 
3512
        # Switch to the sensor logical device
 
3513
        outb($addrreg, $superio{logdevreg});
 
3514
        outb($datareg, $chip->{logdev});
 
3515
 
 
3516
        # Get the IO base address
 
3517
        outb($addrreg, $superio{basereg});
 
3518
        $addr = inb($datareg);
 
3519
        outb($addrreg, $superio{basereg} + 1);
 
3520
        $addr = ($addr << 8) | inb($datareg);
 
3521
 
 
3522
        # Check the activation register and base address
 
3523
        outb($addrreg, $superio{actreg});
 
3524
        $val = inb($datareg);
 
3525
        if (!($val & $superio{actmask})) {
 
3526
                if ($addr) {
 
3527
                        printf "\n    (address 0x\%x, but not activated)\n", $addr;
 
3528
                } else {
 
3529
                        print "\n    (but not activated)\n";
 
3530
                }
 
3531
                return 0;
 
3532
        }
 
3533
        if ($addr == 0) {
 
3534
                print "\n    (but no address specified)\n";
 
3535
                return 0;
 
3536
        }
 
3537
 
 
3538
        print "Success!\n";
 
3539
        printf "    (address 0x\%x, driver `%s')\n", $addr, $chip->{driver};
 
3540
        my $new_hash = {
 
3541
                conf => 9,
 
3542
                isa_addr => $addr,
 
3543
                chipname => $chip->{name}
 
3544
        };
 
3545
        add_isa_to_chips_detected($chip->{driver}, $new_hash);
 
3546
        return $chip->{features};
 
3547
}
 
3548
 
 
3549
# Detection routine for non-standard SMSC Super I/O chips
 
3550
# $_[0]: Super I/O LPC config/index port
 
3551
# $_[1]: Super I/O LPC data port
 
3552
# $_[2]: Reference to array of non-standard chips
 
3553
# Return values: 1 if non-standard chip found, 0 otherwise
 
3554
sub smsc_ns_detect_superio
 
3555
{
 
3556
        my ($addrreg, $datareg, $ns_chips) = @_;
 
3557
        my ($val, $chip);
 
3558
 
 
3559
        # read alternate device ID register
 
3560
        outb($addrreg, 0x0d);
 
3561
        $val = inb($datareg);
 
3562
        return 0 if $val == 0x00 || $val == 0xff;
 
3563
 
 
3564
        print "Yes\n";
 
3565
 
 
3566
        foreach $chip (@{$ns_chips}) {
 
3567
                if ($chip->{devid} == $val) {
 
3568
                        probe_superio($addrreg, $datareg, $chip);
 
3569
                        return 1;
 
3570
                }
 
3571
        }
 
3572
 
 
3573
        printf("Found unknown non-standard chip with ID 0x%02x\n", $val);
 
3574
        return 1;
 
3575
}
 
3576
 
 
3577
# Returns: features supported by the device added, if any
 
3578
sub scan_superio
 
3579
{
 
3580
        my ($addrreg, $datareg) = @_;
 
3581
        my ($val, $found);
 
3582
        my $features = 0;
 
3583
 
 
3584
        printf("Probing for Super-I/O at 0x\%x/0x\%x\n", $addrreg, $datareg);
 
3585
 
 
3586
        $| = 1;
 
3587
        # reset state to avoid false positives
 
3588
        exit_superio($addrreg, $datareg);
 
3589
        foreach my $family (@superio_ids) {
 
3590
                printf("\%-60s", "Trying family `$family->{family}'... ");
 
3591
                # write the password
 
3592
                foreach $val (@{$family->{enter}->{$addrreg}}) {
 
3593
                        outb($addrreg, $val);
 
3594
                }
 
3595
                # call the non-standard detection routine first if it exists
 
3596
                if (defined($family->{ns_detect}) &&
 
3597
                    &{$family->{ns_detect}}($addrreg, $datareg, $family->{ns_chips})) {
 
3598
                        last;
 
3599
                }
 
3600
 
 
3601
                # did it work?
 
3602
                outb($addrreg, $superio{devidreg});
 
3603
                $val = inb($datareg);
 
3604
                outb($addrreg, $superio{devidreg} + 1);
 
3605
                $val = ($val << 8) | inb($datareg);
 
3606
                if ($val == 0x0000 || $val == 0xffff) {
 
3607
                        print "No\n";
 
3608
                        next;
 
3609
                }
 
3610
                print "Yes\n";
 
3611
 
 
3612
                $found = 0;
 
3613
                foreach my $chip (@{$family->{chips}}) {
 
3614
                        if (($chip->{devid} > 0xff &&
 
3615
                             ($val & ($chip->{devid_mask} || 0xffff)) == $chip->{devid})
 
3616
                         || ($chip->{devid} <= 0xff &&
 
3617
                             ($val >> 8) == $chip->{devid})) {
 
3618
                                $features |= probe_superio($addrreg, $datareg, $chip);
 
3619
                                $found++;
 
3620
                        }
 
3621
                }
 
3622
 
 
3623
                if (!$found) {
 
3624
                        printf("Found unknown chip with ID 0x%04x\n", $val);
 
3625
                        # Guess if a logical device could correspond to sensors
 
3626
                        guess_superio_ld($addrreg, $datareg, $family->{guess})
 
3627
                                if defined $family->{guess};
 
3628
                }
 
3629
                last;
 
3630
        }
 
3631
        exit_superio($addrreg, $datareg);
 
3632
        $| = 0;
 
3633
        return $features;
 
3634
}
 
3635
 
 
3636
sub scan_cpu
 
3637
{
 
3638
        my $entry = shift;
 
3639
        my $confidence;
 
3640
 
 
3641
        printf("\%-60s", "$entry->{name}... ");
 
3642
        if (defined ($confidence = $entry->{detect}())) {
 
3643
                print "Success!\n";
 
3644
                printf "    (driver `%s')\n", $entry->{driver};
 
3645
                my $new_hash = {
 
3646
                        conf => $confidence,
 
3647
                        chipname => $entry->{name},
 
3648
                };
 
3649
                add_isa_to_chips_detected($entry->{driver}, $new_hash);
 
3650
        } else {
 
3651
                print "No\n";
 
3652
        }
 
3653
}
 
3654
 
 
3655
##################
 
3656
# CHIP DETECTION #
 
3657
##################
 
3658
 
 
3659
# This routine allows you to dynamically update the chip detection list.
 
3660
# The most common use is to allow for different chip to driver mappings
 
3661
# based on different linux kernels
 
3662
sub chip_special_cases
 
3663
{
 
3664
        # Some chip to driver mappings depend on the environment
 
3665
        foreach my $chip (@chip_ids) {
 
3666
                if (ref($chip->{driver}) eq 'CODE') {
 
3667
                        $chip->{driver} = $chip->{driver}->();
 
3668
                }
 
3669
        }
 
3670
 
 
3671
        # Also fill the fake driver name of non-hwmon chips
 
3672
        foreach my $chip (@non_hwmon_chip_ids) {
 
3673
                $chip->{driver} = "not-a-sensor";
 
3674
        }
 
3675
}
 
3676
 
 
3677
# Each function returns a confidence value. The higher this value, the more
 
3678
# sure we are about this chip. This may help overrule false positives,
 
3679
# although we also attempt to prevent false positives in the first place.
 
3680
 
 
3681
# Each function returns a list. The first element is the confidence value;
 
3682
# Each element after it is an SMBus address. In this way, we can detect
 
3683
# chips with several SMBus addresses. The SMBus address for which the
 
3684
# function was called is never returned.
 
3685
 
 
3686
# All I2C detection functions below take at least 2 parameters:
 
3687
# $_[0]: Reference to the file descriptor to access the chip
 
3688
# $_[1]: Address
 
3689
# Some of these functions which can detect more than one type of device,
 
3690
# take a third parameter:
 
3691
# $_[2]: Chip to detect
 
3692
 
 
3693
# Registers used: 0x58
 
3694
sub mtp008_detect
 
3695
{
 
3696
        my ($file, $addr) = @_;
 
3697
        return if i2c_smbus_read_byte_data($file, 0x58) != 0xac;
 
3698
        return 3;
 
3699
}
 
3700
 
 
3701
# Chip to detect: 0 = LM78, 2 = LM79
 
3702
# Registers used:
 
3703
#   0x40: Configuration
 
3704
#   0x48: Full I2C Address
 
3705
#   0x49: Device ID
 
3706
sub lm78_detect
 
3707
{
 
3708
        my ($file, $addr, $chip) = @_;
 
3709
        my $reg;
 
3710
 
 
3711
        return unless i2c_smbus_read_byte_data($file, 0x48) == $addr;
 
3712
        return unless (i2c_smbus_read_byte_data($file, 0x40) & 0x80) == 0x00;
 
3713
 
 
3714
        $reg = i2c_smbus_read_byte_data($file, 0x49);
 
3715
        return if $chip == 0 && ($reg != 0x00 && $reg != 0x20 && $reg != 0x40);
 
3716
        return if $chip == 2 && ($reg & 0xfe) != 0xc0;
 
3717
 
 
3718
        # Explicitly prevent misdetection of Winbond chips
 
3719
        $reg = i2c_smbus_read_byte_data($file, 0x4f);
 
3720
        return if $reg == 0xa3 || $reg == 0x5c;
 
3721
 
 
3722
        return 6;
 
3723
}
 
3724
 
 
3725
# Chip to detect: 0 = LM75, 1 = DS75
 
3726
# Registers used:
 
3727
#   0x00: Temperature
 
3728
#   0x01: Configuration
 
3729
#   0x02: Hysteresis
 
3730
#   0x03: Overtemperature Shutdown
 
3731
#   0x04-0x07: No registers
 
3732
# The first detection step is based on the fact that the LM75 has only
 
3733
# four registers, and cycles addresses over 8-byte boundaries. We use the
 
3734
# 0x04-0x07 addresses (unused) to improve the reliability. These are not
 
3735
# real registers and will always return the last returned value. This isn't
 
3736
# documented.
 
3737
# Note that register 0x00 may change, so we can't use the modulo trick on it.
 
3738
# The DS75 is a bit different, it doesn't cycle over 8-byte boundaries, and
 
3739
# all register addresses from 0x04 to 0x0f behave like 0x04-0x07 do for
 
3740
# the LM75.
 
3741
# Not all devices enjoy SMBus read word transactions, so we use read byte
 
3742
# transactions even for the 16-bit registers. The low bits aren't very
 
3743
# useful for detection anyway.
 
3744
sub lm75_detect
 
3745
{
 
3746
        my ($file, $addr, $chip) = @_;
 
3747
        my $i;
 
3748
        my $cur = i2c_smbus_read_byte_data($file, 0x00);
 
3749
        my $conf = i2c_smbus_read_byte_data($file, 0x01);
 
3750
 
 
3751
        my $hyst = i2c_smbus_read_byte_data($file, 0x02, NO_CACHE);
 
3752
        my $maxreg = $chip == 1 ? 0x0f : 0x07;
 
3753
        for $i (0x04 .. $maxreg) {
 
3754
                return if i2c_smbus_read_byte_data($file, $i, NO_CACHE) != $hyst;
 
3755
        }
 
3756
 
 
3757
        my $os = i2c_smbus_read_byte_data($file, 0x03, NO_CACHE);
 
3758
        for $i (0x04 .. $maxreg) {
 
3759
                return if i2c_smbus_read_byte_data($file, $i, NO_CACHE) != $os;
 
3760
        }
 
3761
 
 
3762
        if ($chip == 0) {
 
3763
                for ($i = 8; $i <= 248; $i += 40) {
 
3764
                        return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf
 
3765
                               or i2c_smbus_read_byte_data($file, $i + 0x02) != $hyst
 
3766
                               or i2c_smbus_read_byte_data($file, $i + 0x03) != $os;
 
3767
                }
 
3768
        }
 
3769
 
 
3770
        # All registers hold the same value, obviously a misdetection
 
3771
        return if $conf == $cur and $cur == $hyst and $cur == $os;
 
3772
 
 
3773
        # Unused bits
 
3774
        return if $chip == 0 and ($conf & 0xe0);
 
3775
        return if $chip == 1 and ($conf & 0x80);
 
3776
 
 
3777
        # Most probable value ranges
 
3778
        return 6 if $cur <= 100 and ($hyst >= 10 && $hyst <= 125)
 
3779
                and ($os >= 20 && $os <= 127) and $hyst < $os;
 
3780
        return 3;
 
3781
}
 
3782
 
 
3783
# Registers used:
 
3784
#   0x00: Temperature
 
3785
#   0x01: Configuration
 
3786
#   0x02: High Limit
 
3787
#   0x03: Low Limit
 
3788
#   0x04: Status
 
3789
#   0x07: Manufacturer ID and Product ID
 
3790
sub lm73_detect
 
3791
{
 
3792
        my ($file, $addr) = @_;
 
3793
 
 
3794
        my $conf = i2c_smbus_read_byte_data($file, 0x01);
 
3795
        my $status = i2c_smbus_read_byte_data($file, 0x04);
 
3796
 
 
3797
        # Bits that always return 0
 
3798
        return if ($conf & 0x0c) or ($status & 0x10);
 
3799
 
 
3800
        return if i2c_smbus_read_word_data($file, 0x07) != 0x9001;
 
3801
 
 
3802
        # Make sure the chip supports SMBus read word transactions
 
3803
        my $cur = i2c_smbus_read_word_data($file, 0x00);
 
3804
        return if $cur < 0;
 
3805
        my $high = i2c_smbus_read_word_data($file, 0x02);
 
3806
        return if $high < 0;
 
3807
        my $low = i2c_smbus_read_word_data($file, 0x03);
 
3808
        return if $low < 0;
 
3809
        return if ($cur & 0x0300) or (($high | $low) & 0x1f00);
 
3810
 
 
3811
        return 3;
 
3812
}
 
3813
 
 
3814
# Registers used:
 
3815
#   0x00: Temperature
 
3816
#   0x01: Configuration
 
3817
#   0x02: Hysteresis
 
3818
#   0x03: Overtemperature Shutdown
 
3819
#   0x04: Low limit
 
3820
#   0x05: High limit
 
3821
#   0x06-0x07: No registers
 
3822
# The first detection step is based on the fact that the LM77 has only
 
3823
# six registers, and cycles addresses over 8-byte boundaries. We use the
 
3824
# 0x06-0x07 addresses (unused) to improve the reliability. These are not
 
3825
# real registers and will always return the last returned value. This isn't
 
3826
# documented.
 
3827
# Note that register 0x00 may change, so we can't use the modulo trick on it.
 
3828
# Not all devices enjoy SMBus read word transactions, so we use read byte
 
3829
# transactions even for the 16-bit registers at first. We only use read word
 
3830
# transactions in the end when we are already almost certain that we have an
 
3831
# LM77 chip.
 
3832
sub lm77_detect
 
3833
{
 
3834
        my ($file, $addr) = @_;
 
3835
        my $i;
 
3836
        my $cur = i2c_smbus_read_byte_data($file, 0x00);
 
3837
        my $conf = i2c_smbus_read_byte_data($file, 0x01);
 
3838
        my $hyst = i2c_smbus_read_byte_data($file, 0x02);
 
3839
        my $os = i2c_smbus_read_byte_data($file, 0x03);
 
3840
 
 
3841
        my $low = i2c_smbus_read_byte_data($file, 0x04, NO_CACHE);
 
3842
        return if i2c_smbus_read_byte_data($file, 0x06, NO_CACHE) != $low;
 
3843
        return if i2c_smbus_read_byte_data($file, 0x07, NO_CACHE) != $low;
 
3844
 
 
3845
        my $high = i2c_smbus_read_byte_data($file, 0x05, NO_CACHE);
 
3846
        return if i2c_smbus_read_byte_data($file, 0x06, NO_CACHE) != $high;
 
3847
        return if i2c_smbus_read_byte_data($file, 0x07, NO_CACHE) != $high;
 
3848
 
 
3849
        for ($i = 8; $i <= 248; $i += 40) {
 
3850
                return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf;
 
3851
                return if i2c_smbus_read_byte_data($file, $i + 0x02) != $hyst;
 
3852
                return if i2c_smbus_read_byte_data($file, $i + 0x03) != $os;
 
3853
                return if i2c_smbus_read_byte_data($file, $i + 0x04) != $low;
 
3854
                return if i2c_smbus_read_byte_data($file, $i + 0x05) != $high;
 
3855
        }
 
3856
 
 
3857
        # All registers hold the same value, obviously a misdetection
 
3858
        return if $conf == $cur and $cur == $hyst
 
3859
              and $cur == $os and $cur == $low and $cur == $high;
 
3860
 
 
3861
        # Unused bits
 
3862
        return if ($conf & 0xe0)
 
3863
               or (($cur >> 4) != 0 && ($cur >> 4) != 0xf)
 
3864
               or (($hyst >> 4) != 0 && ($hyst >> 4) != 0xf)
 
3865
               or (($os >> 4) != 0 && ($os >> 4) != 0xf)
 
3866
               or (($low >> 4) != 0 && ($low >> 4) != 0xf)
 
3867
               or (($high >> 4) != 0 && ($high >> 4) != 0xf);
 
3868
 
 
3869
        # Make sure the chip supports SMBus read word transactions
 
3870
        foreach $i (0x00, 0x02, 0x03, 0x04, 0x05) {
 
3871
                return if i2c_smbus_read_word_data($file, $i) < 0;
 
3872
        }
 
3873
 
 
3874
        return 3;
 
3875
}
 
3876
 
 
3877
# Chip to detect: 0 = LM92, 1 = LM76, 2 = MAX6633/MAX6634/MAX6635
 
3878
# Registers used:
 
3879
#   0x01: Configuration (National Semiconductor only)
 
3880
#   0x02: Hysteresis
 
3881
#   0x03: Critical Temp
 
3882
#   0x04: Low Limit
 
3883
#   0x05: High Limit
 
3884
#   0x07: Manufacturer ID (LM92 only)
 
3885
# One detection step is based on the fact that the LM92 and clones have a
 
3886
# limited number of registers, which cycle modulo 16 address values.
 
3887
# Note that register 0x00 may change, so we can't use the modulo trick on it.
 
3888
# Not all devices enjoy SMBus read word transactions, so we use read byte
 
3889
# transactions even for the 16-bit registers at first. We only use read
 
3890
# word transactions in the end when we are already almost certain that we
 
3891
# have an LM92 chip or compatible.
 
3892
sub lm92_detect
 
3893
{
 
3894
        my ($file, $addr, $chip) = @_;
 
3895
 
 
3896
        my $conf = i2c_smbus_read_byte_data($file, 0x01);
 
3897
        my $hyst = i2c_smbus_read_byte_data($file, 0x02);
 
3898
        my $crit = i2c_smbus_read_byte_data($file, 0x03);
 
3899
        my $low = i2c_smbus_read_byte_data($file, 0x04);
 
3900
        my $high = i2c_smbus_read_byte_data($file, 0x05);
 
3901
 
 
3902
        return if $conf == 0 and $hyst == 0 and $crit == 0
 
3903
                and $low == 0 and $high == 0;
 
3904
 
 
3905
        # Unused bits
 
3906
        return if ($chip == 0 || $chip == 1)
 
3907
              and ($conf & 0xE0);
 
3908
 
 
3909
        for (my $i = 0; $i <= 240; $i += 16) {
 
3910
                return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf;
 
3911
                return if i2c_smbus_read_byte_data($file, $i + 0x02) != $hyst;
 
3912
                return if i2c_smbus_read_byte_data($file, $i + 0x03) != $crit;
 
3913
                return if i2c_smbus_read_byte_data($file, $i + 0x04) != $low;
 
3914
                return if i2c_smbus_read_byte_data($file, $i + 0x05) != $high;
 
3915
        }
 
3916
 
 
3917
        return if $chip == 0
 
3918
              and i2c_smbus_read_word_data($file, 0x07) != 0x0180;
 
3919
 
 
3920
        # Make sure the chip supports SMBus read word transactions
 
3921
        $hyst = i2c_smbus_read_word_data($file, 0x02);
 
3922
        return if $hyst < 0;
 
3923
        $crit = i2c_smbus_read_word_data($file, 0x03);
 
3924
        return if $crit < 0;
 
3925
        $low = i2c_smbus_read_word_data($file, 0x04);
 
3926
        return if $low < 0;
 
3927
        $high = i2c_smbus_read_word_data($file, 0x05);
 
3928
        return if $high < 0;
 
3929
 
 
3930
        foreach my $temp ($hyst, $crit, $low, $high) {
 
3931
                return if $chip == 2 and ($temp & 0x7F00);
 
3932
                return if $chip != 2 and ($temp & 0x0700);
 
3933
        }
 
3934
 
 
3935
        return ($chip == 0) ? 4 : 2;
 
3936
}
 
3937
 
 
3938
# Registers used:
 
3939
#   0xAA: Temperature
 
3940
#   0xA1: High limit
 
3941
#   0xA2: Low limit
 
3942
#   0xA8: Counter
 
3943
#   0xA9: Slope
 
3944
#   0xAC: Configuration
 
3945
# Detection is weak. We check if bit 4 (NVB) is clear, because it is
 
3946
# unlikely to be set (would mean that EEPROM is currently being accessed).
 
3947
# We also check the value of the counter and slope registers, the datasheet
 
3948
# doesn't mention the possible values but the conversion formula together
 
3949
# with experimental evidence suggest possible sanity checks.
 
3950
# Not all devices enjoy SMBus read word transactions, so we do as much as
 
3951
# possible with read byte transactions first, and only use read word
 
3952
# transactions second.
 
3953
sub ds1621_detect
 
3954
{
 
3955
        my ($file, $addr) = @_;
 
3956
 
 
3957
        my $conf = i2c_smbus_read_byte_data($file, 0xAC);
 
3958
        return if ($conf & 0x10);
 
3959
 
 
3960
        my $temp = i2c_smbus_read_word_data($file, 0xAA);
 
3961
        return if $temp < 0 || ($temp & 0x0f00);
 
3962
        # On the DS1631, the following two checks are too strict in theory,
 
3963
        # but in practice I very much doubt that anyone will set temperature
 
3964
        # limits not a multiple of 0.5 degrees C.
 
3965
        my $high = i2c_smbus_read_word_data($file, 0xA1);
 
3966
        return if $high < 0 || ($high & 0x7f00);
 
3967
        my $low = i2c_smbus_read_word_data($file, 0xA2);
 
3968
        return if $low < 0 || ($low & 0x7f00);
 
3969
 
 
3970
        return if ($temp == 0 && $high == 0 && $low == 0 && $conf == 0);
 
3971
 
 
3972
        # Old versions of the DS1621 apparently don't have the counter and
 
3973
        # slope registers (or they return crap)
 
3974
        my $counter = i2c_smbus_read_byte_data($file, 0xA8);
 
3975
        my $slope = i2c_smbus_read_byte_data($file, 0xA9);
 
3976
        return ($slope == 0x10 && $counter <= $slope) ? 3 : 2;
 
3977
}
 
3978
 
 
3979
# Registers used:
 
3980
#   0x00: Configuration register
 
3981
#   0x02: Interrupt state register
 
3982
#   0x2a-0x3d: Limits registers
 
3983
# This one is easily misdetected since it doesn't provide identification
 
3984
# registers. So we have to use some tricks:
 
3985
#   - 6-bit addressing, so limits readings modulo 0x40 should be unchanged
 
3986
#   - positive temperature limits
 
3987
#   - limits order correctness
 
3988
# Hopefully this should limit the rate of false positives, without increasing
 
3989
# the rate of false negatives.
 
3990
# Thanks to Lennard Klein for testing on a non-LM80 chip, which was
 
3991
# previously misdetected, and isn't anymore. For reference, it scored
 
3992
# a final confidence of 0, and changing from strict limit comparisons
 
3993
# to loose comparisons did not change the score.
 
3994
sub lm80_detect
 
3995
{
 
3996
        my ($file, $addr) = @_;
 
3997
        my ($i, $reg);
 
3998
 
 
3999
        return if (i2c_smbus_read_byte_data($file, 0x00) & 0x80) != 0;
 
4000
        return if (i2c_smbus_read_byte_data($file, 0x02) & 0xc0) != 0;
 
4001
 
 
4002
        for ($i = 0x2a; $i <= 0x3d; $i++) {
 
4003
                $reg = i2c_smbus_read_byte_data($file, $i);
 
4004
                return if i2c_smbus_read_byte_data($file, $i+0x40) != $reg;
 
4005
                return if i2c_smbus_read_byte_data($file, $i+0x80) != $reg;
 
4006
                return if i2c_smbus_read_byte_data($file, $i+0xc0) != $reg;
 
4007
        }
 
4008
 
 
4009
        # Refine a bit by checking whether limits are in the correct order
 
4010
        # (min<max for voltages, hyst<max for temperature). Since it is still
 
4011
        # possible that the chip is an LM80 with limits not properly set,
 
4012
        # a few "errors" are tolerated.
 
4013
        my $confidence = 0;
 
4014
        for ($i = 0x2a; $i <= 0x3a; $i++) {
 
4015
                $confidence++
 
4016
                        if i2c_smbus_read_byte_data($file, $i) < i2c_smbus_read_byte_data($file, $i+1);
 
4017
        }
 
4018
        # hot temp<OS temp
 
4019
        $confidence++
 
4020
                if i2c_smbus_read_byte_data($file, 0x38) < i2c_smbus_read_byte_data($file, 0x3a);
 
4021
 
 
4022
        # Negative temperature limits are unlikely.
 
4023
        for ($i = 0x3a; $i <= 0x3d; $i++) {
 
4024
                $confidence++ if (i2c_smbus_read_byte_data($file, $i) & 0x80) == 0;
 
4025
        }
 
4026
 
 
4027
        # $confidence is between 0 and 14
 
4028
        $confidence = ($confidence >> 1) - 4;
 
4029
        # $confidence is now between -4 and 3
 
4030
 
 
4031
        return unless $confidence > 0;
 
4032
 
 
4033
        return $confidence;
 
4034
}
 
4035
 
 
4036
# Registers used:
 
4037
#   0x02: Status 1
 
4038
#   0x03: Configuration
 
4039
#   0x04: Company ID of LM84
 
4040
#   0x35: Status 2
 
4041
#   0xfe: Manufacturer ID
 
4042
#   0xff: Chip ID / die revision
 
4043
# We can use the LM84 Company ID register because the LM83 and the LM82 are
 
4044
# compatible with the LM84.
 
4045
# The LM83 chip ID is missing from the datasheet and was contributed by
 
4046
# Magnus Forsstrom: 0x03.
 
4047
# At least some revisions of the LM82 seem to be repackaged LM83, so they
 
4048
# have the same chip ID, and temp2/temp4 will be stuck in "OPEN" state.
 
4049
# For this reason, we don't even try to distinguish between both chips.
 
4050
# Thanks to Ben Gardner for reporting.
 
4051
sub lm83_detect
 
4052
{
 
4053
        my ($file, $addr) = @_;
 
4054
        return if i2c_smbus_read_byte_data($file, 0xfe) != 0x01;
 
4055
        my $chipid = i2c_smbus_read_byte_data($file, 0xff);
 
4056
        return if $chipid != 0x01 && $chipid != 0x03;
 
4057
 
 
4058
        my $confidence = 4;
 
4059
        $confidence++
 
4060
                if (i2c_smbus_read_byte_data($file, 0x02) & 0xa8) == 0x00;
 
4061
        $confidence++
 
4062
                if (i2c_smbus_read_byte_data($file, 0x03) & 0x41) == 0x00;
 
4063
        $confidence++
 
4064
                if i2c_smbus_read_byte_data($file, 0x04) == 0x00;
 
4065
        $confidence++
 
4066
                if (i2c_smbus_read_byte_data($file, 0x35) & 0x48) == 0x00;
 
4067
 
 
4068
        return $confidence;
 
4069
}
 
4070
 
 
4071
# Chip to detect: 0 = MAX6680/81, 1 = MAX6695/96
 
4072
# Registers used:
 
4073
#   0x03: Configuration
 
4074
#   0x04: Conversion rate
 
4075
#   0x12: Status2
 
4076
#   0x16: Overtemperature 2
 
4077
#   0xfe: Manufacturer ID
 
4078
#   0xff: Chip ID / die revision
 
4079
sub max6680_95_detect
 
4080
{
 
4081
        my ($file, $addr, $chip) = @_;
 
4082
        my $cid = i2c_smbus_read_byte_data($file, 0xff);
 
4083
        my $conf = i2c_smbus_read_byte_data($file, 0x03);
 
4084
        my $mid = i2c_smbus_read_byte_data($file, 0xfe, NO_CACHE);
 
4085
        my $emerg = i2c_smbus_read_byte_data($file, 0x16, NO_CACHE);
 
4086
        my $rate = i2c_smbus_read_byte_data($file, 0x04, NO_CACHE);
 
4087
        my $emerg2 = i2c_smbus_read_byte_data($file, 0x16, NO_CACHE);
 
4088
 
 
4089
        # Check common conditions
 
4090
        return if $rate > 0x07;
 
4091
        return if $mid != 0x4d;         # Not Maxim
 
4092
        return if $cid != 0x01;         # None of the chips we are looking for
 
4093
 
 
4094
        if ($chip == 0) {
 
4095
                return if ($conf & 0x03) != 0;
 
4096
                return 8 if $emerg != $emerg2;  # MAX6680/MAX6681
 
4097
        }
 
4098
        if ($chip == 1) {
 
4099
                my $status2 = i2c_smbus_read_byte_data($file, 0x12);
 
4100
 
 
4101
                return if ($conf & 0x10) != 0;
 
4102
                return if ($status2 & 0x01) != 0;
 
4103
                return 8 if $emerg == $emerg2;  # MAX6695/MAX6696
 
4104
        }
 
4105
        return;
 
4106
}
 
4107
 
 
4108
# Chip to detect: 0 = LM90, 1 = LM89/LM99, 2 = LM86, 3 = ADM1032,
 
4109
#                 4 = MAX6654, 5 = ADT7461,
 
4110
#                 6 = MAX6646/MAX6647/MAX6648/MAX6649/MAX6692,
 
4111
#                 8 = W83L771W/G, 9 = TMP401, 10 = TMP411,
 
4112
#                 11 = W83L771AWG/ASG, 12 = MAX6690
 
4113
# Registers used:
 
4114
#   0x03: Configuration
 
4115
#   0x04: Conversion rate
 
4116
#   0xfe: Manufacturer ID
 
4117
#   0xff: Chip ID / die revision
 
4118
sub lm90_detect
 
4119
{
 
4120
        my ($file, $addr, $chip) = @_;
 
4121
        my $mid = i2c_smbus_read_byte_data($file, 0xfe);
 
4122
        my $cid = i2c_smbus_read_byte_data($file, 0xff);
 
4123
        my $conf = i2c_smbus_read_byte_data($file, 0x03);
 
4124
        my $rate = i2c_smbus_read_byte_data($file, 0x04);
 
4125
 
 
4126
        if ($chip == 0) {
 
4127
                return if ($conf & 0x2a) != 0;
 
4128
                return if $rate > 0x09;
 
4129
                return if $mid != 0x01;         # National Semiconductor
 
4130
                return 8 if $cid == 0x21;       # LM90
 
4131
                return 6 if ($cid & 0x0f) == 0x20;
 
4132
        }
 
4133
        if ($chip == 1) {
 
4134
                return if ($conf & 0x2a) != 0;
 
4135
                return if $rate > 0x09;
 
4136
                return if $mid != 0x01;         # National Semiconductor
 
4137
                return 8 if $addr == 0x4c and $cid == 0x31; # LM89/LM99
 
4138
                return 8 if $addr == 0x4d and $cid == 0x34; # LM89-1/LM99-1
 
4139
                return 6 if ($cid & 0x0f) == 0x30;
 
4140
        }
 
4141
        if ($chip == 2) {
 
4142
                return if ($conf & 0x2a) != 0;
 
4143
                return if $rate > 0x09;
 
4144
                return if $mid != 0x01;         # National Semiconductor
 
4145
                return 8 if $cid == 0x11;       # LM86
 
4146
                return 6 if ($cid & 0xf0) == 0x10;
 
4147
        }
 
4148
        if ($chip == 3) {
 
4149
                return if ($conf & 0x3f) != 0;
 
4150
                return if $rate > 0x0a;
 
4151
                return if $mid != 0x41;         # Analog Devices
 
4152
                return 6 if ($cid & 0xf0) == 0x40; # ADM1032
 
4153
        }
 
4154
        if ($chip == 4) {
 
4155
                return if ($conf & 0x07) != 0;
 
4156
                return if $rate > 0x07;
 
4157
                return if $mid != 0x4d;         # Maxim
 
4158
                return 8 if $cid == 0x08;       # MAX6654
 
4159
        }
 
4160
        if ($chip == 5) {
 
4161
                return if ($conf & 0x1b) != 0;
 
4162
                return if $rate > 0x0a;
 
4163
                return if $mid != 0x41;         # Analog Devices
 
4164
                return 8 if $cid == 0x51;       # ADT7461
 
4165
        }
 
4166
        if ($chip == 6) {
 
4167
                return if ($conf & 0x3f) != 0;
 
4168
                return if $rate > 0x07;
 
4169
                return if $mid != 0x4d;         # Maxim
 
4170
                return 8 if $cid == 0x59;       # MAX6648/MAX6692
 
4171
        }
 
4172
        if ($chip == 8) {
 
4173
                return if ($conf & 0x2a) != 0;
 
4174
                return if $rate > 0x09;
 
4175
                return if $mid != 0x5c;         # Winbond
 
4176
                return 6 if ($cid & 0xfe) == 0x00; # W83L771W/G
 
4177
        }
 
4178
        if ($chip == 9) {
 
4179
                return if ($conf & 0x1B) != 0;
 
4180
                return if $rate > 0x0F;
 
4181
                return if $mid != 0x55;         # Texas Instruments
 
4182
                return 8 if $cid == 0x11;       # TMP401
 
4183
        }
 
4184
        if ($chip == 10) {
 
4185
                return if ($conf & 0x1B) != 0;
 
4186
                return if $rate > 0x0F;
 
4187
                return if $mid != 0x55;         # Texas Instruments
 
4188
                return 6 if ($addr == 0x4c && $cid == 0x12); # TMP411A
 
4189
                return 6 if ($addr == 0x4d && $cid == 0x13); # TMP411B
 
4190
                return 6 if ($addr == 0x4e && $cid == 0x10); # TMP411C
 
4191
        }
 
4192
        if ($chip == 11) {
 
4193
                return if ($conf & 0x2a) != 0;
 
4194
                return if $rate > 0x08;
 
4195
                return if $mid != 0x5c;         # Winbond
 
4196
                return 6 if ($cid & 0xfe) == 0x10; # W83L771AWG/ASG
 
4197
        }
 
4198
        if ($chip == 12) {
 
4199
                return if ($conf & 0x07) != 0;
 
4200
                return if $rate > 0x07;
 
4201
                return if $mid != 0x4d;         # Maxim
 
4202
                return 8 if $cid == 0x09;       # MAX6690
 
4203
        }
 
4204
        return;
 
4205
}
 
4206
 
 
4207
# Chip to detect: 0 = TMP421, 1 = TMP422, 2 = TMP423
 
4208
# Registers used:
 
4209
#   0xfe: Manufactorer ID
 
4210
#   0xff: Device ID
 
4211
sub tmp42x_detect()
 
4212
{
 
4213
        my ($file, $addr, $chip) = @_;
 
4214
 
 
4215
        my $mid = i2c_smbus_read_byte_data($file, 0xfe);
 
4216
        my $cid = i2c_smbus_read_byte_data($file, 0xff);
 
4217
 
 
4218
        return if ($mid != 0x55);
 
4219
 
 
4220
        return 6 if ($chip == 0 && $cid == 0x21); # TMP421
 
4221
        return 6 if ($chip == 1 && $cid == 0x22); # TMP422
 
4222
        return 6 if ($chip == 2 && $cid == 0x23); # TMP423
 
4223
 
 
4224
        return;
 
4225
}
 
4226
 
 
4227
# Registers used:
 
4228
#   0x3d: Device ID
 
4229
#   0x3e: Company ID
 
4230
sub amc6821_detect()
 
4231
{
 
4232
        my ($file, $addr) = @_;
 
4233
 
 
4234
        my $dev_id = i2c_smbus_read_byte_data($file, 0x3d);
 
4235
        my $comp_id = i2c_smbus_read_byte_data($file, 0x3e);
 
4236
 
 
4237
        return if ($comp_id != 0x49);           # Texas Instruments
 
4238
 
 
4239
        # Bit 7 of register address is ignored
 
4240
        return if i2c_smbus_read_byte_data($file, 0x80 | 0x3d) != $dev_id;
 
4241
        return if i2c_smbus_read_byte_data($file, 0x80 | 0x3e) != $comp_id;
 
4242
 
 
4243
        return 6 if ($dev_id == 0x21);          # AMC6821
 
4244
 
 
4245
        return;
 
4246
}
 
4247
 
 
4248
# Registers used:
 
4249
#   0x03: Configuration (no low nibble, returns the previous low nibble)
 
4250
#   0x04: Conversion rate
 
4251
#   0xfe: Manufacturer ID
 
4252
#   0xff: no register
 
4253
sub max6657_detect
 
4254
{
 
4255
        my ($file, $addr) = @_;
 
4256
        my $mid = i2c_smbus_read_byte_data($file, 0xfe, NO_CACHE);
 
4257
        my $cid = i2c_smbus_read_byte_data($file, 0xff, NO_CACHE);
 
4258
        my $conf = i2c_smbus_read_byte_data($file, 0x03, NO_CACHE);
 
4259
 
 
4260
        return if $mid != 0x4d;         # Maxim
 
4261
        return if ($conf & 0x1f) != 0x0d;
 
4262
        return if $cid != 0x4d;         # No register, returns previous value
 
4263
 
 
4264
        my $rate = i2c_smbus_read_byte_data($file, 0x04, NO_CACHE);
 
4265
        return if $rate > 0x09;
 
4266
 
 
4267
        $cid = i2c_smbus_read_byte_data($file, 0xff, NO_CACHE);
 
4268
        $conf = i2c_smbus_read_byte_data($file, 0x03, NO_CACHE);
 
4269
        return if ($conf & 0x0f) != $rate;
 
4270
        return if $cid != $rate;        # No register, returns previous value
 
4271
 
 
4272
        return 5;
 
4273
}
 
4274
 
 
4275
# Chip to detect: 0 = LM95231, 1 = LM95241
 
4276
# Registers used:
 
4277
#   0x02: Status (3 unused bits)
 
4278
#   0x03: Configuration (3 unused bits)
 
4279
#   0x06: Remote diode filter control (6 unused bits)
 
4280
#   0x30: Remote diode model type select (6 unused bits)
 
4281
#   0xfe: Manufacturer ID
 
4282
#   0xff: Revision ID
 
4283
sub lm95231_detect
 
4284
{
 
4285
        my ($file, $addr, $chip) = @_;
 
4286
        my $mid = i2c_smbus_read_byte_data($file, 0xfe);
 
4287
        my $cid = i2c_smbus_read_byte_data($file, 0xff);
 
4288
 
 
4289
        return if $mid != 0x01;                         # National Semiconductor
 
4290
        return if $chip == 0 && $cid != 0xa1;           # LM95231
 
4291
        return if $chip == 1 && $cid != 0xa4;           # LM95231
 
4292
 
 
4293
        return if i2c_smbus_read_byte_data($file, 0x02) & 0x70;
 
4294
        return if i2c_smbus_read_byte_data($file, 0x03) & 0x89;
 
4295
        return if i2c_smbus_read_byte_data($file, 0x06) & 0xfa;
 
4296
        return if i2c_smbus_read_byte_data($file, 0x30) & 0xfa;
 
4297
 
 
4298
        return 6;
 
4299
}
 
4300
 
 
4301
# Registers used:
 
4302
#   0x03: Configuration 1
 
4303
#   0x24: Configuration 2
 
4304
#   0x3d: Manufacturer ID
 
4305
#   0x3e: Device ID
 
4306
sub adt7481_detect
 
4307
{
 
4308
        my ($file, $addr) = @_;
 
4309
        my $mid = i2c_smbus_read_byte_data($file, 0x3d);
 
4310
        my $cid = i2c_smbus_read_byte_data($file, 0x3e);
 
4311
        my $conf1 = i2c_smbus_read_byte_data($file, 0x03);
 
4312
        my $conf2 = i2c_smbus_read_byte_data($file, 0x24);
 
4313
 
 
4314
        return if ($conf1 & 0x10) != 0;
 
4315
        return if ($conf2 & 0x7f) != 0;
 
4316
        return if $mid != 0x41;         # Analog Devices
 
4317
        return if $cid != 0x81;         # ADT7481
 
4318
 
 
4319
        return 6;
 
4320
}
 
4321
 
 
4322
# Chip to detect: 1 = LM63, 2 = F75363SG, 3 = LM64
 
4323
# Registers used:
 
4324
#   0xfe: Manufacturer ID
 
4325
#   0xff: Chip ID / die revision
 
4326
#   0x03: Configuration (two or three unused bits)
 
4327
#   0x16: Alert mask (two or three unused bits)
 
4328
sub lm63_detect
 
4329
{
 
4330
        my ($file, $addr, $chip) = @_;
 
4331
 
 
4332
        my $mid = i2c_smbus_read_byte_data($file, 0xfe);
 
4333
        my $cid = i2c_smbus_read_byte_data($file, 0xff);
 
4334
        my $conf = i2c_smbus_read_byte_data($file, 0x03);
 
4335
        my $mask = i2c_smbus_read_byte_data($file, 0x16);
 
4336
 
 
4337
        if ($chip == 1) {
 
4338
                return if $mid != 0x01          # National Semiconductor
 
4339
                       || $cid != 0x41;         # LM63
 
4340
                return if ($conf & 0x18) != 0x00
 
4341
                       || ($mask & 0xa4) != 0xa4;
 
4342
        } elsif ($chip == 2) {
 
4343
                return if $mid != 0x23          # Fintek
 
4344
                       || $cid != 0x20;         # F75363SG
 
4345
                return if ($conf & 0x1a) != 0x00
 
4346
                       || ($mask & 0x84) != 0x00;
 
4347
        } elsif ($chip == 3) {
 
4348
                return if $mid != 0x01          # National Semiconductor
 
4349
                       || $cid != 0x51;         # LM64
 
4350
                return if ($conf & 0x18) != 0x00
 
4351
                       || ($mask & 0xa4) != 0xa4;
 
4352
        }
 
4353
 
 
4354
        return 6;
 
4355
}
 
4356
 
 
4357
# Registers used:
 
4358
#   0x02, 0x03: Fan support
 
4359
#   0x06: Temperature support
 
4360
#   0x07, 0x08, 0x09: Fan config
 
4361
#   0x0d: Manufacturer ID
 
4362
#   0x0e: Chip ID / die revision
 
4363
sub adm1029_detect
 
4364
{
 
4365
        my ($file, $addr) = @_;
 
4366
        my $mid = i2c_smbus_read_byte_data($file, 0x0d);
 
4367
        my $cid = i2c_smbus_read_byte_data($file, 0x0e);
 
4368
        my $cfg;
 
4369
 
 
4370
        return unless $mid == 0x41;             # Analog Devices
 
4371
        return unless ($cid & 0xF0) == 0x00;    # ADM1029
 
4372
 
 
4373
        # Extra check on unused bits
 
4374
        $cfg = i2c_smbus_read_byte_data($file, 0x02);
 
4375
        return unless $cfg == 0x03;
 
4376
        $cfg = i2c_smbus_read_byte_data($file, 0x06);
 
4377
        return unless ($cfg & 0xF9) == 0x01;
 
4378
        foreach my $reg (0x03, 0x07, 0x08, 0x09) {
 
4379
                $cfg = i2c_smbus_read_byte_data($file, $reg);
 
4380
                return unless ($cfg & 0xFC) == 0x00;
 
4381
        }
 
4382
 
 
4383
        return 7;
 
4384
}
 
4385
 
 
4386
# Chip to detect: 0 = ADM1030, 1 = ADM1031
 
4387
# Registers used:
 
4388
#   0x01: Config 2
 
4389
#   0x03: Status 2
 
4390
#   0x0d, 0x0e, 0x0f: Temperature offsets
 
4391
#   0x22: Fan speed config
 
4392
#   0x3d: Chip ID
 
4393
#   0x3e: Manufacturer ID
 
4394
#   0x3f: Die revision
 
4395
sub adm1031_detect
 
4396
{
 
4397
        my ($file, $addr, $chip) = @_;
 
4398
        my $mid = i2c_smbus_read_byte_data($file, 0x3e);
 
4399
        my $cid = i2c_smbus_read_byte_data($file, 0x3d);
 
4400
        my $drev = i2c_smbus_read_byte_data($file, 0x3f);
 
4401
        my $conf2 = i2c_smbus_read_byte_data($file, 0x01);
 
4402
        my $stat2 = i2c_smbus_read_byte_data($file, 0x03);
 
4403
        my $fsc = i2c_smbus_read_byte_data($file, 0x22);
 
4404
        my $lto = i2c_smbus_read_byte_data($file, 0x0d);
 
4405
        my $r1to = i2c_smbus_read_byte_data($file, 0x0e);
 
4406
        my $r2to = i2c_smbus_read_byte_data($file, 0x0f);
 
4407
        my $confidence = 3;
 
4408
 
 
4409
        if ($chip == 0) {
 
4410
                return if $mid != 0x41;         # Analog Devices
 
4411
                return if $cid != 0x30;         # ADM1030
 
4412
                $confidence++ if ($drev & 0x70) == 0x00;
 
4413
                $confidence++ if ($conf2 & 0x4A) == 0x00;
 
4414
                $confidence++ if ($stat2 & 0x3F) == 0x00;
 
4415
                $confidence++ if ($fsc & 0xF0) == 0x00;
 
4416
                $confidence++ if ($lto & 0x70) == 0x00;
 
4417
                $confidence++ if ($r1to & 0x70) == 0x00;
 
4418
                return $confidence;
 
4419
        }
 
4420
        if ($chip == 1) {
 
4421
                return if $mid != 0x41;         # Analog Devices
 
4422
                return if $cid != 0x31;         # ADM1031
 
4423
                $confidence++ if ($drev & 0x70) == 0x00;
 
4424
                $confidence++ if ($lto & 0x70) == 0x00;
 
4425
                $confidence++ if ($r1to & 0x70) == 0x00;
 
4426
                $confidence++ if ($r2to & 0x70) == 0x00;
 
4427
                return $confidence;
 
4428
        }
 
4429
}
 
4430
 
 
4431
# Chip to detect: 0 = ADM1033, 1 = ADM1034
 
4432
# Registers used:
 
4433
#   0x3d: Chip ID
 
4434
#   0x3e: Manufacturer ID
 
4435
#   0x3f: Die revision
 
4436
sub adm1034_detect
 
4437
{
 
4438
        my ($file, $addr, $chip) = @_;
 
4439
        my $mid = i2c_smbus_read_byte_data($file, 0x3e);
 
4440
        my $cid = i2c_smbus_read_byte_data($file, 0x3d);
 
4441
        my $drev = i2c_smbus_read_byte_data($file, 0x3f);
 
4442
 
 
4443
        if ($chip == 0) {
 
4444
                return if $mid != 0x41;         # Analog Devices
 
4445
                return if $cid != 0x33;         # ADM1033
 
4446
                return if ($drev & 0xf8) != 0x00;
 
4447
                return 6 if $drev == 0x02;
 
4448
                return 4;
 
4449
        }
 
4450
        if ($chip == 1) {
 
4451
                return if $mid != 0x41;         # Analog Devices
 
4452
                return if $cid != 0x34;         # ADM1034
 
4453
                return if ($drev & 0xf8) != 0x00;
 
4454
                return 6 if $drev == 0x02;
 
4455
                return 4;
 
4456
        }
 
4457
}
 
4458
 
 
4459
# Chip to detect: 0 = ADT7467/ADT7468, 1 = ADT7476, 2 = ADT7462, 3 = ADT7466,
 
4460
#                 4 = ADT7470
 
4461
# Registers used:
 
4462
#   0x3d: Chip ID
 
4463
#   0x3e: Manufacturer ID
 
4464
#   0x3f: Die revision
 
4465
sub adt7467_detect
 
4466
{
 
4467
        my ($file, $addr, $chip) = @_;
 
4468
        my $mid = i2c_smbus_read_byte_data($file, 0x3e);
 
4469
        my $cid = i2c_smbus_read_byte_data($file, 0x3d);
 
4470
        my $drev = i2c_smbus_read_byte_data($file, 0x3f);
 
4471
 
 
4472
        return if $mid != 0x41;                 # Analog Devices
 
4473
 
 
4474
        if ($chip == 0) {
 
4475
                return if $cid != 0x68;         # ADT7467/ADT7468
 
4476
                return if ($drev & 0xf0) != 0x70;
 
4477
                return 7 if $drev == 0x71 || $drev == 0x72;
 
4478
                return 5;
 
4479
        }
 
4480
        if ($chip == 1) {
 
4481
                return if $cid != 0x76;         # ADT7476
 
4482
                return if ($drev & 0xf0) != 0x60;
 
4483
                return 7 if $drev >= 0x69 && $drev <= 0x6b;
 
4484
                return 5;
 
4485
        }
 
4486
        if ($chip == 2) {
 
4487
                return if $cid != 0x62;         # ADT7462
 
4488
                return if ($drev & 0xf0) != 0x00;
 
4489
                return 7 if $drev == 0x04;
 
4490
                return 5;
 
4491
        }
 
4492
        if ($chip == 3) {
 
4493
                return if $cid != 0x66;         # ADT7466
 
4494
                return if ($drev & 0xf0) != 0x00;
 
4495
                return 7 if $drev == 0x02;
 
4496
                return 5;
 
4497
        }
 
4498
        if ($chip == 4) {
 
4499
                return if $cid != 0x70;         # ADT7470
 
4500
                return if ($drev & 0xf0) != 0x00;
 
4501
                return 7 if $drev == 0x00;
 
4502
                return 5;
 
4503
        }
 
4504
}
 
4505
 
 
4506
# Chip to detect: 0 = ADT7473, 1 = ADT7475
 
4507
# Registers used:
 
4508
#   0x3d: Chip ID
 
4509
#   0x3e: Manufacturer ID
 
4510
sub adt7473_detect
 
4511
{
 
4512
        my ($file, $addr, $chip) = @_;
 
4513
        my $mid = i2c_smbus_read_byte_data($file, 0x3e);
 
4514
        my $cid = i2c_smbus_read_byte_data($file, 0x3d);
 
4515
 
 
4516
        return if $mid != 0x41;                 # Analog Devices
 
4517
 
 
4518
        return if $chip == 0 && $cid != 0x73;   # ADT7473
 
4519
        return if $chip == 1 && $cid != 0x75;   # ADT7475
 
4520
        return 5;
 
4521
}
 
4522
 
 
4523
# Registers used:
 
4524
#   0x3e: Manufacturer ID
 
4525
#   0x3f: Chip ID
 
4526
sub adt7490_detect
 
4527
{
 
4528
        my ($file, $addr) = @_;
 
4529
        my $mid = i2c_smbus_read_byte_data($file, 0x3e);
 
4530
        my $cid = i2c_smbus_read_byte_data($file, 0x3f);
 
4531
 
 
4532
        return if $mid != 0x41;                 # Analog Devices
 
4533
        return if ($cid & 0xfc) != 0x6c;        # ADT7490
 
4534
        return 5;
 
4535
}
 
4536
 
 
4537
# Registers used:
 
4538
#   0x4d: Device ID
 
4539
#   0x4e: Manufacturer ID
 
4540
#   0x4e: Silicon revision
 
4541
sub adt7411_detect
 
4542
{
 
4543
        my ($file, $addr) = @_;
 
4544
        my $dev_id = i2c_smbus_read_byte_data($file, 0x4d);
 
4545
        my $man_id = i2c_smbus_read_byte_data($file, 0x4e);
 
4546
        my $revision = i2c_smbus_read_byte_data($file, 0x4f);
 
4547
 
 
4548
        return if $man_id != 0x41;              # Analog Devices
 
4549
        return if $dev_id != 0x02;              # ADT7411
 
4550
        # The datasheet suggests that the version is in the high nibble, but
 
4551
        # a dump from a real ADT7411 chip shows that it is in the low nibble.
 
4552
        return if ($revision & 0x0f) != 0x04;   # ADT7411
 
4553
        return 5;
 
4554
}
 
4555
 
 
4556
# Chip to detect: 0 = aSC7512, 1 = aSC7611, 2 = aSC7621
 
4557
# Registers used:
 
4558
#   0x3e: Manufacturer ID
 
4559
#   0x3f: Version
 
4560
sub andigilog_detect
 
4561
{
 
4562
        my ($file, $addr, $chip) = @_;
 
4563
        my $mid = i2c_smbus_read_byte_data($file, 0x3e);
 
4564
        my $cid = i2c_smbus_read_byte_data($file, 0x3f);
 
4565
 
 
4566
        return if $mid != 0x61;         # Andigilog
 
4567
 
 
4568
        return if $chip == 0 && $cid != 0x62;
 
4569
        return if $chip == 1 && $cid != 0x69;
 
4570
        return if $chip == 2 && ($cid != 0x6C && $cid != 0x6D);
 
4571
        return 5;
 
4572
}
 
4573
 
 
4574
# Registers used:
 
4575
#   0xfe: Manufacturer ID
 
4576
#   0xff: Die Code
 
4577
sub andigilog_aSC7511_detect
 
4578
{
 
4579
        my ($file, $addr) = @_;
 
4580
        my $mid = i2c_smbus_read_byte_data($file, 0xfe);
 
4581
        my $die = i2c_smbus_read_byte_data($file, 0xff);
 
4582
 
 
4583
        return if $mid != 0x61;         # Andigilog
 
4584
        return if $die != 0x00;
 
4585
        return 3;
 
4586
}
 
4587
 
 
4588
# Chip to detect: 0 = LM85, 1 = LM96000, 2 = ADM1027, 3 = ADT7463,
 
4589
#                 4 = EMC6D100/101, 5 = EMC6D102, 6 = EMC6D103,
 
4590
#                 7 = WPCD377I (no sensors)
 
4591
# Registers used:
 
4592
#   0x3e: Vendor register
 
4593
#   0x3d: Device ID register (Analog Devices only)
 
4594
#   0x3f: Version/Stepping register
 
4595
sub lm85_detect
 
4596
{
 
4597
        my ($file, $addr, $chip) = @_;
 
4598
        my $vendor = i2c_smbus_read_byte_data($file, 0x3e);
 
4599
        my $verstep = i2c_smbus_read_byte_data($file, 0x3f);
 
4600
 
 
4601
        if ($chip == 0) {
 
4602
                return if $vendor != 0x01;      # National Semiconductor
 
4603
                return if $verstep != 0x60      # LM85 C
 
4604
                       && $verstep != 0x62;     # LM85 B
 
4605
        } elsif ($chip == 1 || $chip == 7) {
 
4606
                return if $vendor != 0x01;      # National Semiconductor
 
4607
                return if $verstep != 0x68      # LM96000
 
4608
                       && $verstep != 0x69;     # LM96000
 
4609
        } elsif ($chip == 2) {
 
4610
                return if $vendor != 0x41;      # Analog Devices
 
4611
                return if $verstep != 0x60;     # ADM1027
 
4612
        } elsif ($chip == 3) {
 
4613
                return if $vendor != 0x41;      # Analog Devices
 
4614
                return if $verstep != 0x62      # ADT7463
 
4615
                       && $verstep != 0x6a;     # ADT7463 C
 
4616
        } elsif ($chip == 4) {
 
4617
                return if $vendor != 0x5c;      # SMSC
 
4618
                return if $verstep != 0x60      # EMC6D100/101 A0
 
4619
                       && $verstep != 0x61;     # EMC6D100/101 A1
 
4620
        } elsif ($chip == 5) {
 
4621
                return if $vendor != 0x5c;      # SMSC
 
4622
                return if $verstep != 0x65;     # EMC6D102
 
4623
        } elsif ($chip == 6) {
 
4624
                return if $vendor != 0x5c;      # SMSC
 
4625
                return if $verstep != 0x68;     # EMC6D103
 
4626
        }
 
4627
 
 
4628
        if ($vendor == 0x41) {                  # Analog Devices
 
4629
                return if i2c_smbus_read_byte_data($file, 0x3d) != 0x27;
 
4630
                return 8;
 
4631
        }
 
4632
 
 
4633
        if ($chip == 1 || $chip == 7) {
 
4634
                # Differenciate between real LM96000 and Winbond WPCD377I.
 
4635
                # The latter emulate the former except that it has no
 
4636
                # hardware monitoring function so the readings are always
 
4637
                # 0.
 
4638
                my ($in_temp, $fan, $i);
 
4639
                
 
4640
                for ($i = 0; $i < 8; $i++) {
 
4641
                        $in_temp = i2c_smbus_read_byte_data($file, 0x20 + $i);
 
4642
                        $fan = i2c_smbus_read_byte_data($file, 0x28 + $i);
 
4643
                        if ($in_temp != 0x00 or $fan != 0xff) {
 
4644
                                return 7 if $chip == 1;
 
4645
                                return;
 
4646
                        }
 
4647
                }
 
4648
                return 7 if $chip == 7;
 
4649
                return;
 
4650
        }
 
4651
 
 
4652
        return 7;
 
4653
}
 
4654
 
 
4655
# Chip to detect: 0 = LM87, 1 = ADM1024
 
4656
# Registers used:
 
4657
#   0x3e: Company ID
 
4658
#   0x3f: Revision
 
4659
#   0x40: Configuration
 
4660
sub lm87_detect
 
4661
{
 
4662
        my ($file, $addr, $chip) = @_;
 
4663
        my $cid = i2c_smbus_read_byte_data($file, 0x3e);
 
4664
        my $rev = i2c_smbus_read_byte_data($file, 0x3f);
 
4665
 
 
4666
        if ($chip == 0) {
 
4667
                return if $cid != 0x02;         # National Semiconductor
 
4668
                return if ($rev & 0xfc) != 0x04; # LM87
 
4669
        }
 
4670
        if ($chip == 1) {
 
4671
                return if $cid != 0x41;         # Analog Devices
 
4672
                return if ($rev & 0xf0) != 0x10; # ADM1024
 
4673
        }
 
4674
 
 
4675
        my $cfg = i2c_smbus_read_byte_data($file, 0x40);
 
4676
        return if ($cfg & 0x80) != 0x00;
 
4677
 
 
4678
        return 7;
 
4679
}
 
4680
 
 
4681
# Chip to detect: 0 = W83781D, 1 = W83782D, 2 = W83783S, 3 = W83627HF,
 
4682
#                 4 = AS99127F (rev.1), 5 = AS99127F (rev.2), 6 = ASB100,
 
4683
#                 7 = W83791D, 8 = W83792D, 9 = W83627EHF,
 
4684
#                 10 = W83627DHG/W83667HG/W83677HG
 
4685
# Registers used:
 
4686
#   0x48: Full I2C Address
 
4687
#   0x4a: I2C addresses of emulated LM75 chips
 
4688
#   0x4e: Vendor ID byte selection, and bank selection
 
4689
#   0x4f: Vendor ID
 
4690
#   0x58: Device ID (only when in bank 0)
 
4691
# Note: Fails if the W8378xD is not in bank 0!
 
4692
# Note: Asus chips do not have their I2C address at register 0x48?
 
4693
#       AS99127F rev.1 and ASB100 have 0x00, confirmation wanted for
 
4694
#       AS99127F rev.2.
 
4695
sub w83781d_detect
 
4696
{
 
4697
        my ($file, $addr, $chip) = @_;
 
4698
        my ($reg1, $reg2, @res);
 
4699
 
 
4700
        return unless (i2c_smbus_read_byte_data($file, 0x48) == $addr)
 
4701
                   or ($chip >= 4 && $chip <= 6);
 
4702
 
 
4703
        $reg1 = i2c_smbus_read_byte_data($file, 0x4e);
 
4704
        $reg2 = i2c_smbus_read_byte_data($file, 0x4f);
 
4705
        if ($chip == 4) {               # Asus AS99127F (rev.1)
 
4706
                return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xc3) or
 
4707
                              (($reg1 & 0x80) == 0x80 and $reg2 == 0x12);
 
4708
        } elsif ($chip == 6) {          # Asus ASB100
 
4709
                return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0x94) or
 
4710
                              (($reg1 & 0x80) == 0x80 and $reg2 == 0x06);
 
4711
        } else {                        # Winbond and Asus AS99127F (rev.2)
 
4712
                return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or
 
4713
                              (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
 
4714
        }
 
4715
 
 
4716
        return unless ($reg1 & 0x07) == 0x00;
 
4717
 
 
4718
        $reg1 = i2c_smbus_read_byte_data($file, 0x58);
 
4719
        return if $chip == 0 and ($reg1 != 0x10 && $reg1 != 0x11);
 
4720
        return if $chip == 1 and $reg1 != 0x30;
 
4721
        return if $chip == 2 and $reg1 != 0x40;
 
4722
        return if $chip == 3 and $reg1 != 0x21;
 
4723
        return if $chip == 4 and $reg1 != 0x31;
 
4724
        return if $chip == 5 and $reg1 != 0x31;
 
4725
        return if $chip == 6 and $reg1 != 0x31;
 
4726
        return if $chip == 7 and $reg1 != 0x71;
 
4727
        return if $chip == 8 and $reg1 != 0x7a;
 
4728
        return if $chip == 9 and ($reg1 != 0x88 && $reg1 != 0xa1);
 
4729
        return if $chip == 10 and $reg1 != 0xc1;
 
4730
        # Default address is 0x2d
 
4731
        @res = ($addr != 0x2d) ? (7) : (8);
 
4732
        return @res if $chip >= 9; # No subclients
 
4733
 
 
4734
        $reg1 = i2c_smbus_read_byte_data($file, 0x4a);
 
4735
        push @res, ($reg1 & 0x07) + 0x48 unless $reg1 & 0x08;
 
4736
        push @res, (($reg1 & 0x70) >> 4) + 0x48
 
4737
                unless ($reg1 & 0x80 or $chip == 2);
 
4738
        return @res;
 
4739
}
 
4740
 
 
4741
# Registers used:
 
4742
#   0x0b: Full I2C Address
 
4743
#   0x0c: I2C addresses of emulated LM75 chips
 
4744
#   0x00: Vendor ID byte selection, and bank selection(Bank 0, 1, 2)
 
4745
#   0x0d: Vendor ID(Bank 0, 1, 2)
 
4746
#   0x0e: Device ID(Bank 0, 1, 2)
 
4747
sub w83793_detect
 
4748
{
 
4749
        my ($file, $addr) = @_;
 
4750
        my ($bank, $reg, @res);
 
4751
 
 
4752
        $bank = i2c_smbus_read_byte_data($file, 0x00);
 
4753
        $reg = i2c_smbus_read_byte_data($file, 0x0d);
 
4754
 
 
4755
        return unless (($bank & 0x80) == 0x00 and $reg == 0xa3) or
 
4756
                      (($bank & 0x80) == 0x80 and $reg == 0x5c);
 
4757
 
 
4758
        $reg = i2c_smbus_read_byte_data($file, 0x0e);
 
4759
        return if $reg != 0x7b;
 
4760
 
 
4761
        # If bank 0 is selected, we can do more checks
 
4762
        return 6 unless ($bank & 0x07) == 0;
 
4763
        $reg = i2c_smbus_read_byte_data($file, 0x0b);
 
4764
        return unless ($reg == ($addr << 1));
 
4765
 
 
4766
        $reg = i2c_smbus_read_byte_data($file, 0x0c);
 
4767
        @res = (8);
 
4768
        push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08;
 
4769
        push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
 
4770
        return @res;
 
4771
}
 
4772
 
 
4773
# Registers used:
 
4774
#   0xfc: Full I2C Address
 
4775
#   0x00: Vendor ID byte selection, and bank selection(Bank 0, 1, 2)
 
4776
#   0xfd: Vendor ID(Bank 0, 1, 2)
 
4777
#   0xfe: Device ID(Bank 0, 1, 2)
 
4778
sub w83795_detect
 
4779
{
 
4780
        my ($bank, $reg);
 
4781
        my ($file, $addr) = @_;
 
4782
 
 
4783
        $bank = i2c_smbus_read_byte_data($file, 0x00);
 
4784
        $reg = i2c_smbus_read_byte_data($file, 0xfd);
 
4785
 
 
4786
        return unless (($bank & 0x80) == 0x00 and $reg == 0xa3) or
 
4787
                      (($bank & 0x80) == 0x80 and $reg == 0x5c);
 
4788
 
 
4789
        $reg = i2c_smbus_read_byte_data($file, 0xfe);
 
4790
        return if $reg != 0x79;
 
4791
 
 
4792
        # If bank 0 is selected, we can do more checks
 
4793
        return 6 unless ($bank & 0x07) == 0;
 
4794
        $reg = i2c_smbus_read_byte_data($file, 0xfc) & 0x7f;
 
4795
        return unless ($reg == $addr);
 
4796
 
 
4797
        return 8;
 
4798
}
 
4799
 
 
4800
# Registers used:
 
4801
#   0x48: Full I2C Address
 
4802
#   0x4e: Vendor ID byte selection
 
4803
#   0x4f: Vendor ID
 
4804
#   0x58: Device ID
 
4805
# Note that the datasheet was useless and this detection routine
 
4806
# is based on dumps we received from users. Also, the W83781SD is *NOT*
 
4807
# a hardware monitoring chip as far as we know, but we still want to
 
4808
# detect it so that people won't keep reporting it as an unknown chip
 
4809
# we should investigate about.
 
4810
sub w83791sd_detect
 
4811
{
 
4812
        my ($file, $addr) = @_;
 
4813
        my ($reg1, $reg2);
 
4814
 
 
4815
        return unless (i2c_smbus_read_byte_data($file, 0x48) == $addr);
 
4816
 
 
4817
        $reg1 = i2c_smbus_read_byte_data($file, 0x4e);
 
4818
        $reg2 = i2c_smbus_read_byte_data($file, 0x4f);
 
4819
        return unless (!($reg1 & 0x80) && $reg2 == 0xa3)
 
4820
                   || (($reg1 & 0x80) && $reg2 == 0x5c);
 
4821
 
 
4822
        $reg1 = i2c_smbus_read_byte_data($file, 0x58);
 
4823
        return unless $reg1 == 0x72;
 
4824
 
 
4825
        return 3;
 
4826
}
 
4827
 
 
4828
# Registers used:
 
4829
#   0x4e: Vendor ID high byte
 
4830
#   0x4f: Vendor ID low byte
 
4831
#   0x58: Device ID
 
4832
# Note: The values were given by Alex van Kaam, we don't have datasheets
 
4833
#       to confirm.
 
4834
sub mozart_detect
 
4835
{
 
4836
        my ($file, $addr) = @_;
 
4837
        my ($vid, $dev);
 
4838
 
 
4839
        $vid = (i2c_smbus_read_byte_data($file, 0x4e) << 8)
 
4840
             + i2c_smbus_read_byte_data($file, 0x4f);
 
4841
        $dev = i2c_smbus_read_byte_data($file, 0x58);
 
4842
 
 
4843
        return unless ($dev == 0x56 && $vid == 0x9436)  # ASM58
 
4844
                   || ($dev == 0x56 && $vid == 0x9406)  # AS2K129R
 
4845
                   || ($dev == 0x10 && $vid == 0x5ca3);
 
4846
 
 
4847
        return 5;
 
4848
}
 
4849
 
 
4850
# Chip to detect: 0 = GL518SM, 1 = GL520SM
 
4851
# Registers used:
 
4852
#   0x00: Device ID
 
4853
#   0x01: Revision ID
 
4854
#   0x03: Configuration
 
4855
sub gl518sm_detect
 
4856
{
 
4857
        my ($file, $addr, $chip) = @_;
 
4858
        my $reg;
 
4859
 
 
4860
        $reg = i2c_smbus_read_byte_data($file, 0x00);
 
4861
        return if $chip == 0 && $reg != 0x80;
 
4862
        return if $chip == 1 && $reg != 0x20;
 
4863
 
 
4864
        return unless (i2c_smbus_read_byte_data($file, 0x03) & 0x80) == 0x00;
 
4865
        $reg = i2c_smbus_read_byte_data($file, 0x01);
 
4866
        return unless $reg == 0x00 or $reg == 0x80;
 
4867
        return 6;
 
4868
}
 
4869
 
 
4870
# Registers used:
 
4871
#   0x00: Device ID
 
4872
#   0x03: Configuration
 
4873
# Mediocre detection
 
4874
sub gl525sm_detect
 
4875
{
 
4876
        my ($file, $addr) = @_;
 
4877
        return unless i2c_smbus_read_byte_data($file, 0x00) == 0x25;
 
4878
        return unless (i2c_smbus_read_byte_data($file, 0x03) & 0x80) == 0x00;
 
4879
        return 5;
 
4880
}
 
4881
 
 
4882
# Chip to detect: 0 = ADM9240, 1 = DS1780, 2 = LM81
 
4883
# Registers used:
 
4884
#   0x3e: Company ID
 
4885
#   0x40: Configuration
 
4886
#   0x48: Full I2C Address
 
4887
sub adm9240_detect
 
4888
{
 
4889
        my ($file, $addr, $chip) = @_;
 
4890
        my $reg;
 
4891
        $reg = i2c_smbus_read_byte_data($file, 0x3e);
 
4892
        return unless ($chip == 0 and $reg == 0x23) or
 
4893
                      ($chip == 1 and $reg == 0xda) or
 
4894
                      ($chip == 2 and $reg == 0x01);
 
4895
        return unless (i2c_smbus_read_byte_data($file, 0x40) & 0x80) == 0x00;
 
4896
        return unless i2c_smbus_read_byte_data($file, 0x48) == $addr;
 
4897
 
 
4898
        return 7;
 
4899
}
 
4900
 
 
4901
# Chip to detect: 0 = ADM1022, 1 = THMC50, 2 = ADM1028, 3 = THMC51
 
4902
# Registers used:
 
4903
#   0x3e: Company ID
 
4904
#   0x3f: Revision
 
4905
#   0x40: Configuration
 
4906
sub adm1022_detect
 
4907
{
 
4908
        my ($file, $addr, $chip) = @_;
 
4909
        my $reg;
 
4910
        $reg = i2c_smbus_read_byte_data($file, 0x3e);
 
4911
        return unless ($chip == 0 and $reg == 0x41) or
 
4912
                      ($chip == 1 and $reg == 0x49) or
 
4913
                      ($chip == 2 and $reg == 0x41) or
 
4914
                      ($chip == 3 and $reg == 0x49);
 
4915
        $reg = i2c_smbus_read_byte_data($file, 0x40);
 
4916
        return if ($reg & 0x10);                        # Soft Reset always reads 0
 
4917
        return if ($chip != 0 and ($reg & 0x80));       # Reserved on THMC50 and ADM1028
 
4918
        $reg = i2c_smbus_read_byte_data($file, 0x3f) & 0xf0;
 
4919
        return unless ($chip == 0 and $reg == 0xc0) or
 
4920
                      ($chip == 1 and $reg == 0xc0) or
 
4921
                      ($chip == 2 and $reg == 0xd0) or
 
4922
                      ($chip == 3 and $reg == 0xd0);
 
4923
        return 8;
 
4924
}
 
4925
 
 
4926
# Chip to detect: 0 = ADM1025, 1 = NE1619
 
4927
# Registers used:
 
4928
#   0x3e: Company ID
 
4929
#   0x3f: Revision
 
4930
#   0x40: Configuration
 
4931
#   0x41: Status 1
 
4932
#   0x42: Status 2
 
4933
sub adm1025_detect
 
4934
{
 
4935
        my ($file, $addr, $chip) = @_;
 
4936
        my $reg;
 
4937
 
 
4938
        $reg = i2c_smbus_read_byte_data($file, 0x3e);
 
4939
        return if ($chip == 0) and ($reg != 0x41);
 
4940
        return if ($chip == 1) and ($reg != 0xA1);
 
4941
 
 
4942
        return unless (i2c_smbus_read_byte_data($file, 0x40) & 0x80) == 0x00;
 
4943
        return unless (i2c_smbus_read_byte_data($file, 0x41) & 0xC0) == 0x00;
 
4944
        return unless (i2c_smbus_read_byte_data($file, 0x42) & 0xBC) == 0x00;
 
4945
        return unless (i2c_smbus_read_byte_data($file, 0x3f) & 0xf0) == 0x20;
 
4946
 
 
4947
        return 8;
 
4948
}
 
4949
 
 
4950
# Registers used:
 
4951
#   0x16: Company ID
 
4952
#   0x17: Revision
 
4953
sub adm1026_detect
 
4954
{
 
4955
        my ($file, $addr) = @_;
 
4956
        my $reg;
 
4957
        $reg = i2c_smbus_read_byte_data($file, 0x16);
 
4958
        return unless ($reg == 0x41);
 
4959
        return unless (i2c_smbus_read_byte_data($file, 0x17) & 0xf0) == 0x40;
 
4960
        return 8;
 
4961
}
 
4962
 
 
4963
# Chip to detect: 0 = ADM1021, 1 = ADM1021A/ADM1023, 2 = MAX1617, 3 = MAX1617A,
 
4964
#                 4 = THMC10, 5 = LM84, 6 = GL523, 7 = MC1066
 
4965
# Registers used:
 
4966
#   0x04: Company ID (LM84 only)
 
4967
#   0xfe: Company ID (all but LM84 and MAX1617)
 
4968
#   0xff: Revision (ADM1021, ADM1021A/ADM1023 and MAX1617A)
 
4969
#   0x02: Status
 
4970
#   0x03: Configuration
 
4971
#   0x04: Conversion rate
 
4972
#   0x00-0x01, 0x05-0x08: Temperatures (MAX1617 and LM84)
 
4973
# Note: Especially the MAX1617 has very bad detection; we give it a low
 
4974
# confidence value.
 
4975
sub adm1021_detect
 
4976
{
 
4977
        my ($file, $addr, $chip) = @_;
 
4978
        my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
 
4979
        my $rev = i2c_smbus_read_byte_data($file, 0xff);
 
4980
        my $conf = i2c_smbus_read_byte_data($file, 0x03);
 
4981
        my $status = i2c_smbus_read_byte_data($file, 0x02);
 
4982
        my $convrate = i2c_smbus_read_byte_data($file, 0x04);
 
4983
 
 
4984
        # Check manufacturer IDs and product revisions when available
 
4985
        return if $chip == 0 and $man_id != 0x41 || ($rev & 0xf0) != 0x00;
 
4986
        return if $chip == 1 and $man_id != 0x41 || ($rev & 0xf0) != 0x30;
 
4987
        return if $chip == 3 and $man_id != 0x4d || $rev != 0x01;
 
4988
        return if $chip == 4 and $man_id != 0x49;
 
4989
        return if $chip == 5 and $convrate != 0x00;
 
4990
        return if $chip == 6 and $man_id != 0x23;
 
4991
        return if $chip == 7 and $man_id != 0x54;
 
4992
 
 
4993
        # Check unused bits
 
4994
        if ($chip == 5) {       # LM84
 
4995
                return if ($status & 0xab) != 0;
 
4996
                return if ($conf & 0x7f) != 0;
 
4997
        } else {
 
4998
                return if ($status & 0x03) != 0;
 
4999
                return if ($conf & 0x3f) != 0;
 
5000
                return if ($convrate & 0xf8) != 0;
 
5001
        }
 
5002
 
 
5003
        # Extra checks for MAX1617 and LM84, since those are often misdetected.
 
5004
        # We verify several assertions (6 for the MAX1617, 4 for the LM84) and
 
5005
        # discard the chip if any fail. Note that these checks are not done
 
5006
        # by the adm1021 driver.
 
5007
        if ($chip == 2 || $chip == 5) {
 
5008
                my $lte = i2c_smbus_read_byte_data($file, 0x00);
 
5009
                my $rte = i2c_smbus_read_byte_data($file, 0x01);
 
5010
                my $lhi = i2c_smbus_read_byte_data($file, 0x05);
 
5011
                my $rhi = i2c_smbus_read_byte_data($file, 0x07);
 
5012
                my $llo = i2c_smbus_read_byte_data($file, 0x06);
 
5013
                my $rlo = i2c_smbus_read_byte_data($file, 0x08);
 
5014
 
 
5015
                # If all registers hold the same value, it has to be a misdetection
 
5016
                return if $lte == $rte and $lte == $lhi and $lte == $rhi
 
5017
                      and $lte == $llo and $lte == $rlo;
 
5018
 
 
5019
                # Negative temperatures
 
5020
                return if ($lte & 0x80) or ($rte & 0x80);
 
5021
                # Negative high limits
 
5022
                return if ($lhi & 0x80) or ($rhi & 0x80);
 
5023
                # Low limits over high limits
 
5024
                if ($chip == 2) {
 
5025
                        $llo -= 256 if ($llo & 0x80);
 
5026
                        $rlo -= 256 if ($rlo & 0x80);
 
5027
                        return if ($llo > $lhi) or ($rlo > $rhi);
 
5028
                }
 
5029
                return 3;
 
5030
        }
 
5031
 
 
5032
        return ($chip <= 3) ? 7 : 5;
 
5033
}
 
5034
 
 
5035
# Chip to detect: 0 = MAX1668, 1 = MAX1805, 2 = MAX1989
 
5036
# Registers used:
 
5037
#   0xfe: Company ID
 
5038
#   0xff: Device ID
 
5039
sub max1668_detect
 
5040
{
 
5041
        my ($file, $addr, $chip) = @_;
 
5042
        my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
 
5043
        my $dev_id = i2c_smbus_read_byte_data($file, 0xff);
 
5044
 
 
5045
        return if $man_id != 0x4d;
 
5046
        return if $chip == 0 and $dev_id != 0x03;
 
5047
        return if $chip == 1 and $dev_id != 0x05;
 
5048
        return if $chip == 2 and $dev_id != 0x0b;
 
5049
 
 
5050
        return 7;
 
5051
}
 
5052
 
 
5053
# Chip to detect: 0 = MAX1619, 1 = MAX1618
 
5054
# Registers used:
 
5055
#   0xfe: Company ID
 
5056
#   0xff: Device ID
 
5057
#   0x02: Status
 
5058
#   0x03: Configuration
 
5059
#   0x04: Conversion rate
 
5060
sub max1619_detect
 
5061
{
 
5062
        my ($file, $addr, $chip) = @_;
 
5063
        my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
 
5064
        my $dev_id = i2c_smbus_read_byte_data($file, 0xff);
 
5065
        my $conf = i2c_smbus_read_byte_data($file, 0x03);
 
5066
        my $status = i2c_smbus_read_byte_data($file, 0x02);
 
5067
        my $convrate = i2c_smbus_read_byte_data($file, 0x04);
 
5068
 
 
5069
        return if $man_id != 0x4D;      # Maxim
 
5070
 
 
5071
        if ($chip == 0) {               # MAX1619
 
5072
                return if $dev_id != 0x04
 
5073
                       or ($conf & 0x03)
 
5074
                       or ($status & 0x61)
 
5075
                       or $convrate >= 8;
 
5076
        }
 
5077
        if ($chip == 1) {               # MAX1618
 
5078
                return if $dev_id != 0x02
 
5079
                       or ($conf & 0x07)
 
5080
                       or ($status & 0x63);
 
5081
        }
 
5082
 
 
5083
        return 7;
 
5084
}
 
5085
 
 
5086
# Registers used:
 
5087
#   0x28: User ID
 
5088
#   0x29: User ID2
 
5089
sub ite_overclock_detect
 
5090
{
 
5091
        my ($file, $addr) = @_;
 
5092
 
 
5093
        my $uid1 = i2c_smbus_read_byte_data($file, 0x28);
 
5094
        my $uid2 = i2c_smbus_read_byte_data($file, 0x29);
 
5095
        return if $uid1 != 0x83 || $uid2 != 0x12;
 
5096
 
 
5097
        return 6;
 
5098
}
 
5099
 
 
5100
# Registers used:
 
5101
#   0x00: Configuration
 
5102
#   0x48: Full I2C Address
 
5103
#   0x58: Mfr ID
 
5104
#   0x5b: Device ID
 
5105
sub it8712_i2c_detect
 
5106
{
 
5107
        my ($file, $addr) = @_;
 
5108
        my $reg;
 
5109
        return unless i2c_smbus_read_byte_data($file, 0x48) == $addr;
 
5110
        return unless (i2c_smbus_read_byte_data($file, 0x00) & 0x90) == 0x10;
 
5111
        return unless i2c_smbus_read_byte_data($file, 0x58) == 0x90;
 
5112
        return if i2c_smbus_read_byte_data($file, 0x5b) != 0x12;
 
5113
        return 7 + ($addr == 0x2d);
 
5114
}
 
5115
 
 
5116
# Registers used:
 
5117
#   0-63: SPD Data and Checksum
 
5118
sub eeprom_detect
 
5119
{
 
5120
        my ($file, $addr) = @_;
 
5121
        my $checksum = 0;
 
5122
 
 
5123
        # Check the checksum for validity (works for most DIMMs and RIMMs)
 
5124
        for (my $i = 0; $i <= 62; $i++) {
 
5125
                $checksum += i2c_smbus_read_byte_data($file, $i);
 
5126
        }
 
5127
        $checksum &= 255;
 
5128
 
 
5129
        return 8 if $checksum == i2c_smbus_read_byte_data($file, 63);
 
5130
        return;
 
5131
}
 
5132
 
 
5133
# Registers used:
 
5134
#   0x00..0x07: DDC signature
 
5135
sub ddcmonitor_detect
 
5136
{
 
5137
        my ($file, $addr) = @_;
 
5138
 
 
5139
        return unless
 
5140
                i2c_smbus_read_byte_data($file, 0x00) == 0x00 and
 
5141
                i2c_smbus_read_byte_data($file, 0x01) == 0xFF and
 
5142
                i2c_smbus_read_byte_data($file, 0x02) == 0xFF and
 
5143
                i2c_smbus_read_byte_data($file, 0x03) == 0xFF and
 
5144
                i2c_smbus_read_byte_data($file, 0x04) == 0xFF and
 
5145
                i2c_smbus_read_byte_data($file, 0x05) == 0xFF and
 
5146
                i2c_smbus_read_byte_data($file, 0x06) == 0xFF and
 
5147
                i2c_smbus_read_byte_data($file, 0x07) == 0x00;
 
5148
 
 
5149
        return 8;
 
5150
}
 
5151
 
 
5152
# Chip to detect: 0 = Poseidon I, 1 = Poseidon II, 2 = Scylla,
 
5153
#                 3 = Hermes, 4 = Heimdal, 5 = Heracles
 
5154
# Registers used:
 
5155
#   0x00-0x02: Identification (3 capital ASCII letters)
 
5156
sub fsc_detect
 
5157
{
 
5158
        my ($file, $addr, $chip) = @_;
 
5159
        my $id;
 
5160
 
 
5161
        $id = chr(i2c_smbus_read_byte_data($file, 0x00))
 
5162
            . chr(i2c_smbus_read_byte_data($file, 0x01))
 
5163
            . chr(i2c_smbus_read_byte_data($file, 0x02));
 
5164
 
 
5165
        return if $chip == 0 and $id ne 'PEG';  # Pegasus? aka Poseidon I
 
5166
        return if $chip == 1 and $id ne 'POS';  # Poseidon II
 
5167
        return if $chip == 2 and $id ne 'SCY';  # Scylla
 
5168
        return if $chip == 3 and $id ne 'HER';  # Hermes
 
5169
        return if $chip == 4 and $id ne 'HMD';  # Heimdal
 
5170
        return if $chip == 5 and $id ne 'HRC';  # Heracles
 
5171
        return if $chip == 6 and $id ne 'HDS';  # Hades
 
5172
        return if $chip == 7 and $id ne 'SYL';  # Syleus
 
5173
 
 
5174
        return 8;
 
5175
}
 
5176
 
 
5177
# Registers used:
 
5178
#   0x3E: Manufacturer ID
 
5179
#   0x3F: Version/Stepping
 
5180
sub lm93_detect
 
5181
{
 
5182
        my ($file, $addr) = @_;
 
5183
        return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x01
 
5184
                  and i2c_smbus_read_byte_data($file, 0x3F) == 0x73;
 
5185
        return 5;
 
5186
}
 
5187
 
 
5188
# Registers used:
 
5189
#   0x3F: Revision ID
 
5190
#   0x48: Address
 
5191
#   0x4A, 0x4B, 0x4F, 0x57, 0x58: Reserved bits.
 
5192
# We do not use 0x49's reserved bits on purpose. The register is named
 
5193
# "VID4/Device ID" so it is doubtful bits 7-1 are really unused.
 
5194
sub m5879_detect
 
5195
{
 
5196
        my ($file, $addr) = @_;
 
5197
 
 
5198
        return unless i2c_smbus_read_byte_data($file, 0x3F) == 0x01;
 
5199
        return unless i2c_smbus_read_byte_data($file, 0x48) == $addr;
 
5200
 
 
5201
        return unless (i2c_smbus_read_byte_data($file, 0x4A) & 0x06) == 0
 
5202
                  and (i2c_smbus_read_byte_data($file, 0x4B) & 0xFC) == 0
 
5203
                  and (i2c_smbus_read_byte_data($file, 0x4F) & 0xFC) == 0
 
5204
                  and (i2c_smbus_read_byte_data($file, 0x57) & 0xFE) == 0
 
5205
                  and (i2c_smbus_read_byte_data($file, 0x58) & 0xEF) == 0;
 
5206
 
 
5207
        return 7;
 
5208
}
 
5209
 
 
5210
# Registers used:
 
5211
#   0x3E: Manufacturer ID
 
5212
#   0x3F: Version/Stepping
 
5213
#   0x47: VID (3 reserved bits)
 
5214
#   0x49: VID4 (7 reserved bits)
 
5215
sub smsc47m192_detect
 
5216
{
 
5217
        my ($file, $addr) = @_;
 
5218
        return unless i2c_smbus_read_byte_data($file, 0x3E) == 0x55
 
5219
                  and (i2c_smbus_read_byte_data($file, 0x3F) & 0xF0) == 0x20
 
5220
                  and (i2c_smbus_read_byte_data($file, 0x47) & 0x70) == 0x00
 
5221
                  and (i2c_smbus_read_byte_data($file, 0x49) & 0xFE) == 0x80;
 
5222
        return ($addr == 0x2d ? 6 : 5);
 
5223
}
 
5224
 
 
5225
# Chip to detect: 1 = DME1737, 2 = SCH5027
 
5226
# Registers used:
 
5227
#   0x3E: Manufacturer ID
 
5228
#   0x3F: Version/Stepping
 
5229
#   0x73: Read-only test register (4 test bits)
 
5230
#   0x8A: Read-only test register (7 test bits)
 
5231
#   0xBA: Read-only test register (8 test bits)
 
5232
sub dme1737_detect
 
5233
{
 
5234
        my ($file, $addr, $chip) = @_;
 
5235
        my $vendor = i2c_smbus_read_byte_data($file, 0x3E);
 
5236
        my $verstep = i2c_smbus_read_byte_data($file, 0x3F);
 
5237
 
 
5238
        return unless $vendor == 0x5C; # SMSC
 
5239
 
 
5240
        if ($chip == 1) { # DME1737
 
5241
                return unless ($verstep & 0xF8) == 0x88 and
 
5242
                              (i2c_smbus_read_byte_data($file, 0x73) & 0x0F) == 0x09 and
 
5243
                              (i2c_smbus_read_byte_data($file, 0x8A) & 0x7F) == 0x4D;
 
5244
        } elsif ($chip == 2) { # SCH5027
 
5245
                return unless $verstep >= 0x69 and $verstep <= 0x6F and
 
5246
                              i2c_smbus_read_byte_data($file, 0xBA) == 0x0F;
 
5247
        }
 
5248
 
 
5249
        return ($addr == 0x2e ? 6 : 5);
 
5250
}
 
5251
 
 
5252
# Chip to detect: 1 = F75111R/RG/N, 2 = F75121R/F75122R/RG, 3 = F75373S/SG,
 
5253
#                 4 = F75375S/SP, 5 = F75387SG/RG, 6 = F75383M/S/F75384M/S,
 
5254
#                 7 = custom power control IC
 
5255
# Registers used:
 
5256
#   0x5A-0x5B: Chip ID
 
5257
#   0x5D-0x5E: Vendor ID
 
5258
sub fintek_detect
 
5259
{
 
5260
        my ($file, $addr, $chip) = @_;
 
5261
        my $chipid = (i2c_smbus_read_byte_data($file, 0x5A) << 8)
 
5262
                   | i2c_smbus_read_byte_data($file, 0x5B);
 
5263
        my $vendid = (i2c_smbus_read_byte_data($file, 0x5D) << 8)
 
5264
                   | i2c_smbus_read_byte_data($file, 0x5E);
 
5265
 
 
5266
        return unless $vendid == 0x1934; # Fintek ID
 
5267
 
 
5268
        if ($chip == 1) { # F75111R/RG/N
 
5269
                return unless $chipid == 0x0300;
 
5270
        } elsif ($chip == 2) { # F75121R/F75122R/RG
 
5271
                return unless $chipid == 0x0301;
 
5272
        } elsif ($chip == 3) { # F75373S/SG
 
5273
                return unless $chipid == 0x0204;
 
5274
        } elsif ($chip == 4) { # F75375S/SP
 
5275
                return unless $chipid == 0x0306;
 
5276
        } elsif ($chip == 5) { # F75387SG/RG
 
5277
                return unless $chipid == 0x0410;
 
5278
        } elsif ($chip == 6) { # F75383M/S/F75384M/S
 
5279
                # The datasheet has 0x0303, but Fintek say 0x0413 is also
 
5280
                # possible
 
5281
                return unless $chipid == 0x0303 || $chipid == 0x0413;
 
5282
        } elsif ($chip == 7) { # custom power control IC
 
5283
                return unless $chipid == 0x0302;
 
5284
        }
 
5285
 
 
5286
        return 7;
 
5287
}
 
5288
 
 
5289
# Chip to detect: 0 = EMC1403, 1 = EMC1404, 2 = EMC2103
 
5290
# Registers used:
 
5291
#   0xfd: Device ID register
 
5292
#   0xfe: Vendor ID register
 
5293
#   0xff: Revision register
 
5294
sub emc1403_detect
 
5295
{
 
5296
        my ($file, $addr, $chip) = @_;
 
5297
        my $dev_id = i2c_smbus_read_byte_data($file, 0xfd);
 
5298
        my $man_id = i2c_smbus_read_byte_data($file, 0xfe);
 
5299
        my $rev = i2c_smbus_read_byte_data($file, 0xff);
 
5300
 
 
5301
        return unless $man_id == 0x5d;  # SMSC
 
5302
 
 
5303
        if ($chip == 0) {
 
5304
                return unless $dev_id == 0x21;
 
5305
                return unless $rev == 0x01;
 
5306
        } elsif ($chip == 1) {
 
5307
                return unless $dev_id == 0x25;
 
5308
                return unless $rev == 0x01;
 
5309
        } elsif ($chip == 2) {
 
5310
                return unless ($dev_id == 0x24) || ($dev_id == 0x26);
 
5311
                return unless $rev == 0x01;
 
5312
        }
 
5313
 
 
5314
        return 6;
 
5315
}
 
5316
 
 
5317
# This checks for non-FFFF values for temperature, voltage, and current.
 
5318
# The address (0x0b) is specified by the SMBus standard so it's likely
 
5319
# that this really is a smart battery.
 
5320
sub smartbatt_detect
 
5321
{
 
5322
        my ($file, $addr) = @_;
 
5323
 
 
5324
        return if i2c_smbus_read_word_data($file, 0x08) == 0xffff
 
5325
               || i2c_smbus_read_word_data($file, 0x09) == 0xffff
 
5326
               || i2c_smbus_read_word_data($file, 0x0a) == 0xffff;
 
5327
        return 5;
 
5328
}
 
5329
 
 
5330
# Chip to detect: 0 = W83L784R/AR/G, 1 = W83L785R/G, 2 = W83L786NR/NG/R/G,
 
5331
#                 3 = W83L785TS-S
 
5332
# Registers used:
 
5333
#   0x40: Configuration
 
5334
#   0x4a: Full I2C Address (W83L784R only)
 
5335
#   0x4b: I2C addresses of emulated LM75 chips (W83L784R only)
 
5336
#   0x4c: Winbond Vendor ID (Low Byte)
 
5337
#   0x4d: Winbond Vendor ID (High Byte)
 
5338
#   0x4e: Chip ID
 
5339
sub w83l784r_detect
 
5340
{
 
5341
        my ($file, $addr, $chip) = @_;
 
5342
        my ($reg, @res);
 
5343
 
 
5344
        return unless (i2c_smbus_read_byte_data($file, 0x40) & 0x80) == 0x00;
 
5345
        return if $chip == 0
 
5346
              and i2c_smbus_read_byte_data($file, 0x4a) != $addr;
 
5347
        return unless i2c_smbus_read_byte_data($file, 0x4c) == 0xa3;
 
5348
        return unless i2c_smbus_read_byte_data($file, 0x4d) == 0x5c;
 
5349
 
 
5350
        $reg = i2c_smbus_read_byte_data($file, 0x4e);
 
5351
        return if $chip == 0 and $reg != 0x50;
 
5352
        return if $chip == 1 and $reg != 0x60;
 
5353
        return if $chip == 2 and $reg != 0x80;
 
5354
        return if $chip == 3 and $reg != 0x70;
 
5355
 
 
5356
        return 8 if $chip != 0; # No subclients
 
5357
 
 
5358
        @res = (8);
 
5359
        $reg = i2c_smbus_read_byte_data($file, 0x4b);
 
5360
        push @res, ($reg & 0x07) + 0x48 unless $reg & 0x08;
 
5361
        push @res, (($reg & 0x70) >> 4) + 0x48 unless $reg & 0x80;
 
5362
        return @res;
 
5363
}
 
5364
 
 
5365
# The max6650 has no device ID register. However, a few registers have
 
5366
# spare bits, which are documented as being always zero on read. We read
 
5367
# all of these registers check the spare bits. Any non-zero means this
 
5368
# is not a max6650/1.
 
5369
#
 
5370
# The always zero bits are:
 
5371
#   configuration byte register (0x02) - top 2 bits
 
5372
#   gpio status register (0x14) - top 3 bits
 
5373
#   alarm enable register (0x08) - top 3 bits
 
5374
#   alarm status register (0x0A) - top 3 bits
 
5375
#   tachometer count time register (0x16) - top 6 bits
 
5376
# Additionally, not all values are possible for lower 3 bits of
 
5377
# the configuration register.
 
5378
sub max6650_detect
 
5379
{
 
5380
        my ($file, $addr) = @_;
 
5381
 
 
5382
        my $conf = i2c_smbus_read_byte_data($file, 0x02);
 
5383
 
 
5384
        return if i2c_smbus_read_byte_data($file, 0x16) & 0xFC;
 
5385
        return if i2c_smbus_read_byte_data($file, 0x0A) & 0xE0;
 
5386
        return if i2c_smbus_read_byte_data($file, 0x08) & 0xE0;
 
5387
        return if i2c_smbus_read_byte_data($file, 0x14) & 0xE0;
 
5388
        return if ($conf & 0xC0) or ($conf & 0x07) > 4;
 
5389
 
 
5390
        return 2;
 
5391
}
 
5392
 
 
5393
sub max6655_detect
 
5394
{
 
5395
        my ($file, $addr) = @_;
 
5396
 
 
5397
        # checking RDID (Device ID)
 
5398
        return unless i2c_smbus_read_byte_data($file, 0xfe) == 0x0a;
 
5399
        # checking RDRV (Manufacturer ID)
 
5400
        return unless i2c_smbus_read_byte_data($file, 0xff) == 0x4d;
 
5401
        # checking unused bits (conversion rate, extended temperature)
 
5402
        return unless i2c_smbus_read_byte_data($file, 0x04) & 0xf8;
 
5403
        return unless i2c_smbus_read_byte_data($file, 0x10) & 0x1f;
 
5404
        return unless i2c_smbus_read_byte_data($file, 0x11) & 0x1f;
 
5405
        return unless i2c_smbus_read_byte_data($file, 0x12) & 0x1f;
 
5406
 
 
5407
        return 6;
 
5408
}
 
5409
 
 
5410
# Chip to detect: 0 = STTS424, 1 = SE97/SE97B, 2 = SE98, 3 = ADT7408,
 
5411
#                 4 = TS3000/TSE2002, 5 = MAX6604, 6 = MCP98242,
 
5412
#                 7 = MCP98243, 8 = MCP9843, 9 = CAT6095 / CAT34TS02,
 
5413
#                 10 = STTS424E
 
5414
# Registers used:
 
5415
#   0x00: Capabilities
 
5416
#   0x01: Configuration
 
5417
#   0x06: Manufacturer ID
 
5418
#   0x07: Device ID
 
5419
sub jedec_JC42_4_detect
 
5420
{
 
5421
        my ($file, $addr, $chip) = @_;
 
5422
        my ($reg, $manid, $devid);
 
5423
 
 
5424
        # We test the MSB only at first, because not all chips enjoy
 
5425
        # word access.
 
5426
 
 
5427
        # Check for unused bits
 
5428
        $reg = i2c_smbus_read_byte_data($file, 0x00);
 
5429
        return if $reg & 0xff;
 
5430
        $reg = i2c_smbus_read_byte_data($file, 0x01);
 
5431
        return if $reg & 0xf8;
 
5432
 
 
5433
        # Check for manufacturer and device ID
 
5434
        $manid = i2c_smbus_read_byte_data($file, 0x06);
 
5435
        $devid = i2c_smbus_read_byte_data($file, 0x07);
 
5436
 
 
5437
        if ($chip == 0) {
 
5438
                return unless $manid == 0x10;           # STMicrolectronics
 
5439
                return unless $devid == 0x01;           # STTS424
 
5440
        } elsif ($chip == 1) {
 
5441
                return unless $manid == 0x11;           # NXP
 
5442
                return unless $devid == 0xa2;           # SE97
 
5443
        } elsif ($chip == 2) {
 
5444
                return unless $manid == 0x11;           # NXP
 
5445
                return unless $devid == 0xa1;           # SE98
 
5446
        } elsif ($chip == 3) {
 
5447
                return unless $manid == 0x11;           # ADT
 
5448
                return unless $devid == 0x08;           # ADT7408
 
5449
        } elsif ($chip == 4) {
 
5450
                return unless $manid == 0x00;           # IDT
 
5451
                return unless $devid == 0x29;           # TS3000/TSE2002
 
5452
        } elsif ($chip == 5) {
 
5453
                return unless $manid == 0x00;           # MAXIM
 
5454
                return unless $devid == 0x3e;           # MAX6604
 
5455
        } elsif ($chip == 6) {
 
5456
                return unless $manid == 0x00;           # MCP
 
5457
                return unless $devid == 0x20;           # MCP98242
 
5458
        } elsif ($chip == 7) {
 
5459
                return unless $manid == 0x00;           # MCP
 
5460
                return unless $devid == 0x21;           # MCP98243
 
5461
        } elsif ($chip == 8) {
 
5462
                return unless $manid == 0x00;           # MCP
 
5463
                return unless $devid == 0x00;           # MCP9843
 
5464
        } elsif ($chip == 9) {
 
5465
                return unless $manid == 0x1b;           # ONS
 
5466
                return unless $devid == 0x08;           # CAT6095 / CAT34TS02
 
5467
        } elsif ($chip == 10) {
 
5468
                return unless $manid == 0x10;           # STMicrolectronics
 
5469
                return unless $devid == 0x00;           # STTS424E02
 
5470
        }
 
5471
 
 
5472
        # Now, do it all again with words. Note that we get
 
5473
        # the MSB first, so all value checks are byte-swapped.
 
5474
 
 
5475
        # Check for unused bits
 
5476
        $reg = i2c_smbus_read_word_data($file, 0x00);
 
5477
        return if $reg < 0 || $reg & 0x00ff;
 
5478
 
 
5479
        $manid = i2c_smbus_read_word_data($file, 0x06);
 
5480
        $devid = i2c_smbus_read_word_data($file, 0x07);
 
5481
        return if $manid < 0 || $devid < 0;
 
5482
        if ($chip == 0) {
 
5483
                return unless $manid == 0x4a10;         # STMicrolectronics
 
5484
                return unless ($devid & 0xfeff) == 0x0001; # STTS424
 
5485
        } elsif ($chip == 1) {
 
5486
                return unless $manid == 0x3111;         # NXP
 
5487
                return unless ($devid & 0xfcff) == 0x00a2; # SE97
 
5488
        } elsif ($chip == 2) {
 
5489
                return unless $manid == 0x3111;         # NXP
 
5490
                return unless ($devid & 0xfcff) == 0x00a1; # SE98
 
5491
        } elsif ($chip == 3) {
 
5492
                return unless $manid == 0xd411;         # ADT
 
5493
                return unless $devid == 0x0108;         # ADT7408
 
5494
        } elsif ($chip == 4) {
 
5495
                return unless $manid == 0xb300;         # IDT
 
5496
                return unless $devid == 0x0329;         # TS3000/TSE2002
 
5497
        } elsif ($chip == 5) {
 
5498
                return unless $manid == 0x4d00;         # MAXIM
 
5499
                return unless $devid == 0x003e;         # MAX6604
 
5500
        } elsif ($chip == 6) {
 
5501
                return unless $manid == 0x5400;         # MCP
 
5502
                return unless ($devid & 0xfcff) == 0x0020; # MCP98242
 
5503
        } elsif ($chip == 7) {
 
5504
                return unless $manid == 0x5400;         # MCP
 
5505
                return unless ($devid & 0xfcff) == 0x0021; # MCP98243
 
5506
        } elsif ($chip == 8) {
 
5507
                return unless $manid == 0x5400;         # MCP
 
5508
                return unless ($devid & 0xfcff) == 0x0000; # MCP9843
 
5509
        } elsif ($chip == 9) {
 
5510
                return unless $manid == 0x091b;         # ONS
 
5511
                return unless ($devid & 0xe0ff) == 0x0008; # CAT6095 / CAT34TS02
 
5512
        } elsif ($chip == 10) {
 
5513
                return unless $manid == 0x4a10;         # STMicrolectronics
 
5514
                return unless ($devid & 0xfeff) == 0x0000; # STTS424E02
 
5515
        }
 
5516
 
 
5517
        return 5;
 
5518
}
 
5519
 
 
5520
# This isn't very good detection.
 
5521
# Verify the i2c address, and the stepping ID (which is 0xb0 on
 
5522
# my chip but could be different for others...
 
5523
sub vt1211_i2c_detect
 
5524
{
 
5525
        my ($file, $addr) = @_;
 
5526
        return unless (i2c_smbus_read_byte_data($file, 0x48) & 0x7f) == $addr;
 
5527
        return unless i2c_smbus_read_byte_data($file, 0x3f) == 0xb0;
 
5528
        return 2;
 
5529
}
 
5530
 
 
5531
# All ISA detection functions below take at least 1 parameter:
 
5532
# $_[0]: Address
 
5533
# Some of these functions which can detect more than one type of device,
 
5534
# take a second parameter:
 
5535
# $_[1]: Chip to detect
 
5536
 
 
5537
# Chip to detect: 0 = LM78, 2 = LM79
 
5538
sub lm78_isa_detect
 
5539
{
 
5540
        my ($addr, $chip) = @_;
 
5541
        my $val = inb($addr + 1);
 
5542
        return if inb($addr + 2) != $val or inb($addr + 3) != $val or
 
5543
                  inb($addr + 7) != $val;
 
5544
 
 
5545
        $val = inb($addr + 5);
 
5546
        outb($addr + 5, ~$val & 0x7f);
 
5547
        if ((inb($addr+5) & 0x7f) != (~ $val & 0x7f)) {
 
5548
                outb($addr+5, $val);
 
5549
                return;
 
5550
        }
 
5551
 
 
5552
        return unless (isa_read_i5d6($addr, 0x40) & 0x80) == 0x00;
 
5553
        my $reg = isa_read_i5d6($addr, 0x49);
 
5554
        return if $chip == 0 && ($reg != 0x00 && $reg != 0x20 && $reg != 0x40);
 
5555
        return if $chip == 2 && ($reg & 0xfe) != 0xc0;
 
5556
 
 
5557
        # Explicitly prevent misdetection of Winbond chips
 
5558
        $reg = isa_read_i5d6($addr, 0x4f);
 
5559
        return if $reg == 0xa3 || $reg == 0x5c;
 
5560
 
 
5561
        # Explicitly prevent misdetection of ITE chips
 
5562
        $reg = isa_read_i5d6($addr, 0x58);
 
5563
        return if $reg == 0x90;
 
5564
 
 
5565
        return 6;
 
5566
}
 
5567
 
 
5568
# Chip to detect: 0 = W83781D, 1 = W83782D
 
5569
sub w83781d_isa_detect
 
5570
{
 
5571
        my ($addr, $chip) = @_;
 
5572
        my ($reg1, $reg2);
 
5573
        my $val = inb($addr + 1);
 
5574
        return if inb($addr + 2) != $val or inb($addr + 3) != $val or
 
5575
                  inb($addr + 7) != $val;
 
5576
 
 
5577
        $val = inb($addr + 5);
 
5578
        outb($addr+5, ~$val & 0x7f);
 
5579
        if ((inb($addr+5) & 0x7f) != (~ $val & 0x7f)) {
 
5580
                outb($addr+5, $val);
 
5581
                return;
 
5582
        }
 
5583
 
 
5584
        $reg1 = isa_read_i5d6($addr, 0x4e);
 
5585
        $reg2 = isa_read_i5d6($addr, 0x4f);
 
5586
        return unless (($reg1 & 0x80) == 0x00 and $reg2 == 0xa3) or
 
5587
                      (($reg1 & 0x80) == 0x80 and $reg2 == 0x5c);
 
5588
        return unless ($reg1 & 0x07) == 0x00;
 
5589
        $reg1 = isa_read_i5d6($addr, 0x58);
 
5590
        return if $chip == 0 && ($reg1 & 0xfe) != 0x10;
 
5591
        return if $chip == 1 && ($reg1 & 0xfe) != 0x30;
 
5592
 
 
5593
        return 8;
 
5594
}
 
5595
 
 
5596
########
 
5597
# IPMI #
 
5598
########
 
5599
 
 
5600
# Returns: number of IPMI interfaces found
 
5601
sub ipmi_from_smbios
 
5602
{
 
5603
        my ($version, $if, @ipmi_if);
 
5604
 
 
5605
        return 0 unless check_dmidecode_version();
 
5606
 
 
5607
        # Parse the output of dmidecode into an array of IPMI interfaces.
 
5608
        # Each entry is a hash with the following keys: type and addr.
 
5609
        $if = -1;
 
5610
        open(local *DMIDECODE, "dmidecode -t 38 2>/dev/null |") or return 0;
 
5611
        while (<DMIDECODE>) {
 
5612
                if (m/^IPMI Device Information/) {
 
5613
                        $if++;
 
5614
                        next;
 
5615
                }
 
5616
                next unless $if >= 0;
 
5617
 
 
5618
                if (m/^\tInterface Type: (.*)$/) {
 
5619
                        $ipmi_if[$if]->{type} = "IPMI BMC $1";
 
5620
                        $ipmi_if[$if]->{type} =~ s/ \(.*//;
 
5621
                        next;
 
5622
                }
 
5623
                if (m/^\tBase Address: (0x[0-9A-Fa-f]+) \(I\/O\)$/) {
 
5624
                        $ipmi_if[$if]->{addr} = oct($1);
 
5625
                        next;
 
5626
                }
 
5627
        }
 
5628
        close(DMIDECODE);
 
5629
 
 
5630
        foreach $if (@ipmi_if) {
 
5631
                if (exists $if->{addr}) {
 
5632
                        printf("\%-60s", sprintf("Found `\%s' at 0x\%x... ",
 
5633
                                                 $if->{type}, $if->{addr}));
 
5634
                } else {
 
5635
                        printf("\%-60s", sprintf("Found `\%s'... ",
 
5636
                                                 $if->{type}));
 
5637
                }
 
5638
                print "Success!\n".
 
5639
                      "    (confidence 8, driver `ipmisensors')\n";
 
5640
                my $new_hash = {
 
5641
                        conf => 8,
 
5642
                        isa_addr => $if->{addr} || 0,
 
5643
                        chipname => $if->{type},
 
5644
                };
 
5645
                add_isa_to_chips_detected("ipmisensors", $new_hash);
 
5646
        }
 
5647
 
 
5648
        return scalar @ipmi_if;
 
5649
}
 
5650
 
 
5651
# We simply look for a register at standard locations.
 
5652
# For KCS, use the STATUS register. For SMIC, use the FLAGS register.
 
5653
# Incidentally they live at the same offset.
 
5654
sub ipmi_detect
 
5655
{
 
5656
        my ($addr) = @_;
 
5657
        return if inb($addr + 3) == 0xff;
 
5658
        return 4;
 
5659
}
 
5660
 
 
5661
###################
 
5662
# ALIAS DETECTION #
 
5663
###################
 
5664
 
 
5665
# These functions take at least 3 parameters:
 
5666
# $_[0]: ISA/LPC address
 
5667
# $_[1]: I2C file handle
 
5668
# $_[2]: I2C address
 
5669
# Some of these functions may take extra parameters.
 
5670
# They return 1 if both devices are the same, 0 if not.
 
5671
 
 
5672
# Extra parameters:
 
5673
# $_[3]: First limit register to compare
 
5674
# $_[4]: Last limit register to compare
 
5675
sub winbond_alias_detect
 
5676
{
 
5677
        my ($isa_addr, $file, $i2c_addr, $first, $last) = @_;
 
5678
        my $i;
 
5679
 
 
5680
        return 0 unless isa_read_i5d6($isa_addr, 0x48) == $i2c_addr;
 
5681
        for ($i = $first; $i <= $last; $i++) {
 
5682
                return 0 unless isa_read_i5d6($isa_addr, $i) ==
 
5683
                                i2c_smbus_read_byte_data($file, $i);
 
5684
        }
 
5685
        return 1;
 
5686
}
 
5687
 
 
5688
############################
 
5689
# PCI CHIP / CPU DETECTION #
 
5690
############################
 
5691
 
 
5692
sub sis5595_pci_detect
 
5693
{
 
5694
        return unless exists $pci_list{'1039:0008'};
 
5695
        return 9;
 
5696
}
 
5697
 
 
5698
sub via686a_pci_detect
 
5699
{
 
5700
        return unless exists $pci_list{'1106:3057'};
 
5701
        return 9;
 
5702
}
 
5703
 
 
5704
sub via8231_pci_detect
 
5705
{
 
5706
        return unless exists $pci_list{'1106:8235'};
 
5707
        return 9;
 
5708
}
 
5709
 
 
5710
sub k8temp_pci_detect
 
5711
{
 
5712
        return unless exists $pci_list{'1022:1103'};
 
5713
        return 9;
 
5714
}
 
5715
 
 
5716
sub fam10h_pci_detect
 
5717
{
 
5718
        return unless exists $pci_list{'1022:1203'};
 
5719
 
 
5720
        # Errata 319 (Inaccurate Temperature Measurement) affects
 
5721
        # revisions DR-BA, DR-B2 and DR-B3, all have model number = 2.
 
5722
        # Revisions RB-C2 and HY-D0 are also affected.
 
5723
        my $probecpu;
 
5724
        foreach $probecpu (@cpu) {
 
5725
                next unless $probecpu->{vendor_id} eq 'AuthenticAMD' &&
 
5726
                            $probecpu->{'cpu family'} == 0x10;
 
5727
 
 
5728
                next if $probecpu->{model} < 4;         # DR-B*
 
5729
                next if $probecpu->{model} == 8;        # HY-D0
 
5730
                if ($probecpu->{model} == 4 && $probecpu->{stepping} <= 2) {    # RB-C2
 
5731
                        my @dram_cfg = split /\n/, `setpci -d 1022:1202 94.L 2>/dev/null`;
 
5732
                        next unless @dram_cfg >= 1;
 
5733
                        next unless hex($dram_cfg[0]) & 0x00000100;     # DDR3
 
5734
                }
 
5735
 
 
5736
                return 9;
 
5737
        }
 
5738
        
 
5739
        return;
 
5740
}
 
5741
 
 
5742
sub fam11h_pci_detect
 
5743
{
 
5744
        return unless exists $pci_list{'1022:1303'};
 
5745
        return 9;
 
5746
}
 
5747
 
 
5748
sub intel_amb_detect
 
5749
{
 
5750
        if ((exists $pci_list{'8086:25f0'}) ||  # Intel 5000
 
5751
            (exists $pci_list{'8086:4030'})) {  # Intel 5400
 
5752
                return 9;
 
5753
        }
 
5754
        return;
 
5755
}
 
5756
 
 
5757
sub coretemp_detect
 
5758
{
 
5759
        my $chip = shift;
 
5760
        my $probecpu;
 
5761
 
 
5762
        foreach $probecpu (@cpu) {
 
5763
                next unless $probecpu->{vendor_id} eq 'GenuineIntel' &&
 
5764
                            $probecpu->{'cpu family'} == 6;
 
5765
                return 9 if $chip == 0 &&
 
5766
                        ($probecpu->{model} == 14 ||    # Pentium M DC
 
5767
                         $probecpu->{model} == 15 ||    # Core 2 DC 65nm
 
5768
                         $probecpu->{model} == 0x16 ||  # Core 2 SC 65nm
 
5769
                         $probecpu->{model} == 0x17 ||  # Penryn 45nm
 
5770
                         $probecpu->{model} == 0x1a ||  # Nehalem
 
5771
                         $probecpu->{model} == 0x1e);   # Lynnfield
 
5772
                return 9 if $chip == 1 &&
 
5773
                        ($probecpu->{model} == 0x1c);   # Atom
 
5774
        }
 
5775
        return;
 
5776
}
 
5777
 
 
5778
sub via_c7_detect
 
5779
{
 
5780
        my $probecpu;
 
5781
        foreach $probecpu (@cpu) {
 
5782
                if ($probecpu->{vendor_id} eq 'CentaurHauls' &&
 
5783
                                $probecpu->{'cpu family'} == 6 &&
 
5784
                                ($probecpu->{model} == 0xa ||
 
5785
                                 $probecpu->{model} == 0xd)) {
 
5786
                        return 9;
 
5787
                }
 
5788
        }
 
5789
        return;
 
5790
}
 
5791
 
 
5792
sub via_nano_detect
 
5793
{
 
5794
        my $probecpu;
 
5795
        foreach $probecpu (@cpu) {
 
5796
                if ($probecpu->{vendor_id} eq 'CentaurHauls' &&
 
5797
                                $probecpu->{'cpu family'} == 6 &&
 
5798
                                $probecpu->{model} == 0xf) {
 
5799
                        return 9;
 
5800
                }
 
5801
        }
 
5802
        return;
 
5803
}
 
5804
 
 
5805
#################
 
5806
# SPECIAL MODES #
 
5807
#################
 
5808
 
 
5809
sub show_i2c_stats
 
5810
{
 
5811
        my ($chip, $addr, %histo, $chips);
 
5812
 
 
5813
        # Gather the data
 
5814
        foreach $chip (@chip_ids) {
 
5815
                next unless defined $chip->{i2c_addrs};
 
5816
                $chips++;
 
5817
                foreach my $addr (@{$chip->{i2c_addrs}}) {
 
5818
                        $histo{$addr}++;
 
5819
                }
 
5820
        }
 
5821
 
 
5822
        # Display the data
 
5823
        printf "\%d I2C chips known, \%d I2C addresses probed\n\n",
 
5824
                $chips, scalar keys %histo;
 
5825
        print "     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n".
 
5826
              "00:         ";
 
5827
        for (my $addr = 0x03; $addr <= 0x77; $addr++) {
 
5828
                printf("\n\%02x:", $addr) if ($addr % 16) == 0;
 
5829
                if (defined $histo{$addr}) {
 
5830
                        printf ' %02d', $histo{$addr};
 
5831
                } else {
 
5832
                        print ' --';
 
5833
                }
 
5834
        }
 
5835
        print "\n";
 
5836
}
 
5837
 
 
5838
################
 
5839
# MAIN PROGRAM #
 
5840
################
 
5841
 
 
5842
# $_[0]: reference to a list of chip hashes
 
5843
sub print_chips_report
 
5844
{
 
5845
        my ($listref) = @_;
 
5846
        my $data;
 
5847
 
 
5848
        foreach $data (@$listref) {
 
5849
                my $is_i2c = exists $data->{i2c_addr};
 
5850
                my $is_isa = exists $data->{isa_addr};
 
5851
                print "  * ";
 
5852
                if ($is_i2c) {
 
5853
                        printf "Bus `%s'\n", $i2c_adapters[$data->{i2c_devnr}]->{name};
 
5854
                        printf "    Busdriver `%s', I2C address 0x%02x",
 
5855
                               $i2c_adapters[$data->{i2c_devnr}]->{driver}, $data->{i2c_addr};
 
5856
                        if (exists $data->{i2c_sub_addrs}) {
 
5857
                                print " (and";
 
5858
                                my $sub_addr;
 
5859
                                foreach $sub_addr (@{$data->{i2c_sub_addrs}}) {
 
5860
                                        printf " 0x%02x", $sub_addr;
 
5861
                                }
 
5862
                                print ")"
 
5863
                        }
 
5864
                        print "\n    ";
 
5865
                }
 
5866
                if ($is_isa) {
 
5867
                        print "ISA bus";
 
5868
                        if ($data->{isa_addr}) {
 
5869
                                printf ", address 0x%x", $data->{isa_addr};
 
5870
                        }
 
5871
                        print " (Busdriver `i2c-isa')"
 
5872
                                unless kernel_version_at_least(2, 6, 18);
 
5873
                        print "\n    ";
 
5874
                }
 
5875
                printf "Chip `%s' (confidence: %d)\n",
 
5876
                       $data->{chipname}, $data->{conf};
 
5877
        }
 
5878
}
 
5879
 
 
5880
sub generate_modprobes
 
5881
{
 
5882
        my ($driver, $detection, $adap);
 
5883
        my ($configfile, %bus_modules, %hwmon_modules);
 
5884
 
 
5885
        foreach $driver (keys %chips_detected) {
 
5886
                foreach $detection (@{$chips_detected{$driver}}) {
 
5887
                        # Tag adapters which host hardware monitoring chips we want to access
 
5888
                        if (exists $detection->{i2c_devnr}
 
5889
                         && !exists $detection->{isa_addr}) {
 
5890
                                $i2c_adapters[$detection->{i2c_devnr}]->{used}++;
 
5891
                        }
 
5892
 
 
5893
                        # i2c-isa is loaded automatically (as a dependency)
 
5894
                        # since 2.6.14, and will soon be gone.
 
5895
                        if (exists $detection->{isa_addr}
 
5896
                         && !kernel_version_at_least(2, 6, 18)) {
 
5897
                                $bus_modules{"i2c-isa"}++
 
5898
                        }
 
5899
                }
 
5900
                if ($driver eq "ipmisensors") {
 
5901
                        $bus_modules{"ipmi-si"}++;
 
5902
                }
 
5903
        }
 
5904
 
 
5905
        # Handle aliases
 
5906
        # As of kernel 2.6.28, alias detection is handled by kernel drivers
 
5907
        # directly, so module options are no longer needed.
 
5908
        unless (kernel_version_at_least(2, 6, 28)) {
 
5909
                foreach $driver (keys %chips_detected) {
 
5910
                        my @optionlist = ();
 
5911
                        foreach $detection (@{$chips_detected{$driver}}) {
 
5912
                                next unless exists $detection->{i2c_addr}
 
5913
                                         && exists $detection->{isa_addr}
 
5914
                                         && $i2c_adapters[$detection->{i2c_devnr}]->{used};
 
5915
 
 
5916
                                push @optionlist, sprintf("%d,0x%02x",
 
5917
                                                          $detection->{i2c_devnr},
 
5918
                                                          $detection->{i2c_addr});
 
5919
                        }
 
5920
 
 
5921
                        next if not @optionlist;
 
5922
                        $configfile = "# hwmon module options\n"
 
5923
                                unless defined $configfile;
 
5924
                        $configfile .= "options $driver ignore=".
 
5925
                                       (join ",", @optionlist)."\n";
 
5926
                }
 
5927
        }
 
5928
 
 
5929
        # If we added any module option to handle aliases, we need to load all
 
5930
        # the adapter drivers so that the numbers will be the same. If not, then
 
5931
        # we only load the adapter drivers which are useful.
 
5932
        foreach $adap (@i2c_adapters) {
 
5933
                next if $adap->{autoload};
 
5934
                next if $adap->{driver} eq 'UNKNOWN';
 
5935
                next if not defined $configfile and not $adap->{used};
 
5936
                $bus_modules{$adap->{driver}}++;
 
5937
        }
 
5938
 
 
5939
        # Now determine the chip probe lines
 
5940
        foreach $driver (keys %chips_detected) {
 
5941
                next if not @{$chips_detected{$driver}};
 
5942
                if ($driver eq "to-be-written") {
 
5943
                        print "Note: there is no driver for ${$chips_detected{$driver}}[0]{chipname} yet.\n".
 
5944
                              "Check http://www.lm-sensors.org/wiki/Devices for updates.\n\n";
 
5945
                } else {
 
5946
                        open(local *INPUTFILE, "modprobe -l $driver 2>/dev/null |");
 
5947
                        local $_;
 
5948
                        my $modulefound = 0;
 
5949
                        while (<INPUTFILE>) {
 
5950
                                if (m@/@) {
 
5951
                                        $modulefound = 1;
 
5952
                                        last;
 
5953
                                }
 
5954
                        }
 
5955
                        close(INPUTFILE);
 
5956
                        # Check return value from modprobe in case modprobe -l
 
5957
                        # isn't supported
 
5958
                        if ((($? >> 8) == 0) && ! $modulefound) {
 
5959
                                print "Warning: the required module $driver is not currently installed\n".
 
5960
                                      "on your system. If it is built into the kernel then it's OK.\n".
 
5961
                                      "Otherwise, check http://www.lm-sensors.org/wiki/Devices for\n".
 
5962
                                      "driver availability.\n\n";
 
5963
                        } else {
 
5964
                                $hwmon_modules{$driver}++
 
5965
                                        unless hwmon_is_autoloaded($driver);
 
5966
                        }
 
5967
                }
 
5968
        }
 
5969
 
 
5970
        my @bus_modules = sort keys %bus_modules;
 
5971
        my @hwmon_modules = sort keys %hwmon_modules;
 
5972
        return ($configfile, \@bus_modules, \@hwmon_modules);
 
5973
}
 
5974
 
 
5975
sub write_config
 
5976
{
 
5977
        my ($configfile, $bus_modules, $hwmon_modules) = @_;
 
5978
 
 
5979
        if (defined $configfile) {
 
5980
                my $have_modprobe_d = -d '/etc/modprobe.d';
 
5981
                printf "Do you want to \%s /etc/modprobe.d/lm_sensors.conf? (\%s): ",
 
5982
                       (-e '/etc/modprobe.d/lm_sensors.conf' ? 'overwrite' : 'generate'),
 
5983
                       ($have_modprobe_d ? 'YES/no' : 'yes/NO');
 
5984
                $_ = <STDIN>;
 
5985
                if (($have_modprobe_d and not m/^\s*n/i) or m/^\s*y/i) {
 
5986
                        unless ($have_modprobe_d) {
 
5987
                                mkdir('/etc/modprobe.d', 0777)
 
5988
                                        or die "Sorry, can't create /etc/modprobe.d ($!)";
 
5989
                        }
 
5990
                        open(local *MODPROBE_D, ">/etc/modprobe.d/lm_sensors.conf")
 
5991
                                or die "Sorry, can't create /etc/modprobe.d/lm_sensors.conf ($!)";
 
5992
                        print MODPROBE_D "# Generated by sensors-detect on " . scalar localtime() . "\n";
 
5993
                        print MODPROBE_D $configfile;
 
5994
                        close(MODPROBE_D);
 
5995
                } else {
 
5996
                        print "To make the sensors modules behave correctly, add these lines to\n".
 
5997
                              "/etc/modprobe.conf:\n\n";
 
5998
                        print "#----cut here----\n".
 
5999
                              $configfile.
 
6000
                              "#----cut here----\n\n";
 
6001
                }
 
6002
        }
 
6003
 
 
6004
        print "To load everything that is needed, add this to /etc/modules:\n";
 
6005
        print "#----cut here----\n";
 
6006
        if (@{$bus_modules}) {
 
6007
                print "# Adapter drivers\n";
 
6008
                print "$_\n" foreach (@{$bus_modules});
 
6009
        }
 
6010
        print "# Chip drivers\n";
 
6011
        print "$_\n" foreach (@{$hwmon_modules});
 
6012
        print "#----cut here----\n";
 
6013
 
 
6014
        print "If you have some drivers built into your kernel, the list above will\n".
 
6015
              "contain too many modules. Skip the appropriate ones!\n";
 
6016
 
 
6017
        print "\nDo you want to add these lines automatically to /etc/modules? (yes/NO)";
 
6018
        $_ = <STDIN>;
 
6019
        if (m/^\s*[Yy]/) {
 
6020
                open(MODULES, ">>/etc/modules")
 
6021
                        or die "Sorry, can't create /etc/modules ($!)?!?";
 
6022
                print MODULES "\n# Generated by sensors-detect on " . scalar localtime() . "\n";
 
6023
                if (@{$bus_modules}) {
 
6024
                        print MODULES "# Adapter drivers\n";
 
6025
                        print MODULES "$_\n" foreach (@{$bus_modules});
 
6026
                }
 
6027
                print MODULES "# Chip drivers\n";
 
6028
                print MODULES "$_\n" foreach (@{$hwmon_modules});
 
6029
                close(MODULES);
 
6030
 
 
6031
                print "Successful!\n\n";
 
6032
                print "Monitoring programs won't work until the needed modules are\n".
 
6033
                      "loaded. You may want to run '/etc/init.d/module-init-tools start'\n".
 
6034
                      "to load them.\n";
 
6035
        }
 
6036
        print "\n";
 
6037
}
 
6038
 
 
6039
sub main
 
6040
{
 
6041
        my ($input, $superio_features);
 
6042
 
 
6043
        # Handle special command line cases first
 
6044
        if (defined $ARGV[0] && $ARGV[0] eq "--stat") {
 
6045
                show_i2c_stats();
 
6046
                exit 0;
 
6047
        }
 
6048
 
 
6049
        # We won't go very far if not root
 
6050
        unless ($> == 0) {
 
6051
                print "You need to be root to run this script.\n";
 
6052
                exit -1;
 
6053
        }
 
6054
 
 
6055
        if (-x "/sbin/service" && -f "/etc/init.d/lm_sensors" &&
 
6056
            -f "/var/lock/subsys/lm_sensors") {
 
6057
                system("/sbin/service", "lm_sensors", "stop");
 
6058
        }
 
6059
 
 
6060
        initialize_kernel_version();
 
6061
        initialize_conf();
 
6062
        initialize_pci();
 
6063
        initialize_modules_list();
 
6064
        # Make sure any special case chips are added to the chip_ids list
 
6065
        # before making the support modules list
 
6066
        chip_special_cases();
 
6067
        initialize_modules_supported();
 
6068
        initialize_cpu_list();
 
6069
 
 
6070
        print "# sensors-detect revision $revision\n";
 
6071
        initialize_dmi_data();
 
6072
        print_dmi_summary();
 
6073
        print "\n";
 
6074
        print "This program will help you determine which kernel modules you need\n",
 
6075
              "to load to use lm_sensors most effectively. It is generally safe\n",
 
6076
              "and recommended to accept the default answers to all questions,\n",
 
6077
              "unless you know what you're doing.\n\n";
 
6078
 
 
6079
        print "Some south bridges, CPUs or memory controllers contain embedded sensors.\n".
 
6080
              "Do you want to scan for them? This is totally safe. (YES/no): ";
 
6081
        unless (<STDIN> =~ /^\s*n/i) {
 
6082
                $| = 1;
 
6083
                foreach my $entry (@cpu_ids) {
 
6084
                        scan_cpu($entry);
 
6085
                }
 
6086
                $| = 0;
 
6087
        }
 
6088
        print "\n";
 
6089
 
 
6090
        $superio_features = 0;
 
6091
        # Skip "random" I/O port probing on PPC
 
6092
        if ($kernel_arch ne 'ppc'
 
6093
         && $kernel_arch ne 'ppc64') {
 
6094
                print "Some Super I/O chips contain embedded sensors. We have to write to\n".
 
6095
                      "standard I/O ports to probe them. This is usually safe.\n";
 
6096
                print "Do you want to scan for Super I/O sensors? (YES/no): ";
 
6097
                unless (<STDIN> =~ /^\s*n/i) {
 
6098
                        initialize_ioports();
 
6099
                        $superio_features |= scan_superio(0x2e, 0x2f);
 
6100
                        $superio_features |= scan_superio(0x4e, 0x4f);
 
6101
                        close_ioports();
 
6102
                }
 
6103
                print "\n";
 
6104
 
 
6105
                unless (is_laptop()) {
 
6106
                        print "Some systems (mainly servers) implement IPMI, a set of common interfaces\n".
 
6107
                              "through which system health data may be retrieved, amongst other things.\n".
 
6108
                              "We first try to get the information from SMBIOS. If we don't find it\n".
 
6109
                              "there, we have to read from arbitrary I/O ports to probe for such\n".
 
6110
                              "interfaces. This is normally safe. Do you want to scan for IPMI\n".
 
6111
                              "interfaces? (YES/no): ";
 
6112
                        unless (<STDIN> =~ /^\s*n/i) {
 
6113
                                if (!ipmi_from_smbios()) {
 
6114
                                        initialize_ioports();
 
6115
                                        scan_isa_bus(\@ipmi_ifs);
 
6116
                                        close_ioports();
 
6117
                                }
 
6118
                        }
 
6119
                        print "\n";
 
6120
                }
 
6121
 
 
6122
                printf "Some hardware monitoring chips are accessible through the ISA I/O ports.\n".
 
6123
                       "We have to write to arbitrary I/O ports to probe them. This is usually\n".
 
6124
                       "safe though. Yes, you do have ISA I/O ports even if you do not have any\n".
 
6125
                       "ISA slots! Do you want to scan the ISA I/O ports? (\%s): ",
 
6126
                       $superio_features ? "yes/NO" : "YES/no";
 
6127
                $input = <STDIN>;
 
6128
                unless ($input =~ /^\s*n/i
 
6129
                     || ($superio_features && $input !~ /^\s*y/i)) {
 
6130
                        initialize_ioports();
 
6131
                        scan_isa_bus(\@chip_ids);
 
6132
                        close_ioports();
 
6133
                }
 
6134
                print "\n";
 
6135
        }
 
6136
 
 
6137
        print "Lastly, we can probe the I2C/SMBus adapters for connected hardware\n".
 
6138
              "monitoring devices. This is the most risky part, and while it works\n".
 
6139
              "reasonably well on most systems, it has been reported to cause trouble\n".
 
6140
              "on some systems.\n".
 
6141
              "Do you want to probe the I2C/SMBus adapters now? (YES/no): ";
 
6142
 
 
6143
        unless (<STDIN> =~ /^\s*n/i) {
 
6144
                adapter_pci_detection();
 
6145
                load_module("i2c-dev") unless -e "$sysfs_root/class/i2c-dev";
 
6146
                initialize_i2c_adapters_list();
 
6147
                $i2c_addresses_to_scan = i2c_addresses_to_scan();
 
6148
                print "\n";
 
6149
 
 
6150
                # Skip SMBus probing by default if Super-I/O has all the features
 
6151
                my $by_default = ~$superio_features & (FEAT_IN | FEAT_FAN | FEAT_TEMP);
 
6152
                # Except on Asus and Tyan boards which often have more than
 
6153
                # one hardware monitoring chip
 
6154
                $by_default = 1 if dmi_match('board_vendor', 'asustek', 'tyan',
 
6155
                                             'supermicro');
 
6156
 
 
6157
                # udev may take some time to create the device node
 
6158
                if (!(-x "/sbin/udevadm" && system("/sbin/udevadm settle") == 0)
 
6159
                 && !(-x "/sbin/udevsettle" && system("/sbin/udevsettle") == 0)) {
 
6160
                        sleep(1);
 
6161
                }
 
6162
 
 
6163
                for (my $dev_nr = 0; $dev_nr < @i2c_adapters; $dev_nr++) {
 
6164
                        next unless exists $i2c_adapters[$dev_nr];
 
6165
                        scan_i2c_adapter($dev_nr, $by_default);
 
6166
                }
 
6167
                filter_out_fake_i2c_drivers();
 
6168
        }
 
6169
 
 
6170
        if (!keys %chips_detected) {
 
6171
                print "Sorry, no sensors were detected.\n";
 
6172
                if (is_laptop() && -d "$sysfs_root/firmware/acpi") {
 
6173
                        print "This is relatively common on laptops, where thermal management is\n".
 
6174
                              "handled by ACPI rather than the OS.\n";
 
6175
                } else {
 
6176
                        print "Either your system has no sensors, or they are not supported, or\n".
 
6177
                              "they are connected to an I2C or SMBus adapter that is not\n".
 
6178
                              "supported. If you find out what chips are on your board, check\n".
 
6179
                              "http://www.lm-sensors.org/wiki/Devices for driver status.\n";
 
6180
                }
 
6181
                exit;
 
6182
        }
 
6183
 
 
6184
        print "Now follows a summary of the probes I have just done.\n".
 
6185
              "Just press ENTER to continue: ";
 
6186
        <STDIN>;
 
6187
 
 
6188
        initialize_hwmon_autoloaded();
 
6189
        foreach my $driver (keys %chips_detected) {
 
6190
                next unless @{$chips_detected{$driver}};
 
6191
                find_aliases($chips_detected{$driver});
 
6192
                print "\nDriver `$driver'";
 
6193
                print " (autoloaded)" if hwmon_is_autoloaded($driver);
 
6194
                print ":\n";
 
6195
                print_chips_report($chips_detected{$driver});
 
6196
        }
 
6197
        print "\n";
 
6198
 
 
6199
        my ($configfile, $bus_modules, $hwmon_modules) = generate_modprobes();
 
6200
 
 
6201
        if (@{$hwmon_modules}) {
 
6202
                write_config($configfile, $bus_modules, $hwmon_modules);
 
6203
        } else {
 
6204
                print "No modules to load, skipping modules configuration.\n\n";
 
6205
        }
 
6206
 
 
6207
        unload_modules();
 
6208
}
 
6209
 
 
6210
sub cleanup_on_int
 
6211
{
 
6212
        print "\n";
 
6213
        unload_modules();
 
6214
        exit;
 
6215
}
 
6216
 
 
6217
$SIG{INT} = \&cleanup_on_int;
 
6218
 
 
6219
main;