SMBus emulation on real I2C adapters finished

Not tested, as I do not own such an adapter...

Block reading not implemented, as it seems impossible to do with the
currently available I2C primitives.


git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@43 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
Frodo Looijaard committed 1998-12-06 23:03:46 +00:00
1 parent f322a67793
commit 45e87b2b9e
5 files changed
+169 -32

No files matched your search

+1
View File
@@ -1,5 +1,6 @@
Many, many things. Most notably:
* Support 10-bit addresses. At this moment, they are supported nowhere
* Change the i2c modules to keep the namespace clean (EXPORT_SYMBOL does not
work for us; many static declarations need to be added; better ask Simon
Vogl first)
+1 -1
View File
@@ -61,7 +61,7 @@ static struct proc_dir_entry proc_bus_dir =
/* namelen */ 3,
/* name */ "bus",
/* mode */ S_IRUGO | S_IXUGO | S_IFDIR,
/* nlink */ 1, /* Corrected by proc_register[_dynamic] */
/* nlink */ 2, /* Corrected by proc_register[_dynamic] */
/* uid */ 0,
/* gid */ 0,
/* size */ 0,
+83 -15
View File
@@ -93,25 +93,93 @@ s32 smbus_access (struct i2c_adapter * adapter, u8 addr, char read_write,
}
/* Simulate a SMBus command using the i2c protocol
No checking of paramters is done!
For SMBUS_QUICK: Use addr, read_write
For SMBUS_BYTE: Use addr, read_write, command
.... */
No checking of paramters is done! */
s32 smbus_access_i2c(struct i2c_adapter * adapter, u8 addr, char read_write,
u8 command, int size, union smbus_data * data)
{
/* For now */
return -1;
/* So we need to generate a series of msgs. In the case of writing, we
need to use only one message; when reading, we need two. We initialize
most things with sane defaults, to keep the code below somewhat
simpler. */
char msgbuf0[33] = { command };
char msgbuf1[33];
int num = read_write == SMBUS_READ?2:1;
struct i2c_msg msg[2] = { { addr, 0, 1, msgbuf0 },
{ addr, I2C_M_RD, 0, msgbuf1 }
};
int i;
/* So we need to generate a series of msgs
struct i2c_msg msg[2];
char msgbuf0[2];
char msgbuf1[32];
msg[0].addr = addr;
msg[0].flags = read_write;
msg[0].len = 0;
msg[0].buf = msgbuf0;
WHATEVER */
switch(size) {
case SMBUS_QUICK:
msg[0].len = 0;
num = 1; /* Special case: The read/write field is used as data */
break;
case SMBUS_BYTE:
if (read_write == SMBUS_READ)
/* Special case: only a read! */
msg[0].flags = I2C_M_RD;
break;
case SMBUS_BYTE_DATA:
if (read_write == SMBUS_READ)
msg[1].len = 1;
else {
msg[0].len = 2;
msgbuf0[1] = data->byte;
}
break;
case SMBUS_WORD_DATA:
if (read_write == SMBUS_READ)
msg[1].len = 2;
else {
msg[0].len=3;
msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff;
}
break;
case SMBUS_PROC_CALL:
num = 2; /* Special case */
msg[0].len = 3;
msg[1].len = 2;
msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff;
break;
case SMBUS_BLOCK_DATA:
if (read_write == SMBUS_READ) {
printk("smbus.o: Block read not supported under I2C emulation!\n");
return -1;
} else {
msg[1].len = data->block[0] + 1;
if (msg[1].len > 32) {
printk("smbus.o: smbus_access called with invalid block write "
"size (%d)\n",msg[1].len);
return -1;
}
for (i = 1; i <= msg[1].len; i++)
msgbuf0[i] = data->block[1];
}
break;
default:
printk("smbus.o: smbus_access called with invalid size (%d)\n",size);
return -1;
}
if (i2c_transfer(adapter, msg, num) < 0)
return -1;
if(read_write == SMBUS_READ)
switch(size) {
case SMBUS_BYTE:
data->byte = msgbuf0[0];
break;
case SMBUS_BYTE_DATA:
data->byte = msgbuf1[0];
break;
case SMBUS_WORD_DATA:
case SMBUS_PROC_CALL:
data->word = msgbuf1[0] + (msgbuf1[1] << 8);
break;
}
return 0;
}
/* Algorithm master_xfer call-back implementation. Can't do that... */
+1 -1
View File
@@ -61,7 +61,7 @@ static struct proc_dir_entry proc_bus_dir =
/* namelen */ 3,
/* name */ "bus",
/* mode */ S_IRUGO | S_IXUGO | S_IFDIR,
/* nlink */ 1, /* Corrected by proc_register[_dynamic] */
/* nlink */ 2, /* Corrected by proc_register[_dynamic] */
/* uid */ 0,
/* gid */ 0,
/* size */ 0,
+83 -15
View File
@@ -93,25 +93,93 @@ s32 smbus_access (struct i2c_adapter * adapter, u8 addr, char read_write,
}
/* Simulate a SMBus command using the i2c protocol
No checking of paramters is done!
For SMBUS_QUICK: Use addr, read_write
For SMBUS_BYTE: Use addr, read_write, command
.... */
No checking of paramters is done! */
s32 smbus_access_i2c(struct i2c_adapter * adapter, u8 addr, char read_write,
u8 command, int size, union smbus_data * data)
{
/* For now */
return -1;
/* So we need to generate a series of msgs. In the case of writing, we
need to use only one message; when reading, we need two. We initialize
most things with sane defaults, to keep the code below somewhat
simpler. */
char msgbuf0[33] = { command };
char msgbuf1[33];
int num = read_write == SMBUS_READ?2:1;
struct i2c_msg msg[2] = { { addr, 0, 1, msgbuf0 },
{ addr, I2C_M_RD, 0, msgbuf1 }
};
int i;
/* So we need to generate a series of msgs
struct i2c_msg msg[2];
char msgbuf0[2];
char msgbuf1[32];
msg[0].addr = addr;
msg[0].flags = read_write;
msg[0].len = 0;
msg[0].buf = msgbuf0;
WHATEVER */
switch(size) {
case SMBUS_QUICK:
msg[0].len = 0;
num = 1; /* Special case: The read/write field is used as data */
break;
case SMBUS_BYTE:
if (read_write == SMBUS_READ)
/* Special case: only a read! */
msg[0].flags = I2C_M_RD;
break;
case SMBUS_BYTE_DATA:
if (read_write == SMBUS_READ)
msg[1].len = 1;
else {
msg[0].len = 2;
msgbuf0[1] = data->byte;
}
break;
case SMBUS_WORD_DATA:
if (read_write == SMBUS_READ)
msg[1].len = 2;
else {
msg[0].len=3;
msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff;
}
break;
case SMBUS_PROC_CALL:
num = 2; /* Special case */
msg[0].len = 3;
msg[1].len = 2;
msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff;
break;
case SMBUS_BLOCK_DATA:
if (read_write == SMBUS_READ) {
printk("smbus.o: Block read not supported under I2C emulation!\n");
return -1;
} else {
msg[1].len = data->block[0] + 1;
if (msg[1].len > 32) {
printk("smbus.o: smbus_access called with invalid block write "
"size (%d)\n",msg[1].len);
return -1;
}
for (i = 1; i <= msg[1].len; i++)
msgbuf0[i] = data->block[1];
}
break;
default:
printk("smbus.o: smbus_access called with invalid size (%d)\n",size);
return -1;
}
if (i2c_transfer(adapter, msg, num) < 0)
return -1;
if(read_write == SMBUS_READ)
switch(size) {
case SMBUS_BYTE:
data->byte = msgbuf0[0];
break;
case SMBUS_BYTE_DATA:
data->byte = msgbuf1[0];
break;
case SMBUS_WORD_DATA:
case SMBUS_PROC_CALL:
data->word = msgbuf1[0] + (msgbuf1[1] << 8);
break;
}
return 0;
}
/* Algorithm master_xfer call-back implementation. Can't do that... */