diff options
Diffstat (limited to 'drivers/net/wireless/spectrum_cs.c')
-rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 162 |
1 files changed, 69 insertions, 93 deletions
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 67b26d3c3cd5..b0c71c3be467 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -235,6 +235,70 @@ static void spectrum_cs_detach(struct pcmcia_device *link) | |||
235 | * device available to the system. | 235 | * device available to the system. |
236 | */ | 236 | */ |
237 | 237 | ||
238 | static int spectrum_cs_config_check(struct pcmcia_device *p_dev, | ||
239 | cistpl_cftable_entry_t *cfg, | ||
240 | cistpl_cftable_entry_t *dflt, | ||
241 | unsigned int vcc, | ||
242 | void *priv_data) | ||
243 | { | ||
244 | if (cfg->index == 0) | ||
245 | goto next_entry; | ||
246 | |||
247 | /* Use power settings for Vcc and Vpp if present */ | ||
248 | /* Note that the CIS values need to be rescaled */ | ||
249 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
250 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
251 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
252 | if (!ignore_cis_vcc) | ||
253 | goto next_entry; | ||
254 | } | ||
255 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
256 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
257 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
258 | if (!ignore_cis_vcc) | ||
259 | goto next_entry; | ||
260 | } | ||
261 | } | ||
262 | |||
263 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
264 | p_dev->conf.Vpp = | ||
265 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
266 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
267 | p_dev->conf.Vpp = | ||
268 | dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
269 | |||
270 | /* Do we need to allocate an interrupt? */ | ||
271 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
272 | |||
273 | /* IO window settings */ | ||
274 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
275 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
276 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
277 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
278 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
279 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
280 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
281 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
282 | p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
283 | p_dev->io.BasePort1 = io->win[0].base; | ||
284 | p_dev->io.NumPorts1 = io->win[0].len; | ||
285 | if (io->nwin > 1) { | ||
286 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
287 | p_dev->io.BasePort2 = io->win[1].base; | ||
288 | p_dev->io.NumPorts2 = io->win[1].len; | ||
289 | } | ||
290 | |||
291 | /* This reserves IO space but doesn't actually enable it */ | ||
292 | if (pcmcia_request_io(p_dev, &p_dev->io) != 0) | ||
293 | goto next_entry; | ||
294 | } | ||
295 | return 0; | ||
296 | |||
297 | next_entry: | ||
298 | pcmcia_disable_device(p_dev); | ||
299 | return -ENODEV; | ||
300 | }; | ||
301 | |||
238 | static int | 302 | static int |
239 | spectrum_cs_config(struct pcmcia_device *link) | 303 | spectrum_cs_config(struct pcmcia_device *link) |
240 | { | 304 | { |
@@ -243,16 +307,8 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
243 | struct orinoco_pccard *card = priv->card; | 307 | struct orinoco_pccard *card = priv->card; |
244 | hermes_t *hw = &priv->hw; | 308 | hermes_t *hw = &priv->hw; |
245 | int last_fn, last_ret; | 309 | int last_fn, last_ret; |
246 | u_char buf[64]; | ||
247 | config_info_t conf; | ||
248 | tuple_t tuple; | ||
249 | cisparse_t parse; | ||
250 | void __iomem *mem; | 310 | void __iomem *mem; |
251 | 311 | ||
252 | /* Look up the current Vcc */ | ||
253 | CS_CHECK(GetConfigurationInfo, | ||
254 | pcmcia_get_configuration_info(link, &conf)); | ||
255 | |||
256 | /* | 312 | /* |
257 | * In this loop, we scan the CIS for configuration table | 313 | * In this loop, we scan the CIS for configuration table |
258 | * entries, each of which describes a valid card | 314 | * entries, each of which describes a valid card |
@@ -267,94 +323,14 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
267 | * and most client drivers will only use the CIS to fill in | 323 | * and most client drivers will only use the CIS to fill in |
268 | * implementation-defined details. | 324 | * implementation-defined details. |
269 | */ | 325 | */ |
270 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 326 | last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL); |
271 | tuple.Attributes = 0; | 327 | if (last_ret) { |
272 | tuple.TupleData = buf; | 328 | if (!ignore_cis_vcc) |
273 | tuple.TupleDataMax = sizeof(buf); | ||
274 | tuple.TupleOffset = 0; | ||
275 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
276 | while (1) { | ||
277 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | ||
278 | cistpl_cftable_entry_t dflt = { .index = 0 }; | ||
279 | |||
280 | if ( (pcmcia_get_tuple_data(link, &tuple) != 0) | ||
281 | || (pcmcia_parse_tuple(link, &tuple, &parse) != 0)) | ||
282 | goto next_entry; | ||
283 | |||
284 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
285 | dflt = *cfg; | ||
286 | if (cfg->index == 0) | ||
287 | goto next_entry; | ||
288 | link->conf.ConfigIndex = cfg->index; | ||
289 | |||
290 | /* Use power settings for Vcc and Vpp if present */ | ||
291 | /* Note that the CIS values need to be rescaled */ | ||
292 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
293 | if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
294 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
295 | if (!ignore_cis_vcc) | ||
296 | goto next_entry; | ||
297 | } | ||
298 | } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
299 | if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
300 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
301 | if(!ignore_cis_vcc) | ||
302 | goto next_entry; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
307 | link->conf.Vpp = | ||
308 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
309 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
310 | link->conf.Vpp = | ||
311 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
312 | |||
313 | /* Do we need to allocate an interrupt? */ | ||
314 | link->conf.Attributes |= CONF_ENABLE_IRQ; | ||
315 | |||
316 | /* IO window settings */ | ||
317 | link->io.NumPorts1 = link->io.NumPorts2 = 0; | ||
318 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | ||
319 | cistpl_io_t *io = | ||
320 | (cfg->io.nwin) ? &cfg->io : &dflt.io; | ||
321 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
322 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
323 | link->io.Attributes1 = | ||
324 | IO_DATA_PATH_WIDTH_16; | ||
325 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
326 | link->io.Attributes1 = | ||
327 | IO_DATA_PATH_WIDTH_8; | ||
328 | link->io.IOAddrLines = | ||
329 | io->flags & CISTPL_IO_LINES_MASK; | ||
330 | link->io.BasePort1 = io->win[0].base; | ||
331 | link->io.NumPorts1 = io->win[0].len; | ||
332 | if (io->nwin > 1) { | ||
333 | link->io.Attributes2 = | ||
334 | link->io.Attributes1; | ||
335 | link->io.BasePort2 = io->win[1].base; | ||
336 | link->io.NumPorts2 = io->win[1].len; | ||
337 | } | ||
338 | |||
339 | /* This reserves IO space but doesn't actually enable it */ | ||
340 | if (pcmcia_request_io(link, &link->io) != 0) | ||
341 | goto next_entry; | ||
342 | } | ||
343 | |||
344 | |||
345 | /* If we got this far, we're cool! */ | ||
346 | |||
347 | break; | ||
348 | |||
349 | next_entry: | ||
350 | pcmcia_disable_device(link); | ||
351 | last_ret = pcmcia_get_next_tuple(link, &tuple); | ||
352 | if (last_ret == CS_NO_MORE_ITEMS) { | ||
353 | printk(KERN_ERR PFX "GetNextTuple(): No matching " | 329 | printk(KERN_ERR PFX "GetNextTuple(): No matching " |
354 | "CIS configuration. Maybe you need the " | 330 | "CIS configuration. Maybe you need the " |
355 | "ignore_cis_vcc=1 parameter.\n"); | 331 | "ignore_cis_vcc=1 parameter.\n"); |
356 | goto cs_failed; | 332 | cs_error(link, RequestIO, last_ret); |
357 | } | 333 | goto failed; |
358 | } | 334 | } |
359 | 335 | ||
360 | /* | 336 | /* |