* [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper
@ 2008-07-29 7:15 Dominik Brodowski
2008-07-29 7:21 ` [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers Dominik Brodowski
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Dominik Brodowski @ 2008-07-29 7:15 UTC (permalink / raw)
To: linux-pcmcia
Cc: Tejun Heo, Alan Cox, linux-ide, Marcel Holtmann, linux-bluetooth,
James E.J. Bottomley, linux-scsi, Karsten Keil, isdn4linux,
Jeff Garzik, netdev, Harald Welte, linux-parport, Russell King,
Ed Okerson, linux-serial
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>
---
Documentation/pcmcia/driver-changes.txt | 6 +++
drivers/pcmcia/pcmcia_resource.c | 57 +++++++++++++++++++++++++++++++
include/pcmcia/cistpl.h | 6 +++
3 files changed, 69 insertions(+), 0 deletions(-)
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>
---
Documentation/pcmcia/driver-changes.txt | 6 +++
drivers/pcmcia/pcmcia_resource.c | 63 +++++++++++++++++++++++++++++++
include/pcmcia/cistpl.h | 6 +++
3 files changed, 75 insertions(+), 0 deletions(-)
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 96f155e..44085c1 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 4884a18..0fa48aa 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -909,3 +909,66 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
pcmcia_release_window(p_dev->win);
}
EXPORT_SYMBOL(pcmcia_disable_device);
+
+
+/**
+ * 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.
+ */
+
+struct pcmcia_cfg_mem {
+ tuple_t tuple;
+ cisparse_t parse;
+ u8 buf[256];
+};
+
+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 552a332..9830b34 100644
--- a/include/pcmcia/cistpl.h
+++ b/include/pcmcia/cistpl.h
@@ -607,4 +607,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 */
--
1.5.4.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers
2008-07-29 7:15 [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Dominik Brodowski
@ 2008-07-29 7:21 ` Dominik Brodowski
2008-07-29 20:21 ` Larry Finger
[not found] ` <20080729072025.GH27385@comet.dominikbrodowski.net>
2008-07-29 21:16 ` [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Randy Dunlap
2 siblings, 1 reply; 5+ messages in thread
From: Dominik Brodowski @ 2008-07-29 7:21 UTC (permalink / raw)
To: linux-pcmcia; +Cc: Jeff Garzik, netdev
Use the config loop helper in (some) net pcmcia drivers.
CC: Jeff Garzik <jgarzik@pobox.com>
CC: <netdev@vger.kernel.org>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
drivers/net/pcmcia/axnet_cs.c | 71 ++++++++++++++-------------------
drivers/net/pcmcia/pcnet_cs.c | 79 ++++++++++++++++++--------------------
drivers/net/pcmcia/smc91c92_cs.c | 46 ++++++----------------
3 files changed, 80 insertions(+), 116 deletions(-)
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 3f682d4..04ece0b 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -284,58 +284,47 @@ static int try_io_port(struct pcmcia_device *link)
}
}
+static int axnet_configcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ void *priv_data)
+{
+ int i;
+ cistpl_io_t *io = &cfg->io;
+
+ if (cfg->index == 0 || cfg->io.nwin == 0)
+ return -ENODEV;
+
+ p_dev->conf.ConfigIndex = 0x05;
+ /* For multifunction cards, by convention, we configure the
+ network function with window 0, and serial with window 1 */
+ if (io->nwin > 1) {
+ i = (io->win[1].len > io->win[0].len);
+ p_dev->io.BasePort2 = io->win[1-i].base;
+ p_dev->io.NumPorts2 = io->win[1-i].len;
+ } else {
+ i = p_dev->io.NumPorts2 = 0;
+ }
+ p_dev->io.BasePort1 = io->win[i].base;
+ p_dev->io.NumPorts1 = io->win[i].len;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+ return try_io_port(p_dev);
+
+ return -ENODEV;
+}
+
static int axnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
axnet_dev_t *info = PRIV(dev);
- tuple_t tuple;
- cisparse_t parse;
int i, j, last_ret, last_fn;
- u_short buf[64];
DECLARE_MAC_BUF(mac);
DEBUG(0, "axnet_config(0x%p)\n", link);
- tuple.Attributes = 0;
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
-
/* don't trust the CIS on this; Linksys got it wrong */
link->conf.Present = 0x63;
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (last_ret == CS_SUCCESS) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_io_t *io = &(parse.cftable_entry.io);
-
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
- cfg->index == 0 || cfg->io.nwin == 0)
- goto next_entry;
-
- link->conf.ConfigIndex = 0x05;
- /* For multifunction cards, by convention, we configure the
- network function with window 0, and serial with window 1 */
- if (io->nwin > 1) {
- i = (io->win[1].len > io->win[0].len);
- link->io.BasePort2 = io->win[1-i].base;
- link->io.NumPorts2 = io->win[1-i].len;
- } else {
- i = link->io.NumPorts2 = 0;
- }
- link->io.BasePort1 = io->win[i].base;
- link->io.NumPorts1 = io->win[i].len;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
- last_ret = try_io_port(link);
- if (last_ret == CS_SUCCESS) break;
- }
- next_entry:
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- }
+ last_ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
if (last_ret != CS_SUCCESS) {
cs_error(link, RequestIO, last_ret);
goto failed;
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 2d4c4ad..7a9eeca 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -512,58 +512,53 @@ static int try_io_port(struct pcmcia_device *link)
}
}
+static int pcnet_confcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ void *priv_data)
+{
+ int *has_shmem = priv_data;
+ int i;
+ cistpl_io_t *io = &cfg->io;
+
+ if (cfg->index == 0 || cfg->io.nwin == 0)
+ return -EINVAL;
+
+ p_dev->conf.ConfigIndex = cfg->index;
+
+ /* For multifunction cards, by convention, we configure the
+ network function with window 0, and serial with window 1 */
+ if (io->nwin > 1) {
+ i = (io->win[1].len > io->win[0].len);
+ p_dev->io.BasePort2 = io->win[1-i].base;
+ p_dev->io.NumPorts2 = io->win[1-i].len;
+ } else {
+ i = p_dev->io.NumPorts2 = 0;
+ }
+
+ *has_shmem = ((cfg->mem.nwin == 1) &&
+ (cfg->mem.win[0].len >= 0x4000));
+ p_dev->io.BasePort1 = io->win[i].base;
+ p_dev->io.NumPorts1 = io->win[i].len;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+ return try_io_port(p_dev);
+
+ return 0;
+}
+
static int pcnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
pcnet_dev_t *info = PRIV(dev);
- tuple_t tuple;
- cisparse_t parse;
- int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
+ int last_ret, last_fn, start_pg, stop_pg, cm_offset;
int has_shmem = 0;
- u_short buf[64];
hw_info_t *local_hw_info;
DECLARE_MAC_BUF(mac);
DEBUG(0, "pcnet_config(0x%p)\n", link);
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (last_ret == CS_SUCCESS) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_io_t *io = &(parse.cftable_entry.io);
-
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
- cfg->index == 0 || cfg->io.nwin == 0)
- goto next_entry;
-
- link->conf.ConfigIndex = cfg->index;
- /* For multifunction cards, by convention, we configure the
- network function with window 0, and serial with window 1 */
- if (io->nwin > 1) {
- i = (io->win[1].len > io->win[0].len);
- link->io.BasePort2 = io->win[1-i].base;
- link->io.NumPorts2 = io->win[1-i].len;
- } else {
- i = link->io.NumPorts2 = 0;
- }
- has_shmem = ((cfg->mem.nwin == 1) &&
- (cfg->mem.win[0].len >= 0x4000));
- link->io.BasePort1 = io->win[i].base;
- link->io.NumPorts1 = io->win[i].len;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
- last_ret = try_io_port(link);
- if (last_ret == CS_SUCCESS) break;
- }
- next_entry:
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- }
- if (last_ret != CS_SUCCESS) {
+ last_ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
+ if (last_ret) {
cs_error(link, RequestIO, last_ret);
goto failed;
}
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 250eb19..9edd2d6 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -660,46 +660,26 @@ static int mot_setup(struct pcmcia_device *link)
/*====================================================================*/
+static int smc_configcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ void *priv_data)
+{
+ p_dev->conf.ConfigIndex = cf->index;
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+ return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
static int smc_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- struct smc_cfg_mem *cfg_mem;
- tuple_t *tuple;
- cisparse_t *parse;
- cistpl_cftable_entry_t *cf;
- u_char *buf;
int i;
- cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
- if (!cfg_mem)
- return CS_OUT_OF_RESOURCE;
-
- tuple = &cfg_mem->tuple;
- parse = &cfg_mem->parse;
- cf = &parse->cftable_entry;
- buf = cfg_mem->buf;
-
- tuple->Attributes = tuple->TupleOffset = 0;
- tuple->TupleData = (cisdata_t *)buf;
- tuple->TupleDataMax = 255;
- tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
link->io.NumPorts1 = 16;
- i = first_tuple(link, tuple, parse);
- while (i != CS_NO_MORE_ITEMS) {
- if (i == CS_SUCCESS) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
- }
- i = next_tuple(link, tuple, parse);
- }
- if (i == CS_SUCCESS)
- dev->base_addr = link->io.BasePort1;
+ i = pcmcia_loop_config(link, smc_configcheck, NULL);
+ if (!i)
+ dev->base_addr = link->io.BasePort1;
- kfree(cfg_mem);
return i;
}
--
1.5.4.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC] [PATCH 5/7] pcmcia: use pcmcia_loop_config in ISDN pcmcia drivers
[not found] ` <20080729072025.GH27385@comet.dominikbrodowski.net>
@ 2008-07-29 15:45 ` Karsten Keil
0 siblings, 0 replies; 5+ messages in thread
From: Karsten Keil @ 2008-07-29 15:45 UTC (permalink / raw)
To: Dominik Brodowski; +Cc: linux-pcmcia, isdn4linux, netdev
On Tue, Jul 29, 2008 at 09:20:25AM +0200, Dominik Brodowski wrote:
> Use the config loop helper in ISDN pcmcia drivers.
>
Acked-by: Karsten Keil <kkeil@suse.de>
> CC: isdn4linux@listserv.isdn4linux.de
> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
> ---
> drivers/isdn/hardware/avm/avm_cs.c | 80 ++++++++++-------------------------
> drivers/isdn/hisax/avma1_cs.c | 76 +++++++++-------------------------
> drivers/isdn/hisax/elsa_cs.c | 71 ++++++++++----------------------
> drivers/isdn/hisax/teles_cs.c | 71 ++++++++++----------------------
> 4 files changed, 87 insertions(+), 211 deletions(-)
>
> diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
> index a5b941c..7a1ead1 100644
> --- a/drivers/isdn/hardware/avm/avm_cs.c
> +++ b/drivers/isdn/hardware/avm/avm_cs.c
> @@ -154,78 +154,44 @@ static void avmcs_detach(struct pcmcia_device *link)
>
> ======================================================================*/
>
> -static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> +static int avmcs_configcheck(struct pcmcia_device *p_dev,
> + cistpl_cftable_entry_t *cf,
> + void *priv_data)
> {
> - int i = pcmcia_get_tuple_data(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return pcmcia_parse_tuple(handle, tuple, parse);
> -}
> -
> -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> -{
> - int i = pcmcia_get_first_tuple(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return get_tuple(handle, tuple, parse);
> -}
> -
> -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> -{
> - int i = pcmcia_get_next_tuple(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return get_tuple(handle, tuple, parse);
> + if (cf->io.nwin <= 0)
> + return -ENODEV;
> +
> + p_dev->conf.ConfigIndex = cf->index;
> + p_dev->io.BasePort1 = cf->io.win[0].base;
> + p_dev->io.NumPorts1 = cf->io.win[0].len;
> + p_dev->io.NumPorts2 = 0;
> + printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
> + p_dev->io.BasePort1,
> + p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
> + return pcmcia_request_io(p_dev, &p_dev->io);
> }
>
> static int avmcs_config(struct pcmcia_device *link)
> {
> - tuple_t tuple;
> - cisparse_t parse;
> - cistpl_cftable_entry_t *cf = &parse.cftable_entry;
> local_info_t *dev;
> int i;
> - u_char buf[64];
> char devname[128];
> int cardtype;
> int (*addcard)(unsigned int port, unsigned irq);
>
> dev = link->priv;
>
> - do {
> - devname[0] = 0;
> - if (link->prod_id[1])
> - strlcpy(devname, link->prod_id[1], sizeof(devname));
> -
> - /*
> - * find IO port
> - */
> - tuple.TupleData = (cisdata_t *)buf;
> - tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
> - tuple.Attributes = 0;
> - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
> - i = first_tuple(link, &tuple, &parse);
> - while (i == CS_SUCCESS) {
> - if (cf->io.nwin > 0) {
> - link->conf.ConfigIndex = cf->index;
> - link->io.BasePort1 = cf->io.win[0].base;
> - link->io.NumPorts1 = cf->io.win[0].len;
> - link->io.NumPorts2 = 0;
> - printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
> - link->io.BasePort1,
> - link->io.BasePort1+link->io.NumPorts1-1);
> - i = pcmcia_request_io(link, &link->io);
> - if (i == CS_SUCCESS) goto found_port;
> - }
> - i = next_tuple(link, &tuple, &parse);
> - }
> + devname[0] = 0;
> + if (link->prod_id[1])
> + strlcpy(devname, link->prod_id[1], sizeof(devname));
>
> -found_port:
> - if (i != CS_SUCCESS) {
> - cs_error(link, RequestIO, i);
> - break;
> - }
> + /*
> + * find IO port
> + */
> + if (pcmcia_loop_config(link, avmcs_configcheck, NULL))
> + return -ENODEV;
>
> + do {
> /*
> * allocate an interrupt line
> */
> diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
> index fc6cc2c..8142d9f 100644
> --- a/drivers/isdn/hisax/avma1_cs.c
> +++ b/drivers/isdn/hisax/avma1_cs.c
> @@ -174,38 +174,28 @@ static void avma1cs_detach(struct pcmcia_device *link)
>
> ======================================================================*/
>
> -static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> +static int avma1cs_configcheck(struct pcmcia_device *p_dev,
> + cistpl_cftable_entry_t *cf,
> + void *priv_data)
> {
> - int i = pcmcia_get_tuple_data(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return pcmcia_parse_tuple(handle, tuple, parse);
> + if (cf->io.nwin <= 0)
> + return -ENODEV;
> +
> + p_dev->conf.ConfigIndex = cf->index;
> + p_dev->io.BasePort1 = cf->io.win[0].base;
> + p_dev->io.NumPorts1 = cf->io.win[0].len;
> + p_dev->io.NumPorts2 = 0;
> + printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
> + p_dev->io.BasePort1,
> + p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
> + return pcmcia_request_io(p_dev, &p_dev->io);
> }
>
> -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> -{
> - int i = pcmcia_get_first_tuple(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return get_tuple(handle, tuple, parse);
> -}
> -
> -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> -{
> - int i = pcmcia_get_next_tuple(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return get_tuple(handle, tuple, parse);
> -}
>
> static int avma1cs_config(struct pcmcia_device *link)
> {
> - tuple_t tuple;
> - cisparse_t parse;
> - cistpl_cftable_entry_t *cf = &parse.cftable_entry;
> local_info_t *dev;
> int i;
> - u_char buf[64];
> char devname[128];
> IsdnCard_t icard;
> int busy = 0;
> @@ -214,40 +204,14 @@ static int avma1cs_config(struct pcmcia_device *link)
>
> DEBUG(0, "avma1cs_config(0x%p)\n", link);
>
> - do {
> - devname[0] = 0;
> - if (link->prod_id[1])
> - strlcpy(devname, link->prod_id[1], sizeof(devname));
> + devname[0] = 0;
> + if (link->prod_id[1])
> + strlcpy(devname, link->prod_id[1], sizeof(devname));
>
> - /*
> - * find IO port
> - */
> - tuple.TupleData = (cisdata_t *)buf;
> - tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
> - tuple.Attributes = 0;
> - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
> - i = first_tuple(link, &tuple, &parse);
> - while (i == CS_SUCCESS) {
> - if (cf->io.nwin > 0) {
> - link->conf.ConfigIndex = cf->index;
> - link->io.BasePort1 = cf->io.win[0].base;
> - link->io.NumPorts1 = cf->io.win[0].len;
> - link->io.NumPorts2 = 0;
> - printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
> - link->io.BasePort1,
> - link->io.BasePort1+link->io.NumPorts1 - 1);
> - i = pcmcia_request_io(link, &link->io);
> - if (i == CS_SUCCESS) goto found_port;
> - }
> - i = next_tuple(link, &tuple, &parse);
> - }
> + if (pcmcia_loop_config(link, avma1cs_configcheck, NULL))
> + return -ENODEV;
>
> -found_port:
> - if (i != CS_SUCCESS) {
> - cs_error(link, RequestIO, i);
> - break;
> - }
> -
> + do {
> /*
> * allocate an interrupt line
> */
> diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
> index db7e644..b85b07d 100644
> --- a/drivers/isdn/hisax/elsa_cs.c
> +++ b/drivers/isdn/hisax/elsa_cs.c
> @@ -203,68 +203,41 @@ static void elsa_cs_detach(struct pcmcia_device *link)
> device available to the system.
>
> ======================================================================*/
> -static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> -{
> - int i = pcmcia_get_tuple_data(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return pcmcia_parse_tuple(handle, tuple, parse);
> -}
>
> -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> +static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
> + cistpl_cftable_entry_t *cf,
> + void *priv_data)
> {
> - int i = pcmcia_get_first_tuple(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return get_tuple(handle, tuple, parse);
> -}
> + int j;
>
> -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> -{
> - int i = pcmcia_get_next_tuple(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return get_tuple(handle, tuple, parse);
> + if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
> + printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
> + p_dev->conf.ConfigIndex = cf->index;
> + p_dev->io.BasePort1 = cf->io.win[0].base;
> + if (!pcmcia_request_io(p_dev, &p_dev->io))
> + return 0;
> + } else {
> + printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
> + p_dev->conf.ConfigIndex = cf->index;
> + for (j = 0x2f0; j > 0x100; j -= 0x10) {
> + p_dev->io.BasePort1 = j;
> + if (!pcmcia_request_io(p_dev, &p_dev->io))
> + return 0;
> + }
> + }
> + return -ENODEV;
> }
>
> static int elsa_cs_config(struct pcmcia_device *link)
> {
> - tuple_t tuple;
> - cisparse_t parse;
> local_info_t *dev;
> - int i, j, last_fn;
> - u_short buf[128];
> - cistpl_cftable_entry_t *cf = &parse.cftable_entry;
> + int i, last_fn;
> IsdnCard_t icard;
>
> DEBUG(0, "elsa_config(0x%p)\n", link);
> dev = link->priv;
>
> - tuple.TupleData = (cisdata_t *)buf;
> - tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
> - tuple.Attributes = 0;
> - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
> - i = first_tuple(link, &tuple, &parse);
> - while (i == CS_SUCCESS) {
> - if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
> - printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
> - link->conf.ConfigIndex = cf->index;
> - link->io.BasePort1 = cf->io.win[0].base;
> - i = pcmcia_request_io(link, &link->io);
> - if (i == CS_SUCCESS) break;
> - } else {
> - printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
> - link->conf.ConfigIndex = cf->index;
> - for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
> - link->io.BasePort1 = j;
> - i = pcmcia_request_io(link, &link->io);
> - if (i == CS_SUCCESS) break;
> - }
> - break;
> - }
> - i = next_tuple(link, &tuple, &parse);
> - }
> -
> + i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
> if (i != CS_SUCCESS) {
> last_fn = RequestIO;
> goto cs_failed;
> diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
> index ab4bd45..fc4d024 100644
> --- a/drivers/isdn/hisax/teles_cs.c
> +++ b/drivers/isdn/hisax/teles_cs.c
> @@ -193,68 +193,41 @@ static void teles_detach(struct pcmcia_device *link)
> device available to the system.
>
> ======================================================================*/
> -static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> -{
> - int i = pcmcia_get_tuple_data(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return pcmcia_parse_tuple(handle, tuple, parse);
> -}
>
> -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> +static int teles_cs_configcheck(struct pcmcia_device *p_dev,
> + cistpl_cftable_entry_t *cf,
> + void *priv_data)
> {
> - int i = pcmcia_get_first_tuple(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return get_tuple(handle, tuple, parse);
> -}
> + int j;
>
> -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> - cisparse_t *parse)
> -{
> - int i = pcmcia_get_next_tuple(handle, tuple);
> - if (i != CS_SUCCESS) return i;
> - return get_tuple(handle, tuple, parse);
> + if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
> + printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
> + p_dev->conf.ConfigIndex = cf->index;
> + p_dev->io.BasePort1 = cf->io.win[0].base;
> + if (!pcmcia_request_io(p_dev, &p_dev->io))
> + return 0;
> + } else {
> + printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
> + p_dev->conf.ConfigIndex = cf->index;
> + for (j = 0x2f0; j > 0x100; j -= 0x10) {
> + p_dev->io.BasePort1 = j;
> + if (!pcmcia_request_io(p_dev, &p_dev->io))
> + return 0;
> + }
> + }
> + return -ENODEV;
> }
>
> static int teles_cs_config(struct pcmcia_device *link)
> {
> - tuple_t tuple;
> - cisparse_t parse;
> local_info_t *dev;
> - int i, j, last_fn;
> - u_short buf[128];
> - cistpl_cftable_entry_t *cf = &parse.cftable_entry;
> + int i, last_fn;
> IsdnCard_t icard;
>
> DEBUG(0, "teles_config(0x%p)\n", link);
> dev = link->priv;
>
> - tuple.TupleData = (cisdata_t *)buf;
> - tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
> - tuple.Attributes = 0;
> - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
> - i = first_tuple(link, &tuple, &parse);
> - while (i == CS_SUCCESS) {
> - if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
> - printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
> - link->conf.ConfigIndex = cf->index;
> - link->io.BasePort1 = cf->io.win[0].base;
> - i = pcmcia_request_io(link, &link->io);
> - if (i == CS_SUCCESS) break;
> - } else {
> - printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
> - link->conf.ConfigIndex = cf->index;
> - for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
> - link->io.BasePort1 = j;
> - i = pcmcia_request_io(link, &link->io);
> - if (i == CS_SUCCESS) break;
> - }
> - break;
> - }
> - i = next_tuple(link, &tuple, &parse);
> - }
> -
> + i = pcmcia_loop_config(link, teles_cs_configcheck, NULL);
> if (i != CS_SUCCESS) {
> last_fn = RequestIO;
> goto cs_failed;
> --
> 1.5.4.3
--
Karsten Keil
SuSE Labs
ISDN and VOIP development
SUSE LINUX Products GmbH, Maxfeldstr.5 90409 Nuernberg, GF: Markus Rex, HRB 16746 (AG Nuernberg)
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers
2008-07-29 7:21 ` [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers Dominik Brodowski
@ 2008-07-29 20:21 ` Larry Finger
0 siblings, 0 replies; 5+ messages in thread
From: Larry Finger @ 2008-07-29 20:21 UTC (permalink / raw)
To: Dominik Brodowski; +Cc: linux-pcmcia, Jeff Garzik, netdev
Dominik Brodowski wrote:
> Use the config loop helper in (some) net pcmcia drivers.
>
> CC: Jeff Garzik <jgarzik@pobox.com>
> CC: <netdev@vger.kernel.org>
> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
> ---
> drivers/net/pcmcia/axnet_cs.c | 71 ++++++++++++++-------------------
> drivers/net/pcmcia/pcnet_cs.c | 79 ++++++++++++++++++--------------------
> drivers/net/pcmcia/smc91c92_cs.c | 46 ++++++----------------
> 3 files changed, 80 insertions(+), 116 deletions(-)
ACK for pcnet_cs.c by Larry Finger <Larry.Finger@lwfinger.net>.
Tested with 2.6.27-rc1.
Larry
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper
2008-07-29 7:15 [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Dominik Brodowski
2008-07-29 7:21 ` [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers Dominik Brodowski
[not found] ` <20080729072025.GH27385@comet.dominikbrodowski.net>
@ 2008-07-29 21:16 ` Randy Dunlap
2 siblings, 0 replies; 5+ messages in thread
From: Randy Dunlap @ 2008-07-29 21:16 UTC (permalink / raw)
To: Dominik Brodowski
Cc: linux-pcmcia, Tejun Heo, Alan Cox, linux-ide, Marcel Holtmann,
linux-bluetooth, James E.J. Bottomley, linux-scsi, Karsten Keil,
isdn4linux, Jeff Garzik, netdev, Harald Welte, linux-parport,
Russell King, Ed Okerson, linux-serial
On Tue, 29 Jul 2008 09:15:39 +0200 Dominik Brodowski wrote:
> 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>
> ---
> Documentation/pcmcia/driver-changes.txt | 6 +++
> drivers/pcmcia/pcmcia_resource.c | 57 +++++++++++++++++++++++++++++++
> include/pcmcia/cistpl.h | 6 +++
> 3 files changed, 69 insertions(+), 0 deletions(-)
>
> 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>
> ---
> Documentation/pcmcia/driver-changes.txt | 6 +++
> drivers/pcmcia/pcmcia_resource.c | 63 +++++++++++++++++++++++++++++++
> include/pcmcia/cistpl.h | 6 +++
> 3 files changed, 75 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
> index 4884a18..0fa48aa 100644
> --- a/drivers/pcmcia/pcmcia_resource.c
> +++ b/drivers/pcmcia/pcmcia_resource.c
> @@ -909,3 +909,66 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
> pcmcia_release_window(p_dev->win);
> }
> EXPORT_SYMBOL(pcmcia_disable_device);
> +
> +
Hi,
One more comment here (sorry I missed it earlier):
The kernel-doc comment needs to immediately precede the function, so that
struct pcmcia_cfg_mem needs to be moved to before the kernel-doc block...
> +/**
> + * 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.
> + */
> +
> +struct pcmcia_cfg_mem {
> + tuple_t tuple;
> + cisparse_t parse;
> + u8 buf[256];
> +};
> +
> +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)
> +{
...
> +}
> +EXPORT_SYMBOL(pcmcia_loop_config);
---
~Randy
Linux Plumbers Conference, 17-19 September 2008, Portland, Oregon USA
http://linuxplumbersconf.org/
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-07-29 21:16 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-29 7:15 [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Dominik Brodowski
2008-07-29 7:21 ` [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers Dominik Brodowski
2008-07-29 20:21 ` Larry Finger
[not found] ` <20080729072025.GH27385@comet.dominikbrodowski.net>
2008-07-29 15:45 ` [RFC] [PATCH 5/7] pcmcia: use pcmcia_loop_config in ISDN " Karsten Keil
2008-07-29 21:16 ` [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Randy Dunlap
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).