* [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 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
[parent not found: <20080729072025.GH27385@comet.dominikbrodowski.net>]
* 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 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).