mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	pcmcia: move cistpl.c into pcmcia module
As PCMCIA is the only real user of CIS access functions, include cistpl.c in the PCMCIA module, not in the PCMCIA & CardBus core module. Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
This commit is contained in:
		
							parent
							
								
									4e8804ff6d
								
							
						
					
					
						commit
						6e7b51a733
					
				
					 6 changed files with 194 additions and 198 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t
 | 
			
		|||
    kfree(buf);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(pccard_read_tuple);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -1439,7 +1429,6 @@ int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function,
 | 
			
		|||
	kfree(buf);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(pccard_loop_tuple);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -1533,4 +1522,149 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
 | 
			
		|||
	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,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue