diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/cistpl.c | 18 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 12 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_ioctl.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 76 | ||||
-rw-r--r-- | drivers/pcmcia/socket_sysfs.c | 13 |
5 files changed, 89 insertions, 32 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index f804b45..fe789e0 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -266,13 +266,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem); ======================================================================*/ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, - u_int len, void *ptr) + size_t len, void *ptr) { struct cis_cache_entry *cis; int ret; if (s->fake_cis) { - if (s->fake_cis_len > addr+len) + if (s->fake_cis_len >= addr+len) memcpy(ptr, s->fake_cis+addr, len); else memset(ptr, 0xff, len); @@ -381,17 +381,17 @@ int verify_cis_cache(struct pcmcia_socket *s) ======================================================================*/ -int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) +int pcmcia_replace_cis(struct pcmcia_socket *s, + const u8 *data, const size_t len) { - kfree(s->fake_cis); - s->fake_cis = NULL; - if (cis->Length > CISTPL_MAX_CIS_SIZE) + if (len > CISTPL_MAX_CIS_SIZE) return CS_BAD_SIZE; - s->fake_cis = kmalloc(cis->Length, GFP_KERNEL); + kfree(s->fake_cis); + s->fake_cis = kmalloc(len, GFP_KERNEL); if (s->fake_cis == NULL) return CS_OUT_OF_RESOURCE; - s->fake_cis_len = cis->Length; - memcpy(s->fake_cis, cis->Data, cis->Length); + s->fake_cis_len = len; + memcpy(s->fake_cis, data, len); return CS_SUCCESS; } EXPORT_SYMBOL(pcmcia_replace_cis); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 6501a96..a393501 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -864,7 +864,6 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) int ret = -ENOMEM; int no_funcs; int old_funcs; - cisdump_t *cis; cistpl_longlink_mfc_t mfc; if (!filename) @@ -889,16 +888,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) goto release; } - cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); - if (!cis) { - ret = -ENOMEM; - goto release; - } - - cis->Length = fw->size + 1; - memcpy(cis->Data, fw->data, fw->size); - - if (!pcmcia_replace_cis(s, cis)) + if (!pcmcia_replace_cis(s, fw->data, fw->size)) ret = 0; else { dev_printk(KERN_ERR, &dev->dev, diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 0492d2d..f555a50 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -867,7 +867,7 @@ static int ds_ioctl(struct inode * inode, struct file * file, &buf->win_info.map); break; case DS_REPLACE_CIS: - ret = pcmcia_replace_cis(s, &buf->cisdump); + ret = pcmcia_replace_cis(s, buf->cisdump.Data, buf->cisdump.Length); break; case DS_BIND_REQUEST: if (!capable(CAP_SYS_ADMIN)) { diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 2c63605..9afe420 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -912,3 +912,79 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) { pcmcia_release_window(p_dev->win); } EXPORT_SYMBOL(pcmcia_disable_device); + + +struct pcmcia_cfg_mem { + tuple_t tuple; + cisparse_t parse; + u8 buf[256]; + cistpl_cftable_entry_t dflt; +}; + +/** + * pcmcia_loop_config() - loop over configuration options + * @p_dev: the struct pcmcia_device which we need to loop for. + * @conf_check: function to call for each configuration option. + * It gets passed the struct pcmcia_device, the CIS data + * describing the configuration option, and private data + * being passed to pcmcia_loop_config() + * @priv_data: private data to be passed to the conf_check function. + * + * pcmcia_loop_config() loops over all configuration options, and calls + * the driver-specific conf_check() for each one, checking whether + * it is a valid one. + */ +int pcmcia_loop_config(struct pcmcia_device *p_dev, + int (*conf_check) (struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + unsigned int vcc, + void *priv_data), + void *priv_data) +{ + struct pcmcia_cfg_mem *cfg_mem; + + tuple_t *tuple; + int ret = -ENODEV; + unsigned int vcc; + + cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL); + if (cfg_mem == NULL) + return -ENOMEM; + + /* get the current Vcc setting */ + vcc = p_dev->socket->socket.Vcc; + + tuple = &cfg_mem->tuple; + tuple->TupleData = cfg_mem->buf; + tuple->TupleDataMax = 255; + tuple->TupleOffset = 0; + tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple->Attributes = 0; + + ret = pcmcia_get_first_tuple(p_dev, tuple); + while (!ret) { + cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry; + + if (pcmcia_get_tuple_data(p_dev, tuple)) + goto next_entry; + + if (pcmcia_parse_tuple(p_dev, tuple, &cfg_mem->parse)) + goto next_entry; + + /* default values */ + p_dev->conf.ConfigIndex = cfg->index; + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + cfg_mem->dflt = *cfg; + + ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data); + if (!ret) + break; + +next_entry: + ret = pcmcia_get_next_tuple(p_dev, tuple); + } + + return ret; +} +EXPORT_SYMBOL(pcmcia_loop_config); diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 006a29e..ff9a3bb 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -316,27 +316,18 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) { struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); - cisdump_t *cis; int error; if (off) return -EINVAL; - if (count >= 0x200) + if (count >= CISTPL_MAX_CIS_SIZE) return -EINVAL; if (!(s->state & SOCKET_PRESENT)) return -ENODEV; - cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); - if (!cis) - return -ENOMEM; - - cis->Length = count + 1; - memcpy(cis->Data, buf, count); - - error = pcmcia_replace_cis(s, cis); - kfree(cis); + error = pcmcia_replace_cis(s, buf, count); if (error) return -EIO; |