From 81a7bd802541a7acefa7b87d8b57900e5a7e7eb9 Mon Sep 17 00:00:00 2001 From: "Mark D. Studebaker" Date: Sat, 6 Jul 2002 01:36:04 +0000 Subject: [PATCH] reassign address on write to /proc git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1426 7894878c-1315-0410-8ee3-d5d059ff63e0 --- doc/chips/smbus-arp | 66 ++++++++++++++++++++++++++++++++++++++++ kernel/chips/smbus-arp.c | 52 +++++++++++++++++++++++++------ 2 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 doc/chips/smbus-arp diff --git a/doc/chips/smbus-arp b/doc/chips/smbus-arp new file mode 100644 index 00000000..e04fc0a4 --- /dev/null +++ b/doc/chips/smbus-arp @@ -0,0 +1,66 @@ +SMBUS_ARP Driver +------------- +This is a demonstration driver which provides SMBus 2.0 +ARP services. It isn't much use except for testing SMBus 2.0 +ARP and PEC support in the i2c layer. +It is NOT a normal 'chip' driver for a particular sensor device. +If you don't know what SMBus ARP is you don't need this driver. + + +Stability +--------- +Beta. + + +DETECTION +------------- +This driver requires SMBus 2.0 support in i2c-2.6.4 or higher. +If your kernel does not have i2c-2.6.4 or higher the module +will refuse to load. + +This driver will register itself on each i2c bus which +supports SMBus Block Data transactions. + + +USES +---- +The module ARPs each supported bus when it is inserted +(or after that when a i2c bus driver is inserted). +It does not periodically re-ARP, and the i2c stack does not +currently support SMBus Host Notify, so it will not detect +hot-plugged devices. + +The smbus-arp module should be inserted before any chip modules +so that it has an opportunity to assign addresses. + + +/PROC ENTRIES +------------- +There are 8 entries in /proc, 0-7. Each is a 'slot'. +If a chip has responded to ARP, it will appear in a 'slot' +as follows. See the SMBus 2.0 Specification for details. + + value function + 1 SMBus address + 2 UDID Device Capabilities + 3 UDID Version / Revision + 4 UDID Vendor ID + 5 UDID Device ID + 6 UDID Interface + 7 UDID Subsystem Vendor ID + 8 UDID Subsystem Device ID + 9 UDID Vendor Specific ID + +To reassign a device to a different address, write +that address to the slot. For example, 'echo 13 > 0' +to reassign the device in slot 0 to address 13 (0x0d). + + +TO DO +----- +lots + +Author/Maintainer +----------------- +Mark D. Studebaker (mdsxyz123@yahoo.com) + diff --git a/kernel/chips/smbus-arp.c b/kernel/chips/smbus-arp.c index 8b628edb..ea883942 100644 --- a/kernel/chips/smbus-arp.c +++ b/kernel/chips/smbus-arp.c @@ -91,6 +91,7 @@ static u8 reserved[] = #define ARP_MAX_DEVICES 8 struct arp_device { int status; + u8 udid[UDID_LENGTH]; u8 dev_cap; u8 dev_ver; u16 dev_vid; @@ -152,21 +153,21 @@ static struct i2c_driver smbusarp_driver = { }; static ctl_table smbusarp_dir_table_template[] = { - {ARP_SYSCTL1, "0", NULL, 0, 0444, NULL, &i2c_proc_real, + {ARP_SYSCTL1, "0", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &smbusarp_contents}, - {ARP_SYSCTL2, "1", NULL, 0, 0444, NULL, &i2c_proc_real, + {ARP_SYSCTL2, "1", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &smbusarp_contents}, - {ARP_SYSCTL3, "2", NULL, 0, 0444, NULL, &i2c_proc_real, + {ARP_SYSCTL3, "2", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &smbusarp_contents}, - {ARP_SYSCTL4, "3", NULL, 0, 0444, NULL, &i2c_proc_real, + {ARP_SYSCTL4, "3", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &smbusarp_contents}, - {ARP_SYSCTL5, "4", NULL, 0, 0444, NULL, &i2c_proc_real, + {ARP_SYSCTL5, "4", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &smbusarp_contents}, - {ARP_SYSCTL6, "5", NULL, 0, 0444, NULL, &i2c_proc_real, + {ARP_SYSCTL6, "5", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &smbusarp_contents}, - {ARP_SYSCTL7, "6", NULL, 0, 0444, NULL, &i2c_proc_real, + {ARP_SYSCTL7, "6", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &smbusarp_contents}, - {ARP_SYSCTL8, "7", NULL, 0, 0444, NULL, &i2c_proc_real, + {ARP_SYSCTL8, "7", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &smbusarp_contents}, {0} }; @@ -387,6 +388,9 @@ int smbusarp_init_client(struct i2c_client *client) } } + /* store things both ways */ + for(i = 0; i < UDID_LENGTH; i++) + data->dev[newdev].udid[i] = blk[i]; data->dev[newdev].saddr = addr; data->dev[newdev].status = ARP_BUSY; data->dev[newdev].dev_cap = blk[0]; @@ -424,12 +428,15 @@ int smbusarp_init_client(struct i2c_client *client) } +/* reassign address on writex */ void smbusarp_contents(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { int nr = ctl_name - ARP_SYSCTL1; struct arp_data *data = client->data; - + int ret; + u8 save; + u8 a; if (operation == SENSORS_PROC_REAL_INFO) *nrels_mag = 0; @@ -449,9 +456,34 @@ void smbusarp_contents(struct i2c_client *client, int operation, *nrels_mag = 0; } } else if (operation == SENSORS_PROC_REAL_WRITE) { - printk(KERN_WARNING "smbus-arp.o: No writes supported!\n"); + a = results[0]; + if(*nrels_mag >= 1 && + a >= 0 && + a < SMBUS_ADDRESS_SIZE && + data->dev[nr].status == ARP_BUSY && + data->address_pool[a] == ARP_FREE) { + save = data->dev[nr].udid[16]; + data->dev[nr].udid[16] = a << 1; + ret = i2c_smbus_write_block_data(client, ARP_ASSIGN_ADDR, + UDID_LENGTH, data->dev[nr].udid); + if(ret) { + data->dev[nr].udid[16] = save; +#ifdef DEBUG + printk(KERN_DEBUG "smbus-arp Bad response, address 0x%02x not assigned\n", a); +#endif + } else { + data->dev[nr].saddr = a; + data->address_pool[a] = ARP_BUSY; +#ifdef DEBUG + printk(KERN_DEBUG "smbus-arp Assigned address 0x%02x\n", a); +#endif + } + } else { + printk(KERN_WARNING "smbus-arp Bad address 0x%02x\n", a); + } } } + int __init sensors_smbusarp_init(void) { int res;