diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 83ff802de544..3c83f68c803a 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -2,11 +2,11 @@ # Makefile for the kernel pcmcia subsystem (c/o David Hinds) # -pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o +pcmcia_core-y += cs.o rsrc_mgr.o socket_sysfs.o pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o obj-$(CONFIG_PCCARD) += pcmcia_core.o -pcmcia-y += ds.o pcmcia_resource.o +pcmcia-y += ds.o pcmcia_resource.o cistpl.o pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o obj-$(CONFIG_PCMCIA) += pcmcia.o diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 368367ced62b..936417c3e79e 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -76,7 +76,6 @@ void release_cis_mem(struct pcmcia_socket *s) s->cis_virt = NULL; } } -EXPORT_SYMBOL(release_cis_mem); /* * Map the card memory at "card_offset" into virtual space. @@ -195,7 +194,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, *(u_char *)(ptr+2), *(u_char *)(ptr+3)); return 0; } -EXPORT_SYMBOL(pcmcia_read_cis_mem); void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, @@ -254,7 +252,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, } } } -EXPORT_SYMBOL(pcmcia_write_cis_mem); /*====================================================================== @@ -335,7 +332,6 @@ void destroy_cis_cache(struct pcmcia_socket *s) kfree(cis); } } -EXPORT_SYMBOL(destroy_cis_cache); /*====================================================================== @@ -374,7 +370,6 @@ int verify_cis_cache(struct pcmcia_socket *s) kfree(buf); return 0; } -EXPORT_SYMBOL(verify_cis_cache); /*====================================================================== @@ -400,7 +395,6 @@ int pcmcia_replace_cis(struct pcmcia_socket *s, memcpy(s->fake_cis, data, len); return 0; } -EXPORT_SYMBOL(pcmcia_replace_cis); /*====================================================================== @@ -446,7 +440,6 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple } return pccard_get_next_tuple(s, function, tuple); } -EXPORT_SYMBOL(pccard_get_first_tuple); static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) { @@ -582,7 +575,6 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_ tuple->CISOffset = ofs + 2; return 0; } -EXPORT_SYMBOL(pccard_get_next_tuple); /*====================================================================*/ @@ -606,7 +598,6 @@ int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple) _MIN(len, tuple->TupleDataMax), tuple->TupleData); return 0; } -EXPORT_SYMBOL(pccard_get_tuple_data); /*====================================================================== @@ -1379,7 +1370,6 @@ done: kfree(buf); return ret; } -EXPORT_SYMBOL(pccard_read_tuple); /** @@ -1439,7 +1429,6 @@ next_entry: kfree(buf); return ret; } -EXPORT_SYMBOL(pccard_loop_tuple); /** @@ -1533,4 +1522,149 @@ done: kfree(p); return ret; } -EXPORT_SYMBOL(pccard_validate_cis); + + +#define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev) + +static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, + loff_t off, size_t count) +{ + tuple_t tuple; + int status, i; + loff_t pointer = 0; + ssize_t ret = 0; + u_char *tuplebuffer; + u_char *tempbuffer; + + tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL); + if (!tuplebuffer) + return -ENOMEM; + + tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL); + if (!tempbuffer) { + ret = -ENOMEM; + goto free_tuple; + } + + memset(&tuple, 0, sizeof(tuple_t)); + + tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON; + tuple.DesiredTuple = RETURN_FIRST_TUPLE; + tuple.TupleOffset = 0; + + status = pccard_get_first_tuple(s, BIND_FN_ALL, &tuple); + while (!status) { + tuple.TupleData = tuplebuffer; + tuple.TupleDataMax = 255; + memset(tuplebuffer, 0, sizeof(u_char) * 255); + + status = pccard_get_tuple_data(s, &tuple); + if (status) + break; + + if (off < (pointer + 2 + tuple.TupleDataLen)) { + tempbuffer[0] = tuple.TupleCode & 0xff; + tempbuffer[1] = tuple.TupleLink & 0xff; + for (i = 0; i < tuple.TupleDataLen; i++) + tempbuffer[i + 2] = tuplebuffer[i] & 0xff; + + for (i = 0; i < (2 + tuple.TupleDataLen); i++) { + if (((i + pointer) >= off) && + (i + pointer) < (off + count)) { + buf[ret] = tempbuffer[i]; + ret++; + } + } + } + + pointer += 2 + tuple.TupleDataLen; + + if (pointer >= (off + count)) + break; + + if (tuple.TupleCode == CISTPL_END) + break; + status = pccard_get_next_tuple(s, BIND_FN_ALL, &tuple); + } + + kfree(tempbuffer); + free_tuple: + kfree(tuplebuffer); + + return ret; +} + + +static ssize_t pccard_show_cis(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + unsigned int size = 0x200; + + if (off >= size) + count = 0; + else { + struct pcmcia_socket *s; + unsigned int chains; + + if (off + count > size) + count = size - off; + + s = to_socket(container_of(kobj, struct device, kobj)); + + if (!(s->state & SOCKET_PRESENT)) + return -ENODEV; + if (pccard_validate_cis(s, &chains)) + return -EIO; + if (!chains) + return -ENODATA; + + count = pccard_extract_cis(s, buf, off, count); + } + + return count; +} + + +static ssize_t pccard_store_cis(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct pcmcia_socket *s; + int error; + + s = to_socket(container_of(kobj, struct device, kobj)); + + if (off) + return -EINVAL; + + if (count >= CISTPL_MAX_CIS_SIZE) + return -EINVAL; + + if (!(s->state & SOCKET_PRESENT)) + return -ENODEV; + + error = pcmcia_replace_cis(s, buf, count); + if (error) + return -EIO; + + mutex_lock(&s->skt_mutex); + if ((s->callback) && (s->state & SOCKET_PRESENT) && + !(s->state & SOCKET_CARDBUS)) { + if (try_module_get(s->callback->owner)) { + s->callback->requery(s, 1); + module_put(s->callback->owner); + } + } + mutex_unlock(&s->skt_mutex); + + return count; +} + + +struct bin_attribute pccard_cis_attr = { + .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR }, + .size = 0x200, + .read = pccard_show_cis, + .write = pccard_store_cis, +}; diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index ad05e3b59473..3f438afdcd4e 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -92,9 +92,6 @@ struct pccard_resource_ops { * Stuff internal to module "pcmcia_core": */ -/* cistpl.c */ -int verify_cis_cache(struct pcmcia_socket *s); - /* socket_sysfs.c */ extern int pccard_sysfs_add_socket(struct device *dev); extern void pccard_sysfs_remove_socket(struct device *dev); @@ -102,8 +99,6 @@ extern void pccard_sysfs_remove_socket(struct device *dev); /* cardbus.c */ int cb_alloc(struct pcmcia_socket *s); void cb_free(struct pcmcia_socket *s); -int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, - void *ptr); @@ -116,6 +111,7 @@ struct pcmcia_callback{ int (*event) (struct pcmcia_socket *s, event_t event, int priority); void (*requery) (struct pcmcia_socket *s, int new_cis); + int (*validate) (struct pcmcia_socket *s, unsigned int *i); int (*suspend) (struct pcmcia_socket *s); int (*resume) (struct pcmcia_socket *s); }; @@ -137,35 +133,6 @@ int pcmcia_insert_card(struct pcmcia_socket *skt); struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt); void pcmcia_put_socket(struct pcmcia_socket *skt); -/* cistpl.c */ -int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, - u_int addr, u_int len, void *ptr); -void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, - u_int addr, u_int len, void *ptr); -void release_cis_mem(struct pcmcia_socket *s); -void destroy_cis_cache(struct pcmcia_socket *s); -int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, - cisdata_t code, void *parse); -int pcmcia_replace_cis(struct pcmcia_socket *s, - const u8 *data, const size_t len); -int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count); - -/* loop over CIS entries */ -int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, - cisdata_t code, cisparse_t *parse, void *priv_data, - int (*loop_tuple) (tuple_t *tuple, - cisparse_t *parse, - void *priv_data)); - -int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, - tuple_t *tuple); - -int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, - tuple_t *tuple); - -int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple); - - /* rsrc_mgr.c */ int pcmcia_validate_mem(struct pcmcia_socket *s); struct resource *pcmcia_find_mem_region(u_long base, @@ -183,6 +150,37 @@ extern struct bus_type pcmcia_bus_type; /* pcmcia_resource.c */ extern int pcmcia_release_configuration(struct pcmcia_device *p_dev); +/* cistpl.c */ +extern struct bin_attribute pccard_cis_attr; + +int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, + u_int addr, u_int len, void *ptr); +void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, + u_int addr, u_int len, void *ptr); +void release_cis_mem(struct pcmcia_socket *s); +void destroy_cis_cache(struct pcmcia_socket *s); +int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, + cisdata_t code, void *parse); +int pcmcia_replace_cis(struct pcmcia_socket *s, + const u8 *data, const size_t len); +int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count); +int verify_cis_cache(struct pcmcia_socket *s); + +int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, + cisdata_t code, cisparse_t *parse, void *priv_data, + int (*loop_tuple) (tuple_t *tuple, + cisparse_t *parse, + void *priv_data)); + +int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, + tuple_t *tuple); + +int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, + tuple_t *tuple); + +int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple); + + #ifdef CONFIG_PCMCIA_IOCTL /* ds.c */ extern spinlock_t pcmcia_dev_list_lock; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 7bb52b003f0e..0ab4fe045920 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1313,6 +1313,7 @@ static struct pcmcia_callback pcmcia_bus_callback = { .owner = THIS_MODULE, .event = ds_event, .requery = pcmcia_bus_rescan, + .validate = pccard_validate_cis, .suspend = pcmcia_bus_suspend, .resume = pcmcia_bus_resume, }; @@ -1336,6 +1337,13 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, */ msleep(250); + ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr); + if (ret) { + dev_printk(KERN_ERR, dev, "PCMCIA registration failed\n"); + pcmcia_put_socket(socket); + return ret; + } + #ifdef CONFIG_PCMCIA_IOCTL init_waitqueue_head(&socket->queue); #endif @@ -1371,6 +1379,8 @@ static void pcmcia_bus_remove_socket(struct device *dev, release_cis_mem(socket); mutex_unlock(&socket->skt_mutex); + sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr); + pcmcia_put_socket(socket); return; diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 120d5ad99296..91626c17f97b 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -277,7 +277,9 @@ static int readable(struct pcmcia_socket *s, struct resource *res, s->cis_mem.res = res; s->cis_virt = ioremap(res->start, s->map_size); if (s->cis_virt) { - ret = pccard_validate_cis(s, count); + /* as we're only called from pcmcia.c, we're safe */ + if (s->callback->validate) + ret = s->callback->validate(s, count); /* invalidate mapping */ iounmap(s->cis_virt); s->cis_virt = NULL; diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 7a456000332a..537d79305e7a 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -213,138 +213,6 @@ static ssize_t pccard_store_resource(struct device *dev, } static DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); - -static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off, size_t count) -{ - tuple_t tuple; - int status, i; - loff_t pointer = 0; - ssize_t ret = 0; - u_char *tuplebuffer; - u_char *tempbuffer; - - tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL); - if (!tuplebuffer) - return -ENOMEM; - - tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL); - if (!tempbuffer) { - ret = -ENOMEM; - goto free_tuple; - } - - memset(&tuple, 0, sizeof(tuple_t)); - - tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON; - tuple.DesiredTuple = RETURN_FIRST_TUPLE; - tuple.TupleOffset = 0; - - status = pccard_get_first_tuple(s, BIND_FN_ALL, &tuple); - while (!status) { - tuple.TupleData = tuplebuffer; - tuple.TupleDataMax = 255; - memset(tuplebuffer, 0, sizeof(u_char) * 255); - - status = pccard_get_tuple_data(s, &tuple); - if (status) - break; - - if (off < (pointer + 2 + tuple.TupleDataLen)) { - tempbuffer[0] = tuple.TupleCode & 0xff; - tempbuffer[1] = tuple.TupleLink & 0xff; - for (i = 0; i < tuple.TupleDataLen; i++) - tempbuffer[i + 2] = tuplebuffer[i] & 0xff; - - for (i = 0; i < (2 + tuple.TupleDataLen); i++) { - if (((i + pointer) >= off) && - (i + pointer) < (off + count)) { - buf[ret] = tempbuffer[i]; - ret++; - } - } - } - - pointer += 2 + tuple.TupleDataLen; - - if (pointer >= (off + count)) - break; - - if (tuple.TupleCode == CISTPL_END) - break; - status = pccard_get_next_tuple(s, BIND_FN_ALL, &tuple); - } - - kfree(tempbuffer); - free_tuple: - kfree(tuplebuffer); - - return ret; -} - -static ssize_t pccard_show_cis(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - unsigned int size = 0x200; - - if (off >= size) - count = 0; - else { - struct pcmcia_socket *s; - unsigned int chains; - - if (off + count > size) - count = size - off; - - s = to_socket(container_of(kobj, struct device, kobj)); - - if (!(s->state & SOCKET_PRESENT)) - return -ENODEV; - if (pccard_validate_cis(s, &chains)) - return -EIO; - if (!chains) - return -ENODATA; - - count = pccard_extract_cis(s, buf, off, count); - } - - return count; -} - -static ssize_t pccard_store_cis(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); - int error; - - if (off) - return -EINVAL; - - if (count >= CISTPL_MAX_CIS_SIZE) - return -EINVAL; - - if (!(s->state & SOCKET_PRESENT)) - return -ENODEV; - - error = pcmcia_replace_cis(s, buf, count); - if (error) - return -EIO; - - mutex_lock(&s->skt_mutex); - if ((s->callback) && (s->state & SOCKET_PRESENT) && - !(s->state & SOCKET_CARDBUS)) { - if (try_module_get(s->callback->owner)) { - s->callback->requery(s, 1); - module_put(s->callback->owner); - } - } - mutex_unlock(&s->skt_mutex); - - return count; -} - - static struct attribute *pccard_socket_attributes[] = { &dev_attr_card_type.attr, &dev_attr_card_voltage.attr, @@ -362,28 +230,12 @@ static const struct attribute_group socket_attrs = { .attrs = pccard_socket_attributes, }; -static struct bin_attribute pccard_cis_attr = { - .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR }, - .size = 0x200, - .read = pccard_show_cis, - .write = pccard_store_cis, -}; - int pccard_sysfs_add_socket(struct device *dev) { - int ret = 0; - - ret = sysfs_create_group(&dev->kobj, &socket_attrs); - if (!ret) { - ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr); - if (ret) - sysfs_remove_group(&dev->kobj, &socket_attrs); - } - return ret; + return sysfs_create_group(&dev->kobj, &socket_attrs); } void pccard_sysfs_remove_socket(struct device *dev) { - sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr); sysfs_remove_group(&dev->kobj, &socket_attrs); }