aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco_cs.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2008-08-02 08:28:43 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2008-08-22 19:21:28 -0400
commitb54bf94bf91e4ca2a489eb02bca0424ddb55242a (patch)
tree4a5383d29173e24dd1fe71ce3ee4d010e60f391c /drivers/net/wireless/orinoco_cs.c
parent5fcd4da0090828bd34a1956cb322a483c6bf163c (diff)
pcmcia: use pcmcia_loop_config in net pcmcia drivers
Use the config loop helper in (some) net pcmcia drivers. CC: netdev@vger.kernel.org Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/net/wireless/orinoco_cs.c')
-rw-r--r--drivers/net/wireless/orinoco_cs.c176
1 files changed, 85 insertions, 91 deletions
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 1c216e015f64..473370c9e0d6 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -164,23 +164,96 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
164 last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ 164 last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
165 } while (0) 165 } while (0)
166 166
167struct orinoco_cs_config_data {
168 cistpl_cftable_entry_t dflt;
169 config_info_t conf;
170};
171
172static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
173 cistpl_cftable_entry_t *cfg,
174 void *priv_data)
175{
176 struct orinoco_cs_config_data *cfg_mem = priv_data;
177
178 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
179 cfg_mem->dflt = *cfg;
180 if (cfg->index == 0)
181 goto next_entry;
182 p_dev->conf.ConfigIndex = cfg->index;
183
184 /* Use power settings for Vcc and Vpp if present */
185 /* Note that the CIS values need to be rescaled */
186 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
187 if (cfg_mem->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
188 DEBUG(2, "spectrum_cs_config: Vcc mismatch (cfg_mem->conf.Vcc = %d, CIS = %d)\n", cfg_mem->conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
189 if (!ignore_cis_vcc)
190 goto next_entry;
191 }
192 } else if (cfg_mem->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
193 if (cfg_mem->conf.Vcc != cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
194 DEBUG(2, "spectrum_cs_config: Vcc mismatch (cfg_mem->conf.Vcc = %d, CIS = %d)\n", cfg_mem->conf.Vcc, cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
195 if (!ignore_cis_vcc)
196 goto next_entry;
197 }
198 }
199
200 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
201 p_dev->conf.Vpp =
202 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
203 else if (cfg_mem->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
204 p_dev->conf.Vpp =
205 cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
206
207 /* Do we need to allocate an interrupt? */
208 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
209
210 /* IO window settings */
211 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
212 if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) {
213 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io;
214 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
215 if (!(io->flags & CISTPL_IO_8BIT))
216 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
217 if (!(io->flags & CISTPL_IO_16BIT))
218 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
219 p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
220 p_dev->io.BasePort1 = io->win[0].base;
221 p_dev->io.NumPorts1 = io->win[0].len;
222 if (io->nwin > 1) {
223 p_dev->io.Attributes2 = p_dev->io.Attributes1;
224 p_dev->io.BasePort2 = io->win[1].base;
225 p_dev->io.NumPorts2 = io->win[1].len;
226 }
227
228 /* This reserves IO space but doesn't actually enable it */
229 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
230 goto next_entry;
231 }
232 return 0;
233
234next_entry:
235 pcmcia_disable_device(p_dev);
236 return -ENODEV;
237};
238
167static int 239static int
168orinoco_cs_config(struct pcmcia_device *link) 240orinoco_cs_config(struct pcmcia_device *link)
169{ 241{
242 struct orinoco_cs_config_data *cfg_mem;
170 struct net_device *dev = link->priv; 243 struct net_device *dev = link->priv;
171 struct orinoco_private *priv = netdev_priv(dev); 244 struct orinoco_private *priv = netdev_priv(dev);
172 struct orinoco_pccard *card = priv->card; 245 struct orinoco_pccard *card = priv->card;
173 hermes_t *hw = &priv->hw; 246 hermes_t *hw = &priv->hw;
174 int last_fn, last_ret; 247 int last_fn, last_ret;
175 u_char buf[64];
176 config_info_t conf;
177 tuple_t tuple;
178 cisparse_t parse;
179 void __iomem *mem; 248 void __iomem *mem;
180 249
250 cfg_mem = kzalloc(sizeof(struct orinoco_cs_config_data), GFP_KERNEL);
251 if (!cfg_mem)
252 return -ENOMEM;
253
181 /* Look up the current Vcc */ 254 /* Look up the current Vcc */
182 CS_CHECK(GetConfigurationInfo, 255 CS_CHECK(GetConfigurationInfo,
183 pcmcia_get_configuration_info(link, &conf)); 256 pcmcia_get_configuration_info(link, &cfg_mem->conf));
184 257
185 /* 258 /*
186 * In this loop, we scan the CIS for configuration table 259 * In this loop, we scan the CIS for configuration table
@@ -196,94 +269,14 @@ orinoco_cs_config(struct pcmcia_device *link)
196 * and most client drivers will only use the CIS to fill in 269 * and most client drivers will only use the CIS to fill in
197 * implementation-defined details. 270 * implementation-defined details.
198 */ 271 */
199 tuple.Attributes = 0; 272 last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, cfg_mem);
200 tuple.TupleData = buf; 273 if (last_ret) {
201 tuple.TupleDataMax = sizeof(buf); 274 if (!ignore_cis_vcc)
202 tuple.TupleOffset = 0;
203 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
204 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
205 while (1) {
206 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
207 cistpl_cftable_entry_t dflt = { .index = 0 };
208
209 if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
210 || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
211 goto next_entry;
212
213 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
214 dflt = *cfg;
215 if (cfg->index == 0)
216 goto next_entry;
217 link->conf.ConfigIndex = cfg->index;
218
219 /* Use power settings for Vcc and Vpp if present */
220 /* Note that the CIS values need to be rescaled */
221 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
222 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
223 DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
224 if (!ignore_cis_vcc)
225 goto next_entry;
226 }
227 } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
228 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
229 DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
230 if(!ignore_cis_vcc)
231 goto next_entry;
232 }
233 }
234
235 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
236 link->conf.Vpp =
237 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
238 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
239 link->conf.Vpp =
240 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
241
242 /* Do we need to allocate an interrupt? */
243 link->conf.Attributes |= CONF_ENABLE_IRQ;
244
245 /* IO window settings */
246 link->io.NumPorts1 = link->io.NumPorts2 = 0;
247 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
248 cistpl_io_t *io =
249 (cfg->io.nwin) ? &cfg->io : &dflt.io;
250 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
251 if (!(io->flags & CISTPL_IO_8BIT))
252 link->io.Attributes1 =
253 IO_DATA_PATH_WIDTH_16;
254 if (!(io->flags & CISTPL_IO_16BIT))
255 link->io.Attributes1 =
256 IO_DATA_PATH_WIDTH_8;
257 link->io.IOAddrLines =
258 io->flags & CISTPL_IO_LINES_MASK;
259 link->io.BasePort1 = io->win[0].base;
260 link->io.NumPorts1 = io->win[0].len;
261 if (io->nwin > 1) {
262 link->io.Attributes2 =
263 link->io.Attributes1;
264 link->io.BasePort2 = io->win[1].base;
265 link->io.NumPorts2 = io->win[1].len;
266 }
267
268 /* This reserves IO space but doesn't actually enable it */
269 if (pcmcia_request_io(link, &link->io) != 0)
270 goto next_entry;
271 }
272
273
274 /* If we got this far, we're cool! */
275
276 break;
277
278 next_entry:
279 pcmcia_disable_device(link);
280 last_ret = pcmcia_get_next_tuple(link, &tuple);
281 if (last_ret == CS_NO_MORE_ITEMS) {
282 printk(KERN_ERR PFX "GetNextTuple(): No matching " 275 printk(KERN_ERR PFX "GetNextTuple(): No matching "
283 "CIS configuration. Maybe you need the " 276 "CIS configuration. Maybe you need the "
284 "ignore_cis_vcc=1 parameter.\n"); 277 "ignore_cis_vcc=1 parameter.\n");
285 goto cs_failed; 278 cs_error(link, RequestIO, last_ret);
286 } 279 goto failed;
287 } 280 }
288 281
289 /* 282 /*
@@ -334,7 +327,7 @@ orinoco_cs_config(struct pcmcia_device *link)
334 "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id, 327 "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
335 link->irq.AssignedIRQ, link->io.BasePort1, 328 link->irq.AssignedIRQ, link->io.BasePort1,
336 link->io.BasePort1 + link->io.NumPorts1 - 1); 329 link->io.BasePort1 + link->io.NumPorts1 - 1);
337 330 kfree(cfg_mem);
338 return 0; 331 return 0;
339 332
340 cs_failed: 333 cs_failed:
@@ -342,6 +335,7 @@ orinoco_cs_config(struct pcmcia_device *link)
342 335
343 failed: 336 failed:
344 orinoco_cs_release(link); 337 orinoco_cs_release(link);
338 kfree(cfg_mem);
345 return -ENODEV; 339 return -ENODEV;
346} /* orinoco_cs_config */ 340} /* orinoco_cs_config */
347 341