From 45d6e40e75f77ea818f6fc4fb7bd2fe12cb02a24 Mon Sep 17 00:00:00 2001 From: Frodo Looijaard Date: Thu, 26 Nov 1998 10:16:08 +0000 Subject: [PATCH] Example lm_sensors-2 driver Though it is called the LM78 driver, there is not too much LM78 specific code in it; it can better be seen as an example code skeleton for other drivers. Right now, it creats a file /proc/sensors-test, which contains a list of busses it registered itself on. Stupid, but very useful for testing purposes! You need a 2.0 kernel for lm78.o to insert (or hack the /proc system specific parts; see lm78.c of lm_sensors version 1 how to do this). Other parts of lm_sensors-2 are not tested for 2.1 kernels either, but I am certain it won't work in this case :-). See the TODO list to get some idea what is left to do, choose something and implement it. Or not :-). But please, send a note to the mailing list when you start on something, to avoid duplicate work... Other notable changes: the smbus_access routines now use (the more logical) i2c_adapter structure, instead of smbus_adapter. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@13 7894878c-1315-0410-8ee3-d5d059ff63e0 --- TODO | 17 ++++++++++++++--- kernel/Module.mk | 3 ++- kernel/busses/i2c-piix4.c | 6 +++--- kernel/include/i2c-isa.h | 4 +++- kernel/include/isa.h | 4 +++- kernel/include/smbus.h | 28 ++++++++++++++++------------ kernel/smbus.c | 9 +++++---- src/Module.mk | 3 ++- src/isa.h | 4 +++- src/piix4.c | 6 +++--- src/smbus.c | 9 +++++---- src/smbus.h | 28 ++++++++++++++++------------ 12 files changed, 75 insertions(+), 46 deletions(-) diff --git a/TODO b/TODO index d1ca723d..2f73893b 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,16 @@ Many, many things. Most notably: -* Write s32 smbus_access_i2c in smbus.c -* Check out whether we can use the dev interface for smbus (like i2c) -* Write all other modules +* Write smbus_access_i2c in smbus.c +* Write piix4_* in piix4.c +* Complete lm78 driver +* Extend dev interface for SMBus +* Create entries in /proc/bus: a list of all registered busses, and for + each bus, a file with registered clients. +* Write all other drivers +* How to make drivers detect thing *not*; for example, if a Winbond is + present, the LM75 driver should not try to access its simulated + LM75 chips! +* Write a userland-library for SMBus/i2c access (through the /dev interface) +* Write a userland detection program for busses (clients are less important; + but perhaps needed too). +* Bring doc/design up-to-date (it is horribly out of date right now) diff --git a/kernel/Module.mk b/kernel/Module.mk index a70b8304..bc0bf97d 100644 --- a/kernel/Module.mk +++ b/kernel/Module.mk @@ -22,7 +22,8 @@ MODULE_DIR := src # Regrettably, even 'simply expanded variables' will not put their currently # defined value verbatim into the command-list of rules... -SRCTARGETS := $(MODULE_DIR)/smbus.o $(MODULE_DIR)/piix4.o $(MODULE_DIR)/isa.o +SRCTARGETS := $(MODULE_DIR)/smbus.o $(MODULE_DIR)/piix4.o $(MODULE_DIR)/isa.o \ + $(MODULE_DIR)/lm78.o # Include all dependency files INCLUDEFILES += $(SRCTARGETS:.o=.d) diff --git a/kernel/busses/i2c-piix4.c b/kernel/busses/i2c-piix4.c index c06f5a5f..52bcd0b4 100644 --- a/kernel/busses/i2c-piix4.c +++ b/kernel/busses/i2c-piix4.c @@ -49,6 +49,7 @@ s32 piix4_access(u8 addr, char read_write, u8 command, int size, union smbus_data * data) { /* TO BE WRITTEN! */ + return -1; } @@ -89,10 +90,9 @@ int piix4_cleanup(void) if (piix4_initialized >= 2) { if ((res = smbus_del_adapter(&piix4_adapter))) { - printk("piix4.o: smbus_del_adapter failed, module not removed"); + printk("piix4.o: smbus_del_adapter failed, module not removed\n"); return res; - } - else + } else piix4_initialized--; } if (piix4_initialized >= 1) { diff --git a/kernel/include/i2c-isa.h b/kernel/include/i2c-isa.h index d5ad471d..9c738b67 100644 --- a/kernel/include/i2c-isa.h +++ b/kernel/include/i2c-isa.h @@ -77,7 +77,7 @@ struct isa_client { void *data; /* Here ended i2c_client */ - unsigned int full_address; + unsigned int isa_addr; }; /* An algorithm describes how a certain class of busses can be accessed. @@ -127,6 +127,8 @@ struct isa_adapter { access will fail! */ #define i2c_is_isa_client(clientptr) \ ((clientptr)->adapter->algo->id == ALGO_ISA) +#define i2c_is_isa_adapter(adapptr) \ + ((adapptr)->algo->id == ALGO_ISA) /* Next: define ISA variants of registering. */ #define isa_add_algorithm(algoptr) \ diff --git a/kernel/include/isa.h b/kernel/include/isa.h index d5ad471d..9c738b67 100644 --- a/kernel/include/isa.h +++ b/kernel/include/isa.h @@ -77,7 +77,7 @@ struct isa_client { void *data; /* Here ended i2c_client */ - unsigned int full_address; + unsigned int isa_addr; }; /* An algorithm describes how a certain class of busses can be accessed. @@ -127,6 +127,8 @@ struct isa_adapter { access will fail! */ #define i2c_is_isa_client(clientptr) \ ((clientptr)->adapter->algo->id == ALGO_ISA) +#define i2c_is_isa_adapter(adapptr) \ + ((adapptr)->algo->id == ALGO_ISA) /* Next: define ISA variants of registering. */ #define isa_add_algorithm(algoptr) \ diff --git a/kernel/include/smbus.h b/kernel/include/smbus.h index 68a27d02..6227867d 100644 --- a/kernel/include/smbus.h +++ b/kernel/include/smbus.h @@ -130,6 +130,8 @@ struct smbus_adapter { course. */ #define i2c_is_smbus_client(clientptr) \ ((clientptr)->adapter->algo->id == ALGO_SMBUS) +#define i2c_is_smbus_adapter(adapptr) \ + ((adapptr)->algo->id == ALGO_SMBUS) /* This union is used within smbus_access routines */ union smbus_data { @@ -157,21 +159,23 @@ extern struct smbus_algorithm smbus_algorithm; /* This is the very generalized SMBus access routine. You probably do not want to use this, though; one of the functions below may be much easier, - and probably just as fast. */ -extern s32 smbus_access (struct smbus_adapter * adapter, u8 addr, + and probably just as fast. + Note that we use i2c_adapter here, because you do not need a specific + smbus adapter to call this function. */ +extern s32 smbus_access (struct i2c_adapter * adapter, u8 addr, char read_write, u8 command, int size, union smbus_data * data); /* Now follow the 'nice' access routines. These also document the calling conventions of smbus_access. */ -extern inline s32 smbus_write_quick(struct smbus_adapter * adapter, u8 addr, +extern inline s32 smbus_write_quick(struct i2c_adapter * adapter, u8 addr, u8 value) { return smbus_access(adapter,addr,value,0,SMBUS_QUICK,NULL); } -extern inline s32 smbus_read_byte(struct smbus_adapter * adapter,u8 addr) +extern inline s32 smbus_read_byte(struct i2c_adapter * adapter,u8 addr) { union smbus_data data; if (smbus_access(adapter,addr,SMBUS_READ,0,SMBUS_BYTE,&data)) @@ -180,13 +184,13 @@ extern inline s32 smbus_read_byte(struct smbus_adapter * adapter,u8 addr) return data.byte; } -extern inline s32 smbus_write_byte(struct smbus_adapter * adapter, u8 addr, +extern inline s32 smbus_write_byte(struct i2c_adapter * adapter, u8 addr, u8 value) { return smbus_access(adapter,addr,SMBUS_WRITE,value, SMBUS_BYTE,NULL); } -extern inline s32 smbus_read_byte_data(struct smbus_adapter * adapter, +extern inline s32 smbus_read_byte_data(struct i2c_adapter * adapter, u8 addr, u8 command) { union smbus_data data; @@ -196,7 +200,7 @@ extern inline s32 smbus_read_byte_data(struct smbus_adapter * adapter, return data.byte; } -extern inline s32 smbus_write_byte_data(struct smbus_adapter * adapter, +extern inline s32 smbus_write_byte_data(struct i2c_adapter * adapter, u8 addr, u8 command, u8 value) { union smbus_data data; @@ -204,7 +208,7 @@ extern inline s32 smbus_write_byte_data(struct smbus_adapter * adapter, return smbus_access(adapter,addr,SMBUS_WRITE,command,SMBUS_BYTE_DATA,&data); } -extern inline s32 smbus_read_word_data(struct smbus_adapter * adapter, +extern inline s32 smbus_read_word_data(struct i2c_adapter * adapter, u8 addr, u8 command) { union smbus_data data; @@ -214,7 +218,7 @@ extern inline s32 smbus_read_word_data(struct smbus_adapter * adapter, return data.word; } -extern inline s32 smbus_write_word_data(struct smbus_adapter * adapter, +extern inline s32 smbus_write_word_data(struct i2c_adapter * adapter, u8 addr, u8 command, u16 value) { union smbus_data data; @@ -222,7 +226,7 @@ extern inline s32 smbus_write_word_data(struct smbus_adapter * adapter, return smbus_access(adapter,addr,SMBUS_WRITE,command,SMBUS_WORD_DATA,&data); } -extern inline s32 smbus_process_call(struct smbus_adapter * adapter, +extern inline s32 smbus_process_call(struct i2c_adapter * adapter, u8 addr, u8 command, u16 value) { union smbus_data data; @@ -234,7 +238,7 @@ extern inline s32 smbus_process_call(struct smbus_adapter * adapter, } /* Returns the number of read bytes */ -extern inline s32 smbus_read_block_data(struct smbus_adapter * adapter, +extern inline s32 smbus_read_block_data(struct i2c_adapter * adapter, u8 addr, u8 command, u8 *values) { union smbus_data data; @@ -248,7 +252,7 @@ extern inline s32 smbus_read_block_data(struct smbus_adapter * adapter, } } -extern inline int smbus_write_block_data(struct smbus_adapter * adapter, +extern inline int smbus_write_block_data(struct i2c_adapter * adapter, u8 addr, u8 command, u8 length, u8 *values) { diff --git a/kernel/smbus.c b/kernel/smbus.c index 9b66e448..8494caf1 100644 --- a/kernel/smbus.c +++ b/kernel/smbus.c @@ -30,7 +30,7 @@ #include "version.h" #include "smbus.h" -static s32 smbus_access_i2c (struct smbus_adapter * adapter, u8 addr, +static s32 smbus_access_i2c (struct i2c_adapter * adapter, u8 addr, char read_write, u8 command, int size, union smbus_data * data); @@ -69,7 +69,7 @@ struct smbus_algorithm smbus_algorithm = { simulate the SMBus commands using the i2c access routines. We do all locking here, so you can ignore that in the adapter-specific smbus_accesss routine. */ -s32 smbus_access (struct smbus_adapter * adapter, u8 addr, char read_write, +s32 smbus_access (struct i2c_adapter * adapter, u8 addr, char read_write, u8 command, int size, union smbus_data * data) { int res; @@ -79,7 +79,8 @@ s32 smbus_access (struct smbus_adapter * adapter, u8 addr, char read_write, down(&adapter->lock); #endif if (adapter->id & ALGO_SMBUS) - res = adapter->smbus_access(addr,read_write,command,size,data); + res = ((struct smbus_adapter *) adapter) -> + smbus_access(addr,read_write,command,size,data); else res = smbus_access_i2c(adapter,addr,read_write,command,size,data); #ifdef SPINLOCK @@ -95,7 +96,7 @@ s32 smbus_access (struct smbus_adapter * adapter, u8 addr, char read_write, For SMBUS_QUICK: Use addr, read_write For SMBUS_BYTE: Use addr, read_write, command .... */ -s32 smbus_access_i2c(struct smbus_adapter * adapter, u8 addr, char read_write, +s32 smbus_access_i2c(struct i2c_adapter * adapter, u8 addr, char read_write, u8 command, int size, union smbus_data * data) { /* So we need to generate a series of msgs */ diff --git a/src/Module.mk b/src/Module.mk index a70b8304..bc0bf97d 100644 --- a/src/Module.mk +++ b/src/Module.mk @@ -22,7 +22,8 @@ MODULE_DIR := src # Regrettably, even 'simply expanded variables' will not put their currently # defined value verbatim into the command-list of rules... -SRCTARGETS := $(MODULE_DIR)/smbus.o $(MODULE_DIR)/piix4.o $(MODULE_DIR)/isa.o +SRCTARGETS := $(MODULE_DIR)/smbus.o $(MODULE_DIR)/piix4.o $(MODULE_DIR)/isa.o \ + $(MODULE_DIR)/lm78.o # Include all dependency files INCLUDEFILES += $(SRCTARGETS:.o=.d) diff --git a/src/isa.h b/src/isa.h index d5ad471d..9c738b67 100644 --- a/src/isa.h +++ b/src/isa.h @@ -77,7 +77,7 @@ struct isa_client { void *data; /* Here ended i2c_client */ - unsigned int full_address; + unsigned int isa_addr; }; /* An algorithm describes how a certain class of busses can be accessed. @@ -127,6 +127,8 @@ struct isa_adapter { access will fail! */ #define i2c_is_isa_client(clientptr) \ ((clientptr)->adapter->algo->id == ALGO_ISA) +#define i2c_is_isa_adapter(adapptr) \ + ((adapptr)->algo->id == ALGO_ISA) /* Next: define ISA variants of registering. */ #define isa_add_algorithm(algoptr) \ diff --git a/src/piix4.c b/src/piix4.c index c06f5a5f..52bcd0b4 100644 --- a/src/piix4.c +++ b/src/piix4.c @@ -49,6 +49,7 @@ s32 piix4_access(u8 addr, char read_write, u8 command, int size, union smbus_data * data) { /* TO BE WRITTEN! */ + return -1; } @@ -89,10 +90,9 @@ int piix4_cleanup(void) if (piix4_initialized >= 2) { if ((res = smbus_del_adapter(&piix4_adapter))) { - printk("piix4.o: smbus_del_adapter failed, module not removed"); + printk("piix4.o: smbus_del_adapter failed, module not removed\n"); return res; - } - else + } else piix4_initialized--; } if (piix4_initialized >= 1) { diff --git a/src/smbus.c b/src/smbus.c index 9b66e448..8494caf1 100644 --- a/src/smbus.c +++ b/src/smbus.c @@ -30,7 +30,7 @@ #include "version.h" #include "smbus.h" -static s32 smbus_access_i2c (struct smbus_adapter * adapter, u8 addr, +static s32 smbus_access_i2c (struct i2c_adapter * adapter, u8 addr, char read_write, u8 command, int size, union smbus_data * data); @@ -69,7 +69,7 @@ struct smbus_algorithm smbus_algorithm = { simulate the SMBus commands using the i2c access routines. We do all locking here, so you can ignore that in the adapter-specific smbus_accesss routine. */ -s32 smbus_access (struct smbus_adapter * adapter, u8 addr, char read_write, +s32 smbus_access (struct i2c_adapter * adapter, u8 addr, char read_write, u8 command, int size, union smbus_data * data) { int res; @@ -79,7 +79,8 @@ s32 smbus_access (struct smbus_adapter * adapter, u8 addr, char read_write, down(&adapter->lock); #endif if (adapter->id & ALGO_SMBUS) - res = adapter->smbus_access(addr,read_write,command,size,data); + res = ((struct smbus_adapter *) adapter) -> + smbus_access(addr,read_write,command,size,data); else res = smbus_access_i2c(adapter,addr,read_write,command,size,data); #ifdef SPINLOCK @@ -95,7 +96,7 @@ s32 smbus_access (struct smbus_adapter * adapter, u8 addr, char read_write, For SMBUS_QUICK: Use addr, read_write For SMBUS_BYTE: Use addr, read_write, command .... */ -s32 smbus_access_i2c(struct smbus_adapter * adapter, u8 addr, char read_write, +s32 smbus_access_i2c(struct i2c_adapter * adapter, u8 addr, char read_write, u8 command, int size, union smbus_data * data) { /* So we need to generate a series of msgs */ diff --git a/src/smbus.h b/src/smbus.h index 68a27d02..6227867d 100644 --- a/src/smbus.h +++ b/src/smbus.h @@ -130,6 +130,8 @@ struct smbus_adapter { course. */ #define i2c_is_smbus_client(clientptr) \ ((clientptr)->adapter->algo->id == ALGO_SMBUS) +#define i2c_is_smbus_adapter(adapptr) \ + ((adapptr)->algo->id == ALGO_SMBUS) /* This union is used within smbus_access routines */ union smbus_data { @@ -157,21 +159,23 @@ extern struct smbus_algorithm smbus_algorithm; /* This is the very generalized SMBus access routine. You probably do not want to use this, though; one of the functions below may be much easier, - and probably just as fast. */ -extern s32 smbus_access (struct smbus_adapter * adapter, u8 addr, + and probably just as fast. + Note that we use i2c_adapter here, because you do not need a specific + smbus adapter to call this function. */ +extern s32 smbus_access (struct i2c_adapter * adapter, u8 addr, char read_write, u8 command, int size, union smbus_data * data); /* Now follow the 'nice' access routines. These also document the calling conventions of smbus_access. */ -extern inline s32 smbus_write_quick(struct smbus_adapter * adapter, u8 addr, +extern inline s32 smbus_write_quick(struct i2c_adapter * adapter, u8 addr, u8 value) { return smbus_access(adapter,addr,value,0,SMBUS_QUICK,NULL); } -extern inline s32 smbus_read_byte(struct smbus_adapter * adapter,u8 addr) +extern inline s32 smbus_read_byte(struct i2c_adapter * adapter,u8 addr) { union smbus_data data; if (smbus_access(adapter,addr,SMBUS_READ,0,SMBUS_BYTE,&data)) @@ -180,13 +184,13 @@ extern inline s32 smbus_read_byte(struct smbus_adapter * adapter,u8 addr) return data.byte; } -extern inline s32 smbus_write_byte(struct smbus_adapter * adapter, u8 addr, +extern inline s32 smbus_write_byte(struct i2c_adapter * adapter, u8 addr, u8 value) { return smbus_access(adapter,addr,SMBUS_WRITE,value, SMBUS_BYTE,NULL); } -extern inline s32 smbus_read_byte_data(struct smbus_adapter * adapter, +extern inline s32 smbus_read_byte_data(struct i2c_adapter * adapter, u8 addr, u8 command) { union smbus_data data; @@ -196,7 +200,7 @@ extern inline s32 smbus_read_byte_data(struct smbus_adapter * adapter, return data.byte; } -extern inline s32 smbus_write_byte_data(struct smbus_adapter * adapter, +extern inline s32 smbus_write_byte_data(struct i2c_adapter * adapter, u8 addr, u8 command, u8 value) { union smbus_data data; @@ -204,7 +208,7 @@ extern inline s32 smbus_write_byte_data(struct smbus_adapter * adapter, return smbus_access(adapter,addr,SMBUS_WRITE,command,SMBUS_BYTE_DATA,&data); } -extern inline s32 smbus_read_word_data(struct smbus_adapter * adapter, +extern inline s32 smbus_read_word_data(struct i2c_adapter * adapter, u8 addr, u8 command) { union smbus_data data; @@ -214,7 +218,7 @@ extern inline s32 smbus_read_word_data(struct smbus_adapter * adapter, return data.word; } -extern inline s32 smbus_write_word_data(struct smbus_adapter * adapter, +extern inline s32 smbus_write_word_data(struct i2c_adapter * adapter, u8 addr, u8 command, u16 value) { union smbus_data data; @@ -222,7 +226,7 @@ extern inline s32 smbus_write_word_data(struct smbus_adapter * adapter, return smbus_access(adapter,addr,SMBUS_WRITE,command,SMBUS_WORD_DATA,&data); } -extern inline s32 smbus_process_call(struct smbus_adapter * adapter, +extern inline s32 smbus_process_call(struct i2c_adapter * adapter, u8 addr, u8 command, u16 value) { union smbus_data data; @@ -234,7 +238,7 @@ extern inline s32 smbus_process_call(struct smbus_adapter * adapter, } /* Returns the number of read bytes */ -extern inline s32 smbus_read_block_data(struct smbus_adapter * adapter, +extern inline s32 smbus_read_block_data(struct i2c_adapter * adapter, u8 addr, u8 command, u8 *values) { union smbus_data data; @@ -248,7 +252,7 @@ extern inline s32 smbus_read_block_data(struct smbus_adapter * adapter, } } -extern inline int smbus_write_block_data(struct smbus_adapter * adapter, +extern inline int smbus_write_block_data(struct i2c_adapter * adapter, u8 addr, u8 command, u8 length, u8 *values) {