diff --git a/[refs] b/[refs] index 6ab687049861..150ddeea724c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 795659ef0ee175d47723f806e7a29427b171e61b +refs/heads/master: a804b574e6c7236222593046fc2b1b8bd0298fce diff --git a/trunk/Documentation/pcmcia/driver-changes.txt b/trunk/Documentation/pcmcia/driver-changes.txt index 96f155e68750..059934363caf 100644 --- a/trunk/Documentation/pcmcia/driver-changes.txt +++ b/trunk/Documentation/pcmcia/driver-changes.txt @@ -1,5 +1,11 @@ This file details changes in 2.6 which affect PCMCIA card driver authors: +* New configuration loop helper (as of 2.6.28) + By calling pcmcia_loop_config(), a driver can iterate over all available + configuration options. During a driver's probe() phase, one doesn't need + to use pcmcia_get_{first,next}_tuple, pcmcia_get_tuple_data and + pcmcia_parse_tuple directly in most if not all cases. + * New release helper (as of 2.6.17) Instead of calling pcmcia_release_{configuration,io,irq,win}, all that's necessary now is calling pcmcia_disable_device. As there is no valid diff --git a/trunk/drivers/ata/pata_pcmcia.c b/trunk/drivers/ata/pata_pcmcia.c index 3c1fbb2f1d60..41b4361bbf6e 100644 --- a/trunk/drivers/ata/pata_pcmcia.c +++ b/trunk/drivers/ata/pata_pcmcia.c @@ -384,7 +384,6 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904), PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ - PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */ PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */ PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), @@ -405,9 +404,9 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), + PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), - PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), diff --git a/trunk/drivers/ide/legacy/ide-cs.c b/trunk/drivers/ide/legacy/ide-cs.c index 6dd27050b32b..21bfac137844 100644 --- a/trunk/drivers/ide/legacy/ide-cs.c +++ b/trunk/drivers/ide/legacy/ide-cs.c @@ -404,10 +404,8 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), - PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904), PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */ - PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */ PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ diff --git a/trunk/drivers/pcmcia/cistpl.c b/trunk/drivers/pcmcia/cistpl.c index 11c473c865a5..65129b54eb09 100644 --- a/trunk/drivers/pcmcia/cistpl.c +++ b/trunk/drivers/pcmcia/cistpl.c @@ -265,13 +265,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem); ======================================================================*/ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, - size_t len, void *ptr) + u_int 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); @@ -380,17 +380,17 @@ int verify_cis_cache(struct pcmcia_socket *s) ======================================================================*/ -int pcmcia_replace_cis(struct pcmcia_socket *s, - const u8 *data, const size_t len) +int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) { - if (len > CISTPL_MAX_CIS_SIZE) - return CS_BAD_SIZE; kfree(s->fake_cis); - s->fake_cis = kmalloc(len, GFP_KERNEL); + s->fake_cis = NULL; + if (cis->Length > CISTPL_MAX_CIS_SIZE) + return CS_BAD_SIZE; + s->fake_cis = kmalloc(cis->Length, GFP_KERNEL); if (s->fake_cis == NULL) return CS_OUT_OF_RESOURCE; - s->fake_cis_len = len; - memcpy(s->fake_cis, data, len); + s->fake_cis_len = cis->Length; + memcpy(s->fake_cis, cis->Data, cis->Length); return CS_SUCCESS; } EXPORT_SYMBOL(pcmcia_replace_cis); diff --git a/trunk/drivers/pcmcia/ds.c b/trunk/drivers/pcmcia/ds.c index 2382341975e5..4174d9656e35 100644 --- a/trunk/drivers/pcmcia/ds.c +++ b/trunk/drivers/pcmcia/ds.c @@ -854,6 +854,7 @@ 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) @@ -876,7 +877,16 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) goto release; } - if (!pcmcia_replace_cis(s, fw->data, fw->size)) + 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)) ret = 0; else { printk(KERN_ERR "pcmcia: CIS override failed\n"); diff --git a/trunk/drivers/pcmcia/pcmcia_ioctl.c b/trunk/drivers/pcmcia/pcmcia_ioctl.c index 6c086ffea448..419f97fc9a62 100644 --- a/trunk/drivers/pcmcia/pcmcia_ioctl.c +++ b/trunk/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.Data, buf->cisdump.Length); + ret = pcmcia_replace_cis(s, &buf->cisdump); break; case DS_BIND_REQUEST: if (!capable(CAP_SYS_ADMIN)) { diff --git a/trunk/drivers/pcmcia/pcmcia_resource.c b/trunk/drivers/pcmcia/pcmcia_resource.c index 4884a18cf9e6..9f054bc847f2 100644 --- a/trunk/drivers/pcmcia/pcmcia_resource.c +++ b/trunk/drivers/pcmcia/pcmcia_resource.c @@ -909,3 +909,65 @@ 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]; +}; + +/** + * 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, + void *priv_data), + void *priv_data) +{ + struct pcmcia_cfg_mem *cfg_mem; + tuple_t *tuple; + int ret = -ENODEV; + + cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL); + if (cfg_mem == NULL) + return -ENOMEM; + + 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) { + if (pcmcia_get_tuple_data(p_dev, tuple)) + goto next_entry; + + if (pcmcia_parse_tuple(p_dev, tuple, &cfg_mem->parse)) + goto next_entry; + + ret = conf_check(p_dev, &cfg_mem->parse.cftable_entry, + 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/trunk/drivers/pcmcia/socket_sysfs.c b/trunk/drivers/pcmcia/socket_sysfs.c index ff9a3bb3c88d..006a29e91d83 100644 --- a/trunk/drivers/pcmcia/socket_sysfs.c +++ b/trunk/drivers/pcmcia/socket_sysfs.c @@ -316,18 +316,27 @@ 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 >= CISTPL_MAX_CIS_SIZE) + if (count >= 0x200) return -EINVAL; if (!(s->state & SOCKET_PRESENT)) return -ENODEV; - error = pcmcia_replace_cis(s, buf, count); + 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); if (error) return -EIO; diff --git a/trunk/include/pcmcia/cistpl.h b/trunk/include/pcmcia/cistpl.h index 552a332ad714..b2eb914a18df 100644 --- a/trunk/include/pcmcia/cistpl.h +++ b/trunk/include/pcmcia/cistpl.h @@ -580,8 +580,14 @@ typedef struct cisinfo_t { #define CISTPL_MAX_CIS_SIZE 0x200 -int pcmcia_replace_cis(struct pcmcia_socket *s, - const u8 *data, const size_t len); +/* For ReplaceCIS */ +typedef struct cisdump_t { + u_int Length; + cisdata_t Data[CISTPL_MAX_CIS_SIZE]; +} cisdump_t; + + +int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis); /* don't use outside of PCMCIA core yet */ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple); @@ -607,4 +613,10 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned #define pcmcia_validate_cis(p_dev, info) \ pccard_validate_cis(p_dev->socket, p_dev->func, info) +int pcmcia_loop_config(struct pcmcia_device *p_dev, + int (*conf_check) (struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cf, + void *priv_data), + void *priv_data); + #endif /* LINUX_CISTPL_H */ diff --git a/trunk/include/pcmcia/ds.h b/trunk/include/pcmcia/ds.h index 2d36a4f80e5b..b316027c853d 100644 --- a/trunk/include/pcmcia/ds.h +++ b/trunk/include/pcmcia/ds.h @@ -68,12 +68,6 @@ typedef struct region_info_t { #define REGION_BAR_MASK 0xe000 #define REGION_BAR_SHIFT 13 -/* For ReplaceCIS */ -typedef struct cisdump_t { - u_int Length; - cisdata_t Data[CISTPL_MAX_CIS_SIZE]; -} cisdump_t; - typedef union ds_ioctl_arg_t { adjust_t adjust; config_info_t config; diff --git a/trunk/include/pcmcia/ss.h b/trunk/include/pcmcia/ss.h index e34bef0fc74f..ed919dd9bb5c 100644 --- a/trunk/include/pcmcia/ss.h +++ b/trunk/include/pcmcia/ss.h @@ -199,8 +199,8 @@ struct pcmcia_socket { io_window_t io[MAX_IO_WIN]; window_t win[MAX_WIN]; struct list_head cis_cache; - size_t fake_cis_len; - u8 *fake_cis; + u_int fake_cis_len; + char *fake_cis; struct list_head socket_list; struct completion socket_released;