Commit 6cbce905 authored by Evgeniy Polyakov's avatar Evgeniy Polyakov Committed by Greg Kroah-Hartman

[PATCH] w1: add ->search() method.

Patch allows w1_search() to be overwritten by bus_master drivers.
It is very usefull for several devices, like found in iPaq w1 bus master,
which does not support bit operations but has hardware implemented
search algorithm.
Signed-off-by: default avatarEvgeniy Polyakov <johnpol@2ka.mipt.ru>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 812ab7f3
...@@ -468,17 +468,75 @@ static void w1_slave_detach(struct w1_slave *sl) ...@@ -468,17 +468,75 @@ static void w1_slave_detach(struct w1_slave *sl)
w1_netlink_send(sl->master, &msg); w1_netlink_send(sl->master, &msg);
} }
static void w1_search(struct w1_master *dev) static struct w1_master *w1_search_master(unsigned long data)
{ {
u64 last, rn, tmp; struct w1_master *dev;
int i, count = 0, slave_count; int found = 0;
int last_family_desc, last_zero, last_device;
int search_bit, id_bit, comp_bit, desc_bit; spin_lock_irq(&w1_mlock);
struct list_head *ent; list_for_each_entry(dev, &w1_masters, w1_master_entry) {
if (dev->bus_master->data == data) {
found = 1;
atomic_inc(&dev->refcnt);
break;
}
}
spin_unlock_irq(&w1_mlock);
return (found)?dev:NULL;
}
void w1_slave_found(unsigned long data, u64 rn)
{
int slave_count;
struct w1_slave *sl; struct w1_slave *sl;
struct list_head *ent;
struct w1_reg_num *tmp;
int family_found = 0; int family_found = 0;
struct w1_master *dev;
dev = w1_search_master(data);
if (!dev) {
printk(KERN_ERR "Failed to find w1 master device for data %08lx, it is impossible.\n",
data);
return;
}
tmp = (struct w1_reg_num *) &rn;
slave_count = 0;
list_for_each(ent, &dev->slist) {
sl = list_entry(ent, struct w1_slave, w1_slave_entry);
dev->attempts++; if (sl->reg_num.family == tmp->family &&
sl->reg_num.id == tmp->id &&
sl->reg_num.crc == tmp->crc) {
set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
break;
}
else if (sl->reg_num.family == tmp->family) {
family_found = 1;
break;
}
slave_count++;
}
if (slave_count == dev->slave_count &&
rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
}
atomic_dec(&dev->refcnt);
}
void w1_search(struct w1_master *dev)
{
u64 last, rn, tmp;
int i, count = 0;
int last_family_desc, last_zero, last_device;
int search_bit, id_bit, comp_bit, desc_bit;
search_bit = id_bit = comp_bit = 0; search_bit = id_bit = comp_bit = 0;
rn = tmp = last = 0; rn = tmp = last = 0;
...@@ -556,33 +614,8 @@ static void w1_search(struct w1_master *dev) ...@@ -556,33 +614,8 @@ static void w1_search(struct w1_master *dev)
last_device = 1; last_device = 1;
desc_bit = last_zero; desc_bit = last_zero;
slave_count = 0; w1_slave_found(dev->bus_master->data, rn);
list_for_each(ent, &dev->slist) {
struct w1_reg_num *tmp;
tmp = (struct w1_reg_num *) &rn;
sl = list_entry(ent, struct w1_slave, w1_slave_entry);
if (sl->reg_num.family == tmp->family &&
sl->reg_num.id == tmp->id &&
sl->reg_num.crc == tmp->crc) {
set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
break;
}
else if (sl->reg_num.family == tmp->family) {
family_found = 1;
break;
}
slave_count++;
}
if (slave_count == dev->slave_count &&
rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
}
} }
} }
...@@ -724,8 +757,8 @@ int w1_process(void *data) ...@@ -724,8 +757,8 @@ int w1_process(void *data)
clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
} }
w1_search(dev); w1_search_devices(dev, w1_slave_found);
list_for_each_safe(ent, n, &dev->slist) { list_for_each_safe(ent, n, &dev->slist) {
sl = list_entry(ent, struct w1_slave, w1_slave_entry); sl = list_entry(ent, struct w1_slave, w1_slave_entry);
......
...@@ -74,6 +74,8 @@ struct w1_slave ...@@ -74,6 +74,8 @@ struct w1_slave
struct device_attribute attr_name, attr_val; struct device_attribute attr_name, attr_val;
}; };
typedef void (* w1_slave_found_callback)(unsigned long, u64);
struct w1_bus_master struct w1_bus_master
{ {
unsigned long data; unsigned long data;
...@@ -90,6 +92,8 @@ struct w1_bus_master ...@@ -90,6 +92,8 @@ struct w1_bus_master
u8 (*touch_bit)(unsigned long, u8); u8 (*touch_bit)(unsigned long, u8);
u8 (*reset_bus)(unsigned long); u8 (*reset_bus)(unsigned long);
void (*search)(unsigned long, w1_slave_found_callback);
}; };
struct w1_master struct w1_master
...@@ -127,6 +131,7 @@ struct w1_master ...@@ -127,6 +131,7 @@ struct w1_master
int w1_create_master_attributes(struct w1_master *); int w1_create_master_attributes(struct w1_master *);
void w1_destroy_master_attributes(struct w1_master *); void w1_destroy_master_attributes(struct w1_master *);
void w1_search(struct w1_master *dev);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -174,6 +174,15 @@ u8 w1_calc_crc8(u8 * data, int len) ...@@ -174,6 +174,15 @@ u8 w1_calc_crc8(u8 * data, int len)
return crc; return crc;
} }
void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
{
dev->attempts++;
if (dev->bus_master->search)
dev->bus_master->search(dev->bus_master->data, cb);
else
w1_search(dev);
}
EXPORT_SYMBOL(w1_write_bit); EXPORT_SYMBOL(w1_write_bit);
EXPORT_SYMBOL(w1_write_8); EXPORT_SYMBOL(w1_write_8);
EXPORT_SYMBOL(w1_read_bit); EXPORT_SYMBOL(w1_read_bit);
...@@ -183,3 +192,4 @@ EXPORT_SYMBOL(w1_calc_crc8); ...@@ -183,3 +192,4 @@ EXPORT_SYMBOL(w1_calc_crc8);
EXPORT_SYMBOL(w1_delay); EXPORT_SYMBOL(w1_delay);
EXPORT_SYMBOL(w1_read_block); EXPORT_SYMBOL(w1_read_block);
EXPORT_SYMBOL(w1_write_block); EXPORT_SYMBOL(w1_write_block);
EXPORT_SYMBOL(w1_search_devices);
...@@ -34,5 +34,6 @@ int w1_reset_bus(struct w1_master *); ...@@ -34,5 +34,6 @@ int w1_reset_bus(struct w1_master *);
u8 w1_calc_crc8(u8 *, int); u8 w1_calc_crc8(u8 *, int);
void w1_write_block(struct w1_master *, u8 *, int); void w1_write_block(struct w1_master *, u8 *, int);
u8 w1_read_block(struct w1_master *, u8 *, int); u8 w1_read_block(struct w1_master *, u8 *, int);
void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb);
#endif /* __W1_IO_H */ #endif /* __W1_IO_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment