diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2008-07-29 08:38:30 +0200 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2008-08-23 00:46:35 +0200 |
commit | a804b574e6c7236222593046fc2b1b8bd0298fce (patch) | |
tree | 63e8e0805e61337be328a2e25c439317bd96914a | |
parent | 6e86841d05f371b5b9b86ce76c02aaee83352298 (diff) |
pcmcia: add pcmcia_loop_config() helper
By calling pcmcia_loop_config(), a pcmcia 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.
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r-- | Documentation/pcmcia/driver-changes.txt | 6 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 62 | ||||
-rw-r--r-- | include/pcmcia/cistpl.h | 6 |
3 files changed, 74 insertions, 0 deletions
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt index 96f155e6875..059934363ca 100644 --- a/Documentation/pcmcia/driver-changes.txt +++ b/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/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 4884a18cf9e..9f054bc847f 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/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/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h index e2e10c1e9a0..b2eb914a18d 100644 --- a/include/pcmcia/cistpl.h +++ b/include/pcmcia/cistpl.h @@ -613,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 */ |