diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/cs_internal.h | 5 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_ioctl.c | 57 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 39 |
3 files changed, 58 insertions, 43 deletions
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index f889a44280f5..88c96aee0f45 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -126,10 +126,9 @@ extern struct class_interface pccard_sysfs_interface; extern struct rw_semaphore pcmcia_socket_list_rwsem; extern struct list_head pcmcia_socket_list; int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req); -int pccard_get_configuration_info(struct pcmcia_socket *s, unsigned int function, config_info_t *config); +int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config); int pccard_reset_card(struct pcmcia_socket *skt); -int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status); -int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg); +int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status); struct pcmcia_callback{ diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 80969f7e7a0b..56b625d171ae 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -70,10 +70,26 @@ extern int ds_pc_debug; #define ds_dbg(lvl, fmt, arg...) do { } while (0) #endif +static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s, + unsigned int function) +{ + struct pcmcia_device *p_dev = NULL; + unsigned long flags; + + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { + if (p_dev->func == function) { + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + return pcmcia_get_dev(p_dev); + } + } + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + return NULL; +} /* backwards-compatible accessing of driver --- by name! */ -static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info) +static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info) { struct device_driver *drv; struct pcmcia_driver *p_drv; @@ -583,9 +599,11 @@ static int ds_ioctl(struct inode * inode, struct file * file, if (buf->config.Function && (buf->config.Function >= s->functions)) ret = CS_BAD_ARGS; - else - ret = pccard_get_configuration_info(s, - buf->config.Function, &buf->config); + else { + struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function); + ret = pccard_get_configuration_info(s, p_dev, &buf->config); + pcmcia_put_dev(p_dev); + } break; case DS_GET_FIRST_TUPLE: down(&s->skt_sem); @@ -609,12 +627,15 @@ static int ds_ioctl(struct inode * inode, struct file * file, ret = pccard_reset_card(s); break; case DS_GET_STATUS: - if (buf->status.Function && - (buf->status.Function >= s->functions)) - ret = CS_BAD_ARGS; - else - ret = pccard_get_status(s, buf->status.Function, &buf->status); - break; + if (buf->status.Function && + (buf->status.Function >= s->functions)) + ret = CS_BAD_ARGS; + else { + struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function); + ret = pccard_get_status(s, p_dev, &buf->status); + pcmcia_put_dev(p_dev); + } + break; case DS_VALIDATE_CIS: down(&s->skt_sem); pcmcia_validate_mem(s); @@ -638,12 +659,16 @@ static int ds_ioctl(struct inode * inode, struct file * file, err = -EPERM; goto free_out; } - if (buf->conf_reg.Function && - (buf->conf_reg.Function >= s->functions)) - ret = CS_BAD_ARGS; - else - ret = pccard_access_configuration_register(s, - buf->conf_reg.Function, &buf->conf_reg); + + ret = CS_BAD_ARGS; + + if (!(buf->conf_reg.Function && + (buf->conf_reg.Function >= s->functions))) { + struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function); + if (p_dev) + ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg); + pcmcia_put_dev(p_dev); + } break; case DS_GET_FIRST_REGION: case DS_GET_NEXT_REGION: diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 11a94d9a15fb..aabde8be6470 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -165,21 +165,19 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, * this and the tuple reading services. */ -int pccard_access_configuration_register(struct pcmcia_socket *s, - unsigned int function, +int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg) { + struct pcmcia_socket *s; config_t *c; int addr; u_char val; - if (!s || !s->config) + if (!p_dev || !p_dev->function_config) return CS_NO_CARD; - c = &s->config[function]; - - if (c == NULL) - return CS_NO_CARD; + s = p_dev->socket; + c = p_dev->function_config; if (!(c->state & CONFIG_LOCKED)) return CS_CONFIGURATION_LOCKED; @@ -200,20 +198,12 @@ int pccard_access_configuration_register(struct pcmcia_socket *s, break; } return CS_SUCCESS; -} /* pccard_access_configuration_register */ - -int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, - conf_reg_t *reg) -{ - return pccard_access_configuration_register(p_dev->socket, - p_dev->func, reg); -} +} /* pcmcia_access_configuration_register */ EXPORT_SYMBOL(pcmcia_access_configuration_register); - int pccard_get_configuration_info(struct pcmcia_socket *s, - unsigned int function, + struct pcmcia_device *p_dev, config_info_t *config) { config_t *c; @@ -221,7 +211,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; - config->Function = function; + config->Function = p_dev->func; #ifdef CONFIG_CARDBUS if (s->state & SOCKET_CARDBUS) { @@ -242,7 +232,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, } #endif - c = (s->config != NULL) ? &s->config[function] : NULL; + c = (p_dev) ? p_dev->function_config : NULL; if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { config->Attributes = 0; @@ -271,7 +261,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config) { - return pccard_get_configuration_info(p_dev->socket, p_dev->func, + return pccard_get_configuration_info(p_dev->socket, p_dev, config); } EXPORT_SYMBOL(pcmcia_get_configuration_info); @@ -317,7 +307,7 @@ EXPORT_SYMBOL(pcmcia_get_window); * SocketState yet: I haven't seen any point for it. */ -int pccard_get_status(struct pcmcia_socket *s, unsigned int function, +int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status) { config_t *c; @@ -334,7 +324,8 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; - c = (s->config != NULL) ? &s->config[function] : NULL; + c = (p_dev) ? p_dev->function_config : NULL; + if ((c != NULL) && (c->state & CONFIG_LOCKED) && (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { u_char reg; @@ -370,9 +361,9 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, return CS_SUCCESS; } /* pccard_get_status */ -int pcmcia_get_status(client_handle_t handle, cs_status_t *status) +int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status) { - return pccard_get_status(handle->socket, handle->func, status); + return pccard_get_status(p_dev->socket, p_dev, status); } EXPORT_SYMBOL(pcmcia_get_status); |