mirror of
https://github.com/lm-sensors/lm-sensors.git
synced 2026-11-03 13:38:25 +00:00
Delete all kernel chip drivers, documentation and references. We are
moving to a user-space-only package, all the drivers are maintained in the Linux kernel tree itself. I tried to update the documentation a bit, but there's still a lot to go. In fact, a complete rewrite seems to be needed. git-svn-id: http://lm-sensors.org/svn/lm-sensors/branches/lm-sensors-3.0.0@4397 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
1 parent
448c4a70e9
commit
9232f4eb43
136 files changed
+1633
-55767
No files matched your search
@@ -1,550 +0,0 @@
|
||||
This is a design for version 2 of our smbus and lm_sensors module. This
|
||||
document is Copyright (c) 1998, 1999 by Frodo Looijaard. You may freely copy and
|
||||
distribute it, as long as you recognize me as the author, and mark any
|
||||
changes you make as being your own, and distribute this notice with it.
|
||||
|
||||
Document version 1.0, 19981101.
|
||||
1.1, 19981111.
|
||||
1.2, 19981118.
|
||||
1.3, 19981126.
|
||||
|
||||
NOTE: THIS IS BY NOW SOMEWHAT OUTDATED. SORRY.
|
||||
|
||||
|
||||
Object oriented approach
|
||||
========================
|
||||
|
||||
The i2c module structs contain callback functions and data fields. In the
|
||||
i2c module, these structures are only referenced by pointers. This makes
|
||||
it easy to extend these structs to contain additional information or
|
||||
callback functions. For those familiar with object oriented languages,
|
||||
you can see the smbus and isa structures as an object extension of the i2c
|
||||
structures.
|
||||
|
||||
To make this clearer, I will show in an example how this is done. Note
|
||||
that I have simplified some things here, so this example does not
|
||||
correspond to an actual struct found in one of the modules.
|
||||
|
||||
In the i2c module, you can find a struct somewhat like this:
|
||||
|
||||
struct i2c_adapter {
|
||||
char name[32];
|
||||
int (*detach_client) (struct i2c_client *);
|
||||
struct i2c_adapter *next;
|
||||
}
|
||||
|
||||
We have a plain data field (name), a call-back function which needs one
|
||||
parameter (a pointer to a i2c_client struct), and a data field which is
|
||||
a pointer to the next adapter.
|
||||
|
||||
Now we want to extend this structure. We need another data field,
|
||||
containing a number of flags. We will call this new structure smbus_adapter.
|
||||
A few other things change too:
|
||||
|
||||
struct smbus_adapter {
|
||||
char name[32];
|
||||
int (*detach_client) (struct smbus_client *);
|
||||
struct smbus_adapter *next;
|
||||
unsigned int flags;
|
||||
}
|
||||
|
||||
So we copy all existing fields. The next field still points to the next
|
||||
adapter - but it is now of type smbus_adapter, not i2c_adapter. And the
|
||||
call-back function takes now a parameter of type pointer to smbus_client.
|
||||
And there is a new data field, called flags.
|
||||
|
||||
Now examine this function definition:
|
||||
|
||||
int fully_detach_i2c_client (struct i2c_client * client)
|
||||
{
|
||||
res = 0;
|
||||
struct i2c_adapter *current_adapter = first_adapter; /* a global var. */
|
||||
while (current_adapter) {
|
||||
res |= (current_adapter -> detach_client) (client);
|
||||
current_adapter = current_adapter -> next;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
This function detaches a client from all adapters. Nice. But now comes the
|
||||
Big Trick(tm): we can still use this function for smbus_adapters!
|
||||
|
||||
int fully_detach_smbus_client (struct smbus_client * client)
|
||||
{
|
||||
return fully_detach_i2c_client( (struct i2c_client *) client);
|
||||
}
|
||||
|
||||
All we needed here was a simple typecast. Datapointers remain datapointers,
|
||||
so this can safely be done. And because we use call-back functions, the
|
||||
actual function called to detach a client from a single adapter might
|
||||
be the same, or different, depending on what function was put in
|
||||
client->detach_client!
|
||||
|
||||
It gets even better. The i2c module stores internally all registered
|
||||
adapters. But it stores pointers to the i2c_adapter struct, not the
|
||||
structs themselves! So there is an array:
|
||||
|
||||
#define I2C_ADAPTER_MAX 32
|
||||
struct i2c_adapter *adapters[I2C_ADAPTER_MAX];
|
||||
/* this is an array of pointers to structs, not vice versa! */
|
||||
|
||||
So, an element of this array might in fact point to a smbus_adapter, instead
|
||||
of an i2c_adapter! If you know this for sure, you might use a typecast and
|
||||
access the additional fields. In the meantime, the i2c internal
|
||||
administration remains valid.
|
||||
|
||||
We have to thank Simon Vogl and Gerd Knorr for the way they implemented
|
||||
their i2c module. Any other way would have made this approach impossible,
|
||||
and basing anything upon their module much more difficult.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
Extending the adapter and algorithm structures in this way is quite safe.
|
||||
They are only allocated on places where the code knows that they are
|
||||
'special'. Extending the driver or client structures depending on a
|
||||
specific adapter/algorithm type is *very* *dangerous*. A driver/client
|
||||
module would need to be aware of every special adapter/algorithm in
|
||||
order to allocate itself! For the ISA bus, it has to be aware of this
|
||||
anyway, so it is safe to do; on other places, think twice first!
|
||||
|
||||
|
||||
Module overview
|
||||
===============
|
||||
|
||||
All in all, lots of modules will be stacked on each other. Too bad, but
|
||||
that is the only way to cleanly implement everything. Note that in a
|
||||
specific situation, only a few modules may need to be loaded. isa.o,
|
||||
for example, does not depend on smbus.o (in the sense that you can load
|
||||
sensor.o without loading smbus.o). A specific bus driver, though, will
|
||||
depend on many of them.
|
||||
|
||||
Generally:
|
||||
isa.o depends on nothing (actually, on i2c.o, to keep the code small)
|
||||
smbus.o depends on nothing (actually, on i2c.o, to keep the code small)
|
||||
i2c.o depends on nothing.
|
||||
|
||||
A non-i2c SMBus bus driver depends only on smbus.o
|
||||
A i2c bus driver depends only on i2c.o
|
||||
|
||||
A sensor chip driver depends either on isa.o or smbus.o, or both.
|
||||
A SMBus chip driver depends only on smbus.o
|
||||
A I2C chip driver depends only on i2c.o
|
||||
|
||||
We may need a sensor.o module, to act as a central point for sensor
|
||||
modules. At this moment, it seems not really necessary, but this may
|
||||
change.
|
||||
|
||||
We will need an enhanced i2c-dev.o module, to add SMBus access to I2C
|
||||
/dev entries.
|
||||
|
||||
|
||||
isa.o
|
||||
ISA bus handling.
|
||||
Encapsulates ISA bus access within the i2c structures.
|
||||
Unites I2C adapters and the ISA bus.
|
||||
Defines variables isa_algorithm and isa_adapter.
|
||||
|
||||
smbus.o
|
||||
Main SMBus handling.
|
||||
Encapsulates SMBus access within the smbus structures.
|
||||
Unites I2C adapters and SMBus hosts (like the PIIX4).
|
||||
Emulates SMBus access on pure I2C adapters.
|
||||
Defines variable smbus_algorithm.
|
||||
|
||||
piix4.o
|
||||
SMBus adapter driver for the PIIX4 SMBus host.
|
||||
Defines variable piix4_adapter (based on smbus_algorithm).
|
||||
|
||||
FOO.o
|
||||
Adapter driver for FOO SMBus host
|
||||
Defines variable FOO_adapter (based on smbus_algorithm).
|
||||
|
||||
i2c-core.o (From Simon Vogl)
|
||||
Main i2c handling.
|
||||
|
||||
????.o
|
||||
I2C adapter driver
|
||||
Implementing a class of I2C busses
|
||||
|
||||
|
||||
A chip driver (typically defined in its own module) can be hooked on all
|
||||
these levels:
|
||||
* If it is a sensor chip, it should be hooked to isa.o or smbus.o
|
||||
* A pure ISA chip should be hooked to isa.o
|
||||
* A pure SMBus chip should be hooked to smbus.o
|
||||
* An I2C chip should be hooked to i2c.o
|
||||
It can be difficult to decide whether a specific chip should be hooked to
|
||||
smbus.o or i2c.o. A good deciding question is, 'could it be connected to
|
||||
a PIIX4?'
|
||||
|
||||
|
||||
Module i2c.o
|
||||
============
|
||||
|
||||
This is Simon Vogl's i2c module (this one is different from the i2c module
|
||||
included in kernels around 2.1.120!).
|
||||
|
||||
A driver
|
||||
--------
|
||||
|
||||
struct i2c_driver {
|
||||
char name[32];
|
||||
int id;
|
||||
unsigned int flags;
|
||||
int (* attach_adapter) (struct i2c_adapter *);
|
||||
int (* detach_client) (struct i2c_client *);
|
||||
int (* command) (struct i2c_client *, unsigned int cmd, void *arg);
|
||||
void (* inc_use) (struct i2c_client *);
|
||||
void (* dec_use) (struct i2c_client *);
|
||||
}
|
||||
|
||||
A driver tells us how we should handle a specific type of i2c chip. An
|
||||
instance of such a chip is called a 'client'. An example would be the LM75
|
||||
module: it would contain only one driver, which tells us how to handle the
|
||||
LM75; but each detected LM75 would be a separate client (which would be
|
||||
dynamically allocated).
|
||||
|
||||
|
||||
A description of the above struct:
|
||||
name: The name of this driver
|
||||
id: A unique driver identifier
|
||||
flags: Flags to set certain kinds of behaviour. Most notably, DF_NOTIFY
|
||||
will notify the driver when a new i2c bus is detected, so it can
|
||||
try to detect chips on it.
|
||||
attach_adapter: A call-back function which is called if a new adapter (bus)
|
||||
is found. This allows us to do our detection stuff on the new adapter,
|
||||
and register new clients.
|
||||
detach_client: A call-back function which is called if a specific client
|
||||
which uses this driver should be disallocated. If a specific sensor module
|
||||
is removed, for instance, this function would be called for each registered
|
||||
client.
|
||||
command: A generic call-back function to communicate in a driver-dependent
|
||||
way with a specific client. This should only be seldom needed.
|
||||
inc_use: Can be called to add one to an internal 'use' counter. This can be
|
||||
used to control when it is safe to remove this module, for example.
|
||||
|
||||
|
||||
A client
|
||||
--------
|
||||
|
||||
struct i2c_client {
|
||||
char name[32];
|
||||
int id;
|
||||
unsigned int flags;
|
||||
unsigned char addr;
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_driver *driver;
|
||||
void *data;
|
||||
}
|
||||
|
||||
A client is a specific sensor chip. Its operation is controlled by a driver
|
||||
(which describes a type of sensor chip), and it is connected to an adapter
|
||||
(a bus).
|
||||
|
||||
A description of the above struct:
|
||||
name: The name of this client
|
||||
id: A unique client id
|
||||
flags: Flags to set certain kinds of behaviour (not very important)
|
||||
addr: The client address. 10-bit addresses are a bit of a kludge right now.
|
||||
adapter: A pointer to the adapter this client is on.
|
||||
driver: A pointer to the driver this client uses.
|
||||
data: Additional, client-dependent data
|
||||
|
||||
|
||||
An algorithm
|
||||
------------
|
||||
|
||||
struct i2c_algorithm {
|
||||
char name[32];
|
||||
unsigned int id;
|
||||
int (* master_xfer) (struct i2c_adapter *adap, struct i2c_msg msgs[],
|
||||
int num);
|
||||
int (* slave_send) (struct i2c_adapter *,char *, int);
|
||||
int (* slave_recv) (struct i2c_adapter *,char *, int);
|
||||
int (* algo_control) (struct i2c_adapter *, unsigned int, unsigned long);
|
||||
int (* client_register) (struct i2c_client *);
|
||||
int (* client_unregister) (struct i2c_client *);
|
||||
}
|
||||
|
||||
An algorithm describes how a certain class of i2c busses can be accessed.
|
||||
|
||||
A description of the above struct:
|
||||
name: The name of this algorithm
|
||||
id: A unique algorithm id
|
||||
master_xfer: Transfer a bunch of messages through a specific i2c bus.
|
||||
slave_send: Send a message as if we are a slave device
|
||||
slave_recv: Receive a message as if we are a slave device
|
||||
client_register: Register a new client
|
||||
client_unregister: Unregister a client
|
||||
|
||||
|
||||
An adapter
|
||||
----------
|
||||
|
||||
struct i2c_adapter {
|
||||
char name[32];
|
||||
unsigned int id;
|
||||
struct i2c_algorithm *algo;
|
||||
void *data;
|
||||
#ifdef SPINLOCK
|
||||
spinlock_t lock;
|
||||
unsigned long lockflags;
|
||||
#else
|
||||
struct semaphore lock;
|
||||
#endif
|
||||
unsigned int flags;
|
||||
struct i2c_client *clients[I2C_CLIENT_MAX];
|
||||
int client_count;
|
||||
int timeout;
|
||||
int retries;
|
||||
}
|
||||
|
||||
An adapter is a specific i2c bus. How to access it is defined in the
|
||||
algorithm associated with it.
|
||||
|
||||
A description of the above struct:
|
||||
name: The name of this adapter
|
||||
id: A unique adapter id
|
||||
algo: The algorithm through which this bus must be accessed
|
||||
data: Adapter specific data
|
||||
lock, lockflags: To lock out simultaneous adapter access
|
||||
flags: Modifiers for adapter operation
|
||||
clients: All currently connected clients
|
||||
client_count: The number of currently connected clients
|
||||
timeout, retries: Internal variables (unimportant here).
|
||||
|
||||
|
||||
Access functions
|
||||
----------------
|
||||
|
||||
All these functions are defined extern.
|
||||
|
||||
int i2c_master_send(struct i2c_client *,const char *, int);
|
||||
int i2c_master_recv(struct i2c_client *,char *, int);
|
||||
int i2c_transfer(struct i2c_adapter *,struct i2c_msg [], int num);
|
||||
|
||||
These function respectively send one message to a client, receive one message
|
||||
from a client, or transmit a bunch of messages. struct i2c_msg contains
|
||||
an i2c address to communicate with, and can both read from and write to this
|
||||
address.
|
||||
|
||||
|
||||
int i2c_slave_send(struct i2c_client *, char *, int);
|
||||
int i2c_slave_recv(struct i2c_client *, char *, int);
|
||||
|
||||
Communicate with another master as if the normal master is a common slave
|
||||
device.
|
||||
|
||||
|
||||
Administration functions
|
||||
------------------------
|
||||
|
||||
int i2c_add_algorithm(struct i2c_algorithm *);
|
||||
int i2c_del_algorithm(struct i2c_algorithm *);
|
||||
|
||||
The i2c_{add,del}_algorithm functions must be called whenever a new module
|
||||
is inserted with this driver in it, by the module initialization function.
|
||||
|
||||
|
||||
int i2c_add_adapter(struct i2c_adapter *);
|
||||
int i2c_del_adapter(struct i2c_adapter *);
|
||||
|
||||
The i2c_{add,del}_adapter functions must be called if you have detected
|
||||
a specific bus. It triggers driver->attach_adapter (add, for each driver
|
||||
present) or driver->detach_client (del, for each registered client on
|
||||
this adapter).
|
||||
|
||||
|
||||
int i2c_add_driver(struct i2c_driver *);
|
||||
int i2c_del_driver(struct i2c_driver *);
|
||||
|
||||
The i2c_{add,del}_driver functions must be called whenever a new module is
|
||||
inserted with a chip driver in it, by the module initialization function.
|
||||
|
||||
|
||||
int i2c_attach_client(struct i2c_client *);
|
||||
int i2c_detach_client(struct i2c_client *);
|
||||
|
||||
The i2c_{attach,detach}_client functions must be called if you have detected
|
||||
a single chip.
|
||||
|
||||
|
||||
Module smbus.o
|
||||
==============
|
||||
|
||||
This module offers support for SMBus operation. An SMBus adapter can either
|
||||
accept SMBus commands (like the PIIX4), or be in fact an I2C driver. In
|
||||
the last case, all SMBus commands will be expressed through I2C primitives.
|
||||
This means that any I2C adapter driver will automatically be a SMBus
|
||||
driver.
|
||||
|
||||
At this point, it should be noted that there can only be one System
|
||||
Management Bus in a given system (is this really true, by the way?). This
|
||||
means there must be some way of selecting which of the many possible adapters
|
||||
is in fact *the* SMBus. For now, I will ignore this problem. Later on,
|
||||
we can add a hook somewhere in the i2c module to help us decide this.
|
||||
|
||||
This module consists in fact of three separate parts: first of all, it extends
|
||||
all i2c structs to accomodate the new smbus fields. Second, it defines a
|
||||
new algorithm (smbus_algorithm), that will be used by all non-i2c adapters.
|
||||
Finally, it implements a new access function that sends or receives SMBus
|
||||
commands; these are either translated into I2C commands or sent to the
|
||||
SMBus driver.
|
||||
|
||||
|
||||
A driver, client and algorithm
|
||||
------------------------------
|
||||
|
||||
We will not need to extend i2c_driver, i2c_client or i2c_adapter. This means
|
||||
that struct smbus_driver is exactly the same as struct i2c_driver, and
|
||||
struct smbus_client is the same as struct i2c_client, and smbus_adapter is
|
||||
the same as struct i2c_adapter. We *will* define the smbus_* variants, and
|
||||
use them within this module, so it should be easy to extend them after all.
|
||||
|
||||
Note that at this moment, 10 bit SMBus addresses seem to be only
|
||||
partially supported by the i2c module. We will ignore this issue for
|
||||
now.
|
||||
|
||||
|
||||
An adapter
|
||||
------------
|
||||
|
||||
struct smbus_adapter {
|
||||
char name[32];
|
||||
unsigned int id;
|
||||
struct smbus_algorithm *algo;
|
||||
void *data;
|
||||
#ifdef SPINLOCK
|
||||
spinlock_t lock;
|
||||
unsigned long lockflags;
|
||||
#else
|
||||
struct semaphore lock;
|
||||
#endif
|
||||
unsigned int flags;
|
||||
struct smbus_client *clients[I2C_CLIENT_MAX];
|
||||
int client_count;
|
||||
int timeout;
|
||||
int retries;
|
||||
|
||||
/* Here ended i2c_adapter */
|
||||
s32 (* smbus_access) (__u8 addr, char read_write,
|
||||
__u8 command, int size, union smbus_data * data);
|
||||
}
|
||||
|
||||
A description of the above struct:
|
||||
smbus_access: A function to access the SMBus. It is only used for non-i2c
|
||||
smbus adapters.
|
||||
|
||||
|
||||
Access functions
|
||||
----------------
|
||||
|
||||
All these functions are defined extern.
|
||||
|
||||
The i2c access function should not be used within SMBus chip drivers, as
|
||||
they might not be defined (for the PIIX4, for example). Instead, use the
|
||||
following general access function, or one of the easier functions based
|
||||
on it:
|
||||
|
||||
int smbus_access (struct i2c_adapter *, __u8 addr, char read_write,
|
||||
__u8 command, int size, union smbus_data * data);
|
||||
|
||||
There are specific SMBus registration functions too, like the i2c ones.
|
||||
They are fully compatiable with each other; just substitute 'smbus' for
|
||||
'i2c' everywhere in the i2c description.
|
||||
|
||||
int i2c_is_smbus_client(struct i2c_client *);
|
||||
int i2c_is_smbus_adapter(struct i2c_adapter *);
|
||||
|
||||
Decide whether this client, or adapter, is (on) a non-I2C SMBus. Usually
|
||||
not needed, but it is nice anyway to be able to decide this.
|
||||
|
||||
|
||||
Module isa.o
|
||||
============
|
||||
|
||||
This module implements a new algorithm and a specific adapter for the
|
||||
(single) ISA bus in your computer. This makes writing drivers for chips
|
||||
that can be both on ISA and SMBus much easier.
|
||||
|
||||
Note that this module does *not* in any way depend on smbus.o (previous
|
||||
versions of this document still assumed it would be build upon it; this
|
||||
is no longer true).
|
||||
|
||||
|
||||
A driver, adapter or algorithm
|
||||
------------------------------
|
||||
|
||||
We will not need to extend i2c_driver, i2c_adapter or i2c_algorithm. This
|
||||
means that struct isa_driver is exactly the same as struct i2c_driver,
|
||||
struct isa_adapter is the same as struct i2c_adapter and struct isa_algorithm
|
||||
is the same as struct isa_driver. We *will* define the isa_* variants, and
|
||||
use them within this module, so it should be easy to extend them after all.
|
||||
|
||||
|
||||
A client
|
||||
--------
|
||||
|
||||
struct isa_client {
|
||||
char name[32];
|
||||
int id;
|
||||
unsigned int flags;
|
||||
unsigned char addr;
|
||||
struct isa_adapter *adapter;
|
||||
struct isa_driver *driver;
|
||||
void *data;
|
||||
|
||||
unsigned int isa_addr;
|
||||
}
|
||||
|
||||
A client is a specific sensor chip. Its operation is controlled by a driver
|
||||
(which describes a type of sensor chip), and it is connected to an adapter
|
||||
(a bus, the (single) ISA bus here).
|
||||
|
||||
A description of the above struct:
|
||||
isa_addr: ISA addresses do not fit in the i2c-compatible addr field, so
|
||||
we needed a new field.
|
||||
|
||||
|
||||
Access functions
|
||||
----------------
|
||||
|
||||
All these functions are defined extern.
|
||||
|
||||
In case of the ISA bus, the master_xfer, slave_send and slave_recv hooks
|
||||
will be NULL, because these functions make no sense. It is regrettably
|
||||
not easy to create an access abstraction in which both ISA bus access
|
||||
and SMBus access are united. See below for examples how you can solve
|
||||
this problem.
|
||||
|
||||
The most imporant additional access function:
|
||||
|
||||
int i2c_is_isa_client(struct i2c_client *);
|
||||
int i2c_is_isa_adapter(struct i2c_adapter *);
|
||||
|
||||
Decide whether this client, or adapter, is (on) the ISA bus. This is
|
||||
important, because it determines whether we can use the SMBus access
|
||||
routines.
|
||||
|
||||
As an example, I will here implement our old LM78 access function:
|
||||
|
||||
/* The SMBus locks itself, but ISA access must be locked explicitly!
|
||||
We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
|
||||
would slow down the LM78 access and should not be necessary.
|
||||
There are some ugly typecasts here, but the good new is - they should
|
||||
nowhere else be necessary! */
|
||||
int lm78_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
int res;
|
||||
if (i2c_is_isa_client(client)) {
|
||||
down((struct semaphore *) (client->data));
|
||||
outb_p(reg,(((struct isa_client *) client)->isa_addr) +
|
||||
LM78_ADDR_REG_OFFSET);
|
||||
res = inb_p((((struct isa_client *) client)->isa_addr) +
|
||||
LM78_DATA_REG_OFFSET);
|
||||
up((struct semaphore *) (client->data));
|
||||
return res;
|
||||
} else
|
||||
return smbus_read_byte_data(client->adapter,client->addr, reg);
|
||||
}
|
||||
@@ -4,36 +4,28 @@ See doc/useful_addresses.html for a link to this article.
|
||||
|
||||
There is one big Makefile in the root of this package. It includes many
|
||||
other files; one for each directory in which source code is found. These
|
||||
included files are called 'Module.mk'. There is a separate set of Makefiles
|
||||
in the i2c/ directories; these are Simon Vogl's original Makefiles, and
|
||||
not referred by the main package Makefile.
|
||||
included files are called 'Module.mk'.
|
||||
|
||||
There are several interesting targets defined through this Makefile:
|
||||
* all
|
||||
Create everything in all directories.
|
||||
* all-i2c, all-src, ...
|
||||
Create everything in the designated directory.
|
||||
* install
|
||||
Install everything from all directories.
|
||||
* install-i2c, install-src, ...
|
||||
Install everything in the designated directory.
|
||||
* uninstall
|
||||
Uninstall everything.
|
||||
* clean
|
||||
Remove anything which can be regenerated from all directories. A call
|
||||
of 'make clean' (without any other targets) will ignore any .d files;
|
||||
this is useful when they are out of date (and prevent the calling of
|
||||
any other target).
|
||||
* clean-i2c, clean-src, ...
|
||||
Remove anything which can be regenerated from the designated directory.
|
||||
* version
|
||||
Regenerate version.h, using the current date for the date-stamp, and
|
||||
a user-supplied version number.
|
||||
* package
|
||||
Create a .tar.gz file containing everything except the SVN directories.
|
||||
* src/lm78.o, i2c/i2c-core.o, ...
|
||||
You can of course also specify one or more targets to make.
|
||||
|
||||
The best way to understand the Module.mk subfiles is to examine one of them,
|
||||
for example src/Module.mk. They are not too difficult to understand.
|
||||
for example lib/Module.mk. They are not too difficult to understand.
|
||||
|
||||
There are several variables which can be set in the main Makefile. You can
|
||||
also specify them on the command-line; this overrules any definitions
|
||||
@@ -47,16 +39,12 @@ ones for developers:
|
||||
only output more information, and never make the code mis-behave.
|
||||
|
||||
Several files are generated by Makefiles:
|
||||
* .d
|
||||
Dependency files for modules. Automatically generated.
|
||||
* .rd
|
||||
Dependency files for executables. Automatically generated.
|
||||
* .ao
|
||||
Dependency files for static libraries. Automatically generated.
|
||||
* .lo
|
||||
Dependency files for shared libraries. Automatically generated.
|
||||
* .o
|
||||
Generated modules
|
||||
* .ro
|
||||
Object files for executables. They will be linked together to create
|
||||
the executable. This extension is used to distinguish them from
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
These are the steps you should follow to write a new driver and
|
||||
submit it to us so that it will be applied cleanly to our package.
|
||||
See at the bottom for adding new chip support to an existing driver.
|
||||
|
||||
Don't be intimidated by the list, it's just here so we don't
|
||||
forget anything.
|
||||
We are more than happy to help you with any part of the process.
|
||||
|
||||
There are two types of drivers, chip and bus.
|
||||
Steps which apply to only one type of driver are noted.
|
||||
|
||||
These instructions are for 2.4-kernel-compatible drivers.
|
||||
If you wish to write a driver for 2.6 only, not all of the following
|
||||
steps apply.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
* Check our "New Drivers" page for status!!
|
||||
|
||||
* Contact us.
|
||||
You are of course free to write your own drivers, but it is smart to
|
||||
check first nobody else is already working on it, in case the
|
||||
New Drivers page is out of date.
|
||||
Tell us it's OK to put your name on the "New Drivers" page.
|
||||
|
||||
* Consider subscribing to the mailing list.
|
||||
|
||||
* Check out our latest code from SVN.
|
||||
You should use this as a base for your development.
|
||||
See instructions on our download page.
|
||||
|
||||
* Write the new driver.
|
||||
If you write a driver for a device that is similar to one we already
|
||||
support, use the other device driver as a template. If you don't know
|
||||
which one to use, either ask us or use the following defaults.
|
||||
For a chip driver, use lm78.c as template. For an SMBus-only adapter,
|
||||
use i2c-piix4.c. Use i2c-via.c for an I2C-level adapter ('bit banger').
|
||||
Usually, we make all prefixes start with the driver name. This is not
|
||||
really necessary, as these symbols will not be exported anyway. But by
|
||||
doing this, you are sure you do not shadow any global kernel names.
|
||||
|
||||
* A quick note about conversions. The conversions which are specified
|
||||
in the sensor chip datasheet and which *cannot* vary from one board to
|
||||
the next are performed by the driver. If other conversions are
|
||||
necessary, they are performed in user-space.
|
||||
|
||||
* Meet Kernel coding standards.
|
||||
See Documentation/CodingStyle in the kernel source.
|
||||
Be sure and use 8 column tabs.
|
||||
Also, please do not use // comments.
|
||||
Also, please do not go past column 80.
|
||||
Also, please use C99 struct initializers {.foo = blat}
|
||||
Please do this _before_ you check in your driver.
|
||||
|
||||
* Meet /proc naming standards in the ctl_table (for chip drivers only).
|
||||
See doc/developers/proc for information. Please do not deviate from
|
||||
this without discussion.
|
||||
|
||||
* Add the driver to the Module.mk (the makefile).
|
||||
Usually, you can just add it to KERNEL{CHIPS,DRIVERS}TARGETS in the
|
||||
Module.mk file in the directory itself.
|
||||
|
||||
* Make sure it compiles cleanly.
|
||||
Check compilation with 'make DEBUG=1' if you use debugging
|
||||
information. Remember, things put between #ifdef DEBUG #endif may never
|
||||
stop the driver from functioning; they should just output additional
|
||||
information.
|
||||
|
||||
* Check for external symbols.
|
||||
'nm --extern --defined' should only output symbols starting with __module,
|
||||
cleanup_module, init_module and some kernel versioning symbols. Mark all
|
||||
other symbols as static in your source file.
|
||||
|
||||
* Test the module.
|
||||
Test with a recent 2.4 kernel.
|
||||
For bus drivers, use i2cdetect and i2cdump. For i2cdump, test all supported
|
||||
bus access modes (see i2cdump man page).
|
||||
For chip drivers, cat all files in applicable /proc or /sys directory
|
||||
and check for problems. Write all supported settings.
|
||||
Check ALARM indications.
|
||||
|
||||
* Add detection information to prog/detect/sensors-detect.
|
||||
This is a perl script that automatically detects what chips and adapters
|
||||
are present. Contact us if you need help.
|
||||
|
||||
* Add chip information to lib/chips.{c,h} (for chip drivers only).
|
||||
Until you have done this, the chip will be invisible for user-level
|
||||
programs which use libsensors. Use standard names in lib/chips.c;
|
||||
see also the comments in etc/sensors.conf.eg for help.
|
||||
Contact us if you need more assistance.
|
||||
|
||||
* Be sure that SYSCTL and ALARM definitions in the driver are bracketed
|
||||
by the special comments so that the kernel/include/sensors.h
|
||||
file, which is generated automatically, contains your definitions.
|
||||
(for chip drivers only)
|
||||
|
||||
* Add a procedure to prog/sensors/chips.[ch] (for chip drivers only).
|
||||
This is a function specific for your driver that
|
||||
makes the included 'sensors' program pretty-print your chip information.
|
||||
|
||||
* Add an line for the procedure in the matches[] table in
|
||||
prog/sensors/main.c (for chip drivers only).
|
||||
This tells sensors to call your new procedure when the chip name matches.
|
||||
|
||||
* Add entries to etc/sensors.conf.eg (for chip drivers only).
|
||||
If needed, you can set defaults here.
|
||||
|
||||
* Test the userspace apps (sensors-detect and sensors).
|
||||
Test setting limits with sensors -s.
|
||||
|
||||
* Add the name of the device to the README file.
|
||||
|
||||
* Add your name to the CONTRIBUTORS file.
|
||||
|
||||
* Add entries to the CHANGES file. Please keep in alphabetical order.
|
||||
|
||||
* Write a doc/chips/xxx or doc/busses/xxx file.
|
||||
|
||||
* Add entry to doc/chips/SUMMARY (for chip drivers only).
|
||||
|
||||
* Clearly specify licensing and copyright.
|
||||
Make sure the GPL boilerplate and your name
|
||||
(or if applicable your company's name) is at the top of the
|
||||
new driver so we know you are giving it to us under the GPL.
|
||||
|
||||
* Submit the changes to us.
|
||||
Do a 'svn update' to get in sync (things will have changed since
|
||||
you started), then submit the changes to us as a patch against SVN.
|
||||
|
||||
* If you want to have your driver integrated to Linux 2.6, you have to
|
||||
port your driver to the new sysfs interface. Once done and preferably
|
||||
after testing, submit a patch to our mailing list: see
|
||||
http://www.lm-sensors.org/wiki/AuthorsAndContributors
|
||||
Make sure to check the current status for your driver first:
|
||||
http://www.lm-sensors.org/wiki/Kernel2.6
|
||||
http://www.lm-sensors.org/wiki/Devices
|
||||
|
||||
---------------------------------------------------------------------
|
||||
Checklist for us to do on the webpage:
|
||||
|
||||
* Add entry to 'supported drivers' page
|
||||
|
||||
* Update entry on 'new drivers' page
|
||||
|
||||
---------------------------------------------------------------------
|
||||
Checklist for _adding_ support for a chip to an _existing_ driver:
|
||||
|
||||
* Make the changes to the driver itself.
|
||||
|
||||
* Add detection information to prog/detect/sensors-detect.
|
||||
|
||||
* Add a strncmp() call for the new prefix in prog/sensors/main.c
|
||||
(chip drivers only).
|
||||
|
||||
* Add entries for the new prefix to etc/sensors.conf.eg (chip drivers only).
|
||||
|
||||
* Update doc/[chips,busses]/xxx file
|
||||
|
||||
* Update doc/chips/SUMMARY file (chip drivers only)
|
||||
|
||||
* Update list in README
|
||||
|
||||
* Submit the changes as a patch or check them in
|
||||
|
||||
* Update entry on 'new drivers' page
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
Naming and data format standards under /proc
|
||||
--------------------------------------------
|
||||
|
||||
The libsensors library offers an interface to the raw sensors data
|
||||
through the sysctl interface. See the doc/developers/sysctl
|
||||
and the libsensors source for further information.
|
||||
|
||||
An alternative method that some programs use is to access the /proc
|
||||
files directly. This document briefly describes the standards that
|
||||
the drivers follow, so that an application program can scan for
|
||||
entries and access this data in a simple and consistent way.
|
||||
|
||||
Note that not all chip drivers adhere to this standard.
|
||||
We will attempt to migrate older drivers to this standard,
|
||||
and ensure that new drivers follow this standard wherever possible.
|
||||
If you are developing a userspace application please send us
|
||||
feedback on this standard.
|
||||
|
||||
Note that motherboards vary widely in the connections to sensor chips.
|
||||
There is no standard that ensures, for example, that the second
|
||||
temperature sensor is connected to the CPU, or that the second
|
||||
fan is on the CPU. Therefore, programs must provide a facility
|
||||
for the user to label or bind /proc entries for display.
|
||||
Sensor chips often have unused inputs that should be ignored
|
||||
by user programs.
|
||||
|
||||
Each chip gets its own directory under /proc/sys/dev/sensors.
|
||||
The format is either chip-i2c-bus-hexaddress or chip-isa-hexaddress.
|
||||
(Exception - chip lm78-j has a '-' in it - should this be changed??)
|
||||
New dummy drivers may present chips as chip-busname-hexaddress.
|
||||
|
||||
All /proc values are integers or floating point numbers.
|
||||
There is no facility in the lm_sensors package for drivers
|
||||
to output general strings via /proc. This facility may be added
|
||||
in the future.
|
||||
|
||||
Alarms are direct indications read from the chips. The drivers do NOT make
|
||||
comparisons of readings to thresholds. This allows violations
|
||||
between readings to be caught and alarmed. The exact definition of
|
||||
an alarm (for example, whether a threshold must be met or must be
|
||||
exceeded to cause an alarm) is chip-dependent.
|
||||
|
||||
Guidelines for new entries:
|
||||
- If there are multiple values, some r/w and some r/o,
|
||||
put the r/w ones first.
|
||||
- Additional non-standard values should be after the standard values.
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
/proc entries are as follows:
|
||||
|
||||
|
||||
Entry Values Function
|
||||
----- ------ --------
|
||||
alarms 1 Alarm bitmask.
|
||||
Read only.
|
||||
Integer representation of one to four bytes.
|
||||
A '1' bit means an alarm.
|
||||
Chips should be programmed for 'comparator' mode so that
|
||||
the alarm will 'come back' after you read the register
|
||||
if it is still valid.
|
||||
Generally a direct representation of a chip's internal
|
||||
alarm registers; there is no standard for the position
|
||||
of individual bits.
|
||||
Bits are defined in kernel/include/sensors.h.
|
||||
|
||||
beep 2 Beep/interrupt enable and bitmask.
|
||||
The first value is 0 or 1 to globally disable
|
||||
or enable the beeps.
|
||||
The second value is a bitmask, with the
|
||||
same format as 'alarms' with same bit locations.
|
||||
|
||||
curr[1-n] 3 Current max, min or hysteresis, and input value.
|
||||
Floating point values XX.X or XX.XX in Amps.
|
||||
The second value is preferably a hysteresis value,
|
||||
reported as a absolute current, NOT a delta from
|
||||
the max value.
|
||||
First two values are read/write and third is read only.
|
||||
|
||||
fan[1-3] 2 Fan minimum and input value.
|
||||
Two integers indicating RPM.
|
||||
First value is read/write and second is read only.
|
||||
|
||||
fan_div 3 Fan divisor.
|
||||
Integers in powers of two (1,2,4,8,16,32,64,128).
|
||||
Some chips only support values 1,2,4,8.
|
||||
Entries correspond to the fans[1-3].
|
||||
See doc/fan-divisors for details.
|
||||
|
||||
in[0-8] 3 Voltage min, max, and input value.
|
||||
Floating point values X.XX in volts from 0 to 4.01 volts.
|
||||
Actual voltage depends on the scaling resistors on the
|
||||
motherboard, as recommended in the chip datasheet.
|
||||
This varies by chip and by motherboard.
|
||||
Because of this variation, values are generally NOT scaled
|
||||
by the chip driver, and must be done by the application.
|
||||
However, some drivers (notably lm87 and via686a)
|
||||
do scale, with various degrees of success.
|
||||
These drivers will output the actual voltage.
|
||||
First two values are read/write and third is read only.
|
||||
Typical usage:
|
||||
in0 CPU #1 voltage (not scaled)
|
||||
in1 CPU #1 voltage (not scaled)
|
||||
in2 3.3V nominal (not scaled)
|
||||
in3 5.0V nominal (scaled)
|
||||
in4 12.0V nominal (scaled)
|
||||
in5 -12.0V nominal (scaled)
|
||||
in6 -5.0V nominal (scaled)
|
||||
in7 varies
|
||||
in8 varies
|
||||
|
||||
pwm[1-3] 1-2 Pulse width modulation fan control.
|
||||
Integer 0 - 255, read/write.
|
||||
255 is max or 100%.
|
||||
Corresponds to the fans 1-3.
|
||||
Second value, if present, is an enable (0 or 1)
|
||||
|
||||
sensor[1-3] 1 Sensor type selection.
|
||||
Integers 1,2,3, or thermistor Beta value (3435); read/write.
|
||||
|
||||
temp,
|
||||
temp[1-4] 3 Temperature max, min or hysteresis, and input value.
|
||||
Floating point values XXX.X or XXX.XX in degrees Celsius.
|
||||
'temp' is used if there is only one temperature sensor on the
|
||||
chip; for multiple temps. start with 'temp1'.
|
||||
Temp1 is generally the sensor inside the chip itself,
|
||||
generally reported as "motherboard temperature".
|
||||
Temp2 to temp4 are generally sensors external to the chip
|
||||
itself, for example the thermal diode inside the CPU or a
|
||||
termistor nearby. The second value is preferably a hysteresis
|
||||
value, reported as a absolute temperature, NOT a delta from
|
||||
the max value.
|
||||
First two values are read/write and third is read only.
|
||||
|
||||
vid 1 CPU core voltage.
|
||||
Read only.
|
||||
Floating point X.XX or X.XXX corresponding to CPU core voltage
|
||||
as told to the sensor chip. Not always correct.
|
||||
|
||||
vrm 1 Voltage Regulator Module version number.
|
||||
"Floating point" X.X. Default 8.2.
|
||||
Affects the way the driver calculates the core voltage from
|
||||
the vid pins. See doc/vid for details.
|
||||
@@ -2,18 +2,16 @@ CHECKLIST FOR NEW RELEASES
|
||||
==========================
|
||||
|
||||
Release steps:
|
||||
- Check out i2c and lm-sensors
|
||||
- Check out lm-sensors
|
||||
- Update if necessary, the version number of libsensors
|
||||
(edit lib/Module.mk and change LIBMAINVER and/or LIBMINORVER)
|
||||
Remember: update main number when interface changes, minor if new
|
||||
functionality is added, and patch if only bugs are fixed.
|
||||
`svn diff -r Vx-y-z lib' is your friend.
|
||||
- Update both CHANGES files (add the release date)
|
||||
- Verify i2c dependency instructions in README, QUICKSTART, and INSTALL,
|
||||
update if necessary
|
||||
- Update the CHANGES file (add the release date)
|
||||
- Update lm_sensors.lsm and send it to the LSM by mailing it to
|
||||
lsm@execpc.com with the subject `add' (no quotes).
|
||||
- Update lm_sensors2/version.h and i2c/kernel/i2c.h
|
||||
- Update version.h
|
||||
- Commit
|
||||
- Tag the release using SVN:
|
||||
svn copy http://lm-sensors.org/svn/lm-sensors/trunk \
|
||||
@@ -21,9 +19,9 @@ Release steps:
|
||||
-m "Create tag 'V2-x-x'."
|
||||
- Remove empty directories (e.g. rmdir `find . -type d`)
|
||||
- Remove 'SVN' related files/directories (e.g. rm -fR `find . -name .svn`)
|
||||
- Rename i2c and lm_sensors2 to i2c-#.#.# and lm_sensors-#.#.#
|
||||
- Rename lm_sensors2 to lm_sensors-#.#.#
|
||||
- Tar it up and post it (sign it)
|
||||
- Make sure the file permissions on both the archives and the signatures
|
||||
- Make sure the file permissions on both the archive and the signature
|
||||
are correct (664)
|
||||
|
||||
After release, remember to:
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
You can access everything under /proc/sys through the sysctl interface. This
|
||||
is mostly useful for C programs, which can use the sysctl function. Try
|
||||
'man 2 sysctl' for more information.
|
||||
|
||||
As each chip gets its own directory under /proc/sys/dev/sensors, you must
|
||||
somehow know the sysctl id of these directories to access the sensor data.
|
||||
This is done through the file /proc/sys/dev/sensors/chips (see sensors.h
|
||||
for the corresponding SYSCTL ids). You can only read this file; it
|
||||
returns an array of struct sensors_chips_data, as defined in sensors.h.
|
||||
Each chip will have its own entry here, with both its sysctl id and
|
||||
the corresponding /proc name.
|
||||
|
||||
Generally, it is a better idea to use the new libsensors to access this
|
||||
data. If you feel you need more than the library offers, please mail us,
|
||||
so we can either add the new functionality to the library, or explain how
|
||||
you can work around it.
|
||||
Reference in new issue
Block a user