root/lm-sensors/trunk/doc/design @ 12

Revision 12, 16.3 KB (checked in by frodo, 16 years ago)

isa module added, some bugfixes

'isa.o' is roughly what was called 'sensor.o' in doc/design.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1This is a design for version 2 of our smbus and lm_sensors module. This
2document is Copyright (c) 1998 by Frodo Looijaard. You may freely copy and
3distribute it, as long as you recognize me as the author, and mark any
4changes you make as being your own, and distribute this notice with it.
5
6Document version 1.0, 19981101.
7                 1.1, 19981111.
8                 1.2, 19981118.
9
10--> Never, ever change the driver struct with this technique!
11
12
13Object oriented approach
14========================
15
16The i2c module structs contain callback functions and data fields. In the
17i2c module, these structures are only referenced by pointers. This makes
18is easy to extend these structs to contain additional information or
19callback functions. For those familiar with object oriented languages,
20you can see the smbus structures as an object extension of the i2c
21structures, and the sensors structures are an extenstion of the smbus
22structures.
23
24To make this clearer, I will show in an example how this is done. Note
25that I have simplified some things here, so this example does not
26correspond to an actual struct found in one of the modules.
27
28In the i2c module, you can find a struct somewhat like this:
29
30struct i2c_adapter {
31  char name[32];
32  int (*detach_client) (struct i2c_client *);
33  struct i2c_adapter *next;
34}
35
36We have a plain data field (name), a call-back function which needs one
37parameter (a pointer to a i2c_client struct), and a data field which is
38a pointer to the next adapater.
39
40Now we want to extend this structure. We need another data field,
41containing a number of flags. We will call this new structure smbus_adapter.
42A few other things change too:
43
44struct smbus_adapter {
45  char name[32];
46  int (*detach_client) (struct smbus_client *);
47  struct smbus_adapter *next;
48  unsigned int flags;
49}
50
51So we copy all existing fields. The next field still points to the next
52adapter - but it is now of type smbus_adapter, not i2c_adapter. And the
53call-back function takes now a parameter of type pointer to smbus_client.
54And there is a new data field, called flags.
55
56Now examine this function definition:
57
58int fully_detach_i2c_client (struct i2c_client * client)
59{
60  res = 0;
61  struct i2c_adapter *current_adapter = first_adapter; /* a global var. */
62  while (current_adapter) {
63    res |= (current_adapter -> detach_client) (client);
64    current_adapter = current_adapter -> next;
65  }
66  return res;
67}
68
69This function detaches a client from all adapters. Nice. But now comes the
70Big Trick(tm): we can still use this function for smbus_adapters!
71
72int fully_detach_smbus_client (struct smbus_client * client)
73{
74  return fully_detach_i2c_client( (struct i2c_client *) client);
75}
76
77All we needed here was a simple typecast. Datapointers remain datapointers,
78so this can safely be done. And because we use call-back functions, the
79actual function called to detach a client from a single adapter might
80be the same, or different, depending on what function was put in
81client->detach_client!
82
83It gets even better. The i2c module stores internally all registered
84adapters. But it stores pointers to the i2c_adapter struct, not the
85structs themselves! So there is an array:
86
87#define I2C_ADAPTER_MAX 32
88struct i2c_adapter *adapters[I2C_ADAPTER_MAX];
89/* this is an array of pointers to structs, not vice versa! */
90
91So, an element of this array might in fact point to a smbus_adapter, instead
92of an i2c_adapter! If you know this for sure, you might use a typecast and
93access the additional fields. In the meantime, the i2c internal
94administration remains valid.
95
96We have to thank Simon Vogl and Gerd Knorr for the way they implemented
97their i2c module. Any other way would have made this approach impossible,
98and basing anything upon their module much more difficult.
99
100
101Module overview
102===============
103
104All in all, lots of modules will be stacked on each other. Too bad, but
105that is the only way to cleanly implement everything. Note that in a
106specific situation, only a few modules may need to be loaded. sensor.o,
107for example, does not depend on smbus.o (in the sense that you can load
108sensor.o without loading smbus.o). A specific bus driver, though, will
109depend on many of them.
110
111Generally:
112  sensor.o depends on nothing
113  smbus.o depends on nothing
114  i2c.o depends on nothing.
115
116  isa.o depends only on sensor.o
117  A non-i2c SMBus bus driver depends only on smbus.o
118  A i2c bus driver depends only on i2c.o
119
120  A sensor chip driver depends at least on sensor.o, and possibly on smbus.o
121  A SMBus chip driver depends only on smbus.o
122  A I2C chip driver depends only on i2c.o
123
124
125sensor.o
126Main sensors handling
127Unites SMBus adapters and ISA adapters.
128
129  isa.o
130  Implements the ISA adapter driver for sensor.o. This may prove to be so
131  closely integrated that it can better be made part of sensor.o
132 
133
134smbus.o
135Main SMBus handling
136Unites I2C adapters and SMBus hosts (like the PIIX4)
137Defines smbus_algorithm
138
139  piix4.o
140  SMBus adapter driver for the PIIX4 SMBus host.
141
142  ????.o
143  Adapter driver for another SMBus host
144
145
146i2c.o               
147Main i2c handling
148
149  ????.o
150  I2C adapter driver
151  Implementing a class of I2C busses
152
153
154A chip driver (typically defined in its own module) can be hooked on all
155these levels:
156  * If it is a sensor chip, it should be hooked to sensor.o
157  * An SMBus chip should be hooked to smbus.o
158  * An I2C chip should be hooked to i2c.o
159It can be difficult to decide whether a specific chip should be hoooked to
160smbus.o or i2c.o. A good deciding question is, 'could it be connected to
161a PIIX4?'
162
163
164Module i2c.o
165============
166
167This is Simon Vogl's i2c module (this one is different from the i2c module
168included in kernels around 1.2.120!).
169
170A driver
171--------
172
173struct i2c_driver {
174  char name[32];
175  int id;
176  unsigned int flags;
177  int (* attach_adapter) (struct i2c_adapter *);
178  int (* detach_client) (struct i2c_client *);
179  int (* command) (struct i2c_client *, unsigned int cmd, void *arg);
180  void (* inc_use) (struct i2c_client *);
181  void (* dec_use) (struct i2c_client *);
182}
183
184A driver tells us how we should handle a specific type of i2c chip. An
185instance of such a chip is called a 'client'. An example would be the LM75
186module: it would contain only one driver, which tells us how to handle the
187LM75; but each detected LM75 would be a separate client (which would be
188dynamically allocated).
189
190
191A description of the above struct:
192  name: The name of this driver
193  id: A unique driver identifier
194  flags: Flags to set certain kinds of behaviour (not used right now)
195  attach_adapter: A call-back function which is called if a new adapter (bus)
196    is found. This allows us to do our detection stuff on the new adapter,
197    and register new clients.
198  detach_client: A call-back function which is called if a specific client
199    which uses this driver should be disallocated. If a specific sensor module
200    is removed, for instance, this function would be called for each registered
201    client.
202  command: A generic call-back function to communicate in a driver-dependent
203    way with a specific client. This should only be seldom needed.
204  inc_use: Can be called to add one to an internal 'use' counter. This can be
205    used to control when it is safe to remove this module, for example.
206
207
208A client
209--------
210
211struct i2c_client {
212  char name[32];
213  int id;
214  unsigned int flags;
215  unsigned char addr;
216  struct i2c_adapter *adapter;
217  struct i2c_driver *driver;
218  void *data;
219}
220
221A client is a specific sensor chip. Its operation is controlled by a driver
222(which describes a type of sensor chip), and it is connected to an adapter
223(a bus).
224
225A description of the above struct:
226  name: The name of this client
227  id: A unique client id
228  flags: Flags to set certain kinds of behaviour (not very important)
229  addr: The client address. 10-bit addresses are a bit of a kludge right now.
230  adapter: A pointer to the adapter this client is on.
231  driver: A pointer to the driver this client uses.
232  data: Additional, client-dependent data
233
234
235An algorithm
236------------
237
238struct i2c_algorithm {
239  char name[32];
240  unsigned int id;
241  int (* master_xfer) (struct i2c_adapter *adap, struct i2c_msg msgs[],
242                       int num);
243  int (* slave_send) (struct i2c_adapter *,char *, int);
244  int (* slave_recv) (struct i2c_adapter *,char *, int);
245  int (* algo_control) (struct i2c_adapter *, unsigned int, unsigned long);
246  int (* client_register) (struct i2c_client *);
247  int (* client_unregister) (struct i2c_client *);
248}
249
250An algorithm describes how a certain class of i2c busses can be accessed.
251
252A description of the above struct:
253  name: The name of this algorithm
254  id: A unique algorithm id
255  master_xfer: Transfer a bunch of messages through a specific i2c bus.
256  slave_send: Send a message as if we are a slave device
257  slave_recv: Receive a message as if we are a slave device
258  client_register: Register a new client
259  client_unregister: Unregister a client
260
261
262An adapter
263----------
264
265struct i2c_adapter {
266  char name[32];
267  unsigned int id;
268  struct i2c_algorithm *algo;
269  void *data;
270#ifdef SPINLOCK
271  spinlock_t lock;
272  unsigned long lockflags;
273#else
274  struct semaphore lock;
275#endif
276  unsigned int flags;
277  struct i2c_client *clients[I2C_CLIENT_MAX];
278  int client_count;
279  int timeout;
280  int retries;
281}
282
283An adapter is a specific i2c bus. How to access it is defined in the
284algorithm associated with it.
285
286A description of the above struct:
287  name: The name of this adapter
288  id: A unique adapter id
289  algo: The algorithm through which this bus must be accessed
290  data: Adapter specific data
291  lock, lockflags: To lock out simultaneous adapter access
292  flags: Modifiers for adapter operation
293  clients: All currently connected clients
294  client_count: The number of currently connected clients
295  timeout, retries: Internal variables (unimportant here).
296
297
298Access functions
299----------------
300
301All these functions are defined extern.
302
303int i2c_master_send(struct i2c_client *,const char *, int);
304int i2c_master_recv(struct i2c_client *,char *, int);
305int i2c_transfer(struct i2c_adapter *,struct i2c_msg [], int num);
306
307These function respectively send one message to a client, receive one message
308from a client, or transmit a bunch of messages. struct i2c_msg contains
309an i2c address to communicate with, and can both read from and write to this
310address.
311
312
313int i2c_slave_send(struct i2c_client *, char *, int);
314int i2c_slave_recv(struct i2c_client *, char *, int);
315
316Communicate with another master as if the normal master is a common slave
317device.
318
319
320There are several other functions, to register things for example, that
321are less important to us.
322
323
324Module smbus.o
325==============
326
327This module offers support for SMBus operation. An SMBus adapter can either
328accept SMBus commands (like the PIIX4), or be in fact an I2C driver. In
329the last case, all SMBus commands will be expressed through I2C primitives.
330This means that any I2C adapter driver will automatically be a SMBus
331driver.
332
333At this point, it should be noted that there can only be one System
334Management Bus in a given system (is this really true, by the way?). This
335means there must be some way of selecting which of the many possible adapters
336is in fact *the* SMBus. For now, I will ignore this problem. Later on,
337we can add a hook somewhere in the i2c module to help us decide this.
338
339This module consists in fact of two separate parts: first of all, it extends
340all i2c structs to accomodate the new smbus fields. Second, it defines a
341new algorithm (smbus_algorithm), that will be used by all non-i2c adapters.
342
343
344A driver, client and algorithm
345------------------------------
346
347We will not need to extend i2c_driver, i2c_client or i2c_adapter. This means
348that struct smbus_driver is exactly the same as struct i2c_driver, and
349struct smbus_client is the same as struct i2c_client, and smbus_adapter is
350the same as struct i2c_adapter. We *will* define the smbus_* variants, and
351use them within this module, so it should be easy to extend them after all.
352
353Note that at this moment, 10 bit SMBus addresses seem to be only
354partially supported by the i2c module. We will ignore this issue for
355now.
356
357
358An adapter
359------------
360
361struct smbus_adapter {
362  char name[32];
363  unsigned int id;
364  struct smbus_algorithm *algo;
365  void *data;
366#ifdef SPINLOCK
367  spinlock_t lock;
368  unsigned long lockflags;
369#else
370  struct semaphore lock;
371#endif
372  unsigned int flags;
373  struct smbus_client *clients[I2C_CLIENT_MAX];
374  int client_count;
375  int timeout;
376  int retries;
377
378  /* Here ended i2c_algorithm */
379  s32 (* smbus_access) (__u8 addr, char read_write,
380                        __u8 command, int size, union smbus_data * data);
381}
382
383A description of the above struct:
384  smbus_access: A function to access the SMBus. It is only used for non-i2c
385      smbus adapters.
386
387
388Access functions
389----------------
390
391All these functions are defined extern.
392
393The i2c access function should not be used within SMBus chip drivers, as
394they might not be defined (for the PIIX4, for example). Instead, use the
395following general access function, or one of the easier functions based
396on it:
397
398int smbus_access (struct smbus_adapter *, __u8 addr, char read_write,
399                  __u8 command, int size, union smbus_data * data);
400
401There will be specific SMBus registration functions too, like the i2c
402ones.
403
404
405Module sensors.o
406================
407
408This module acts as a coordinations point between specific sensor modules
409(which each support a certain kind of sensor). We need this module to unite
410SMBus access and ISA access.
411
412
413A driver or adapter
414-------------------
415
416We will not need to extend smbus_driver or smbus_adapter. This means that
417struct sensor_driver is exactly the same as struct smbus_driver, and struct
418sensor_adapter is the same as struct smbus_adapter. We *will* define the
419sensor_* variants, and use them within this module, so it should be easy to
420extend them after all.
421
422Note that a driver can be for a chip on either the ISA bus or the
423I2C/SMBus. If a specific chip can be on both, you must check variable
424client->adapter->algorithm->on_isa to determine which bus you need to access.
425
426
427A client
428--------
429
430struct sensor_client {
431  char name[32];
432  int id;
433  unsigned int flags;
434  unsigned char addr;
435  struct sensor_adapter *adapter;
436  struct sensor_driver *driver;
437  void *data;
438
439  unsigned int full_address;
440}
441
442A client is a specific sensor chip. Its operation is controlled by a driver
443(which describes a type of sensor chip), and it is connected to an adapter
444(a bus, either a I2C/SMBus or the ISA bus).
445
446A description of the above struct:
447  full_address: The full client address. ISA addresses and 10-bit SMBus
448    addresses do not fit in the i2c-compatible addr field, so we needed
449    a new field.
450
451
452
453An algorithm
454------------
455
456struct sensor_algorithm {
457  char name[32];
458  unsigned int id;
459  int (* master_xfer) (struct sensor_adapter *adap, struct smbus_msg msgs[],
460                       int num);
461  int (* slave_send) (struct sensor_adapter *,char *, int);
462  int (* slave_recv) (struct sensor_adapter *,char *, int);
463  int (* algo_control) (struct sensor_adapter *, unsigned int, unsigned long);
464  int (* client_register) (struct sensor_client *);
465  int (* client_unregister) (struct sensor_client *);
466
467  int (* smbus_access) (struct sensor_adapter *, __u8 addr, char read_write,
468                        __u8 command, int size, union smbus_data * data);
469  int isa_bus;
470}
471
472A description of the above struct:
473  isa_bus: 0 if this structure describes SMBus access, 1 if it describes
474    ISA access.
475
476In case of the ISA bus, the master_xfer, slave_send, slave_recv and
477smbus_access hooks will be NULL, because these functions make no sense.
478It is regrettably not easy to create an access abstraction in which both
479ISA bus access and SMBus access are united. See below for examples how
480you can solve this problem.
481
482
483Access functions
484----------------
485
486All these functions are defined extern.
487
488The most imporant additional access function:
489
490  int is_on_isa (struct sensor_client *);
491
492This function tells us whether a specific client is connected to the ISA
493bus or to the SMBus. This is important, because it determines whether we
494can use the SMBus access routines.
495
496As an example, I will here implement our old LM78 access function:
497
498u8 lm78_read_value(struct sensor_client *client, u8 register)
499{
500  if (is_on_isa(client)) {
501    /* Ignore the check for LM78_BUSY to keep things simple here; the best
502       place to put this semaphore struct would be in client->data */
503    outb_p(register,client->address + LM78_ADDR_REG_OFFSET);
504    return inb_p(client->address + LM78_DATA_REG_OFFSET);
505  } else
506    return smbus_read_byte_data(client,register);
507    /* This is a standard function based on smbus_access */
508}
509
510
Note: See TracBrowser for help on using the browser.