aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
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
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')
-rw-r--r--drivers/net/wireless/airo_cs.c230
-rw-r--r--drivers/net/wireless/atmel_cs.c123
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c227
-rw-r--r--drivers/net/wireless/orinoco_cs.c176
-rw-r--r--drivers/net/wireless/spectrum_cs.c175
5 files changed, 452 insertions, 479 deletions
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index f12355398fe7..4fbe811bebfc 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -206,126 +206,131 @@ static void airo_detach(struct pcmcia_device *link)
206#define CS_CHECK(fn, ret) \ 206#define CS_CHECK(fn, ret) \
207do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 207do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
208 208
209struct airo_cs_config_data {
210 cistpl_cftable_entry_t dflt;
211 win_req_t req;
212};
213
214static int airo_cs_config_check(struct pcmcia_device *p_dev,
215 cistpl_cftable_entry_t *cfg,
216 void *priv_data)
217{
218 struct airo_cs_config_data *cfg_mem = priv_data;
219
220 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
221 cfg_mem->dflt = *cfg;
222
223 if (cfg->index == 0)
224 return -ENODEV;
225
226 p_dev->conf.ConfigIndex = cfg->index;
227
228 /* Does this card need audio output? */
229 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
230 p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
231 p_dev->conf.Status = CCSR_AUDIO_ENA;
232 }
233
234 /* Use power settings for Vcc and Vpp if present */
235 /* Note that the CIS values need to be rescaled */
236 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
237 p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
238 else if (cfg_mem->dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
239 p_dev->conf.Vpp = cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
240
241 /* Do we need to allocate an interrupt? */
242 if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1)
243 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
244
245 /* IO window settings */
246 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
247 if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) {
248 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io;
249 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
250 if (!(io->flags & CISTPL_IO_8BIT))
251 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
252 if (!(io->flags & CISTPL_IO_16BIT))
253 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
254 p_dev->io.BasePort1 = io->win[0].base;
255 p_dev->io.NumPorts1 = io->win[0].len;
256 if (io->nwin > 1) {
257 p_dev->io.Attributes2 = p_dev->io.Attributes1;
258 p_dev->io.BasePort2 = io->win[1].base;
259 p_dev->io.NumPorts2 = io->win[1].len;
260 }
261 }
262
263 /* This reserves IO space but doesn't actually enable it */
264 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
265 return -ENODEV;
266
267 /*
268 Now set up a common memory window, if needed. There is room
269 in the struct pcmcia_device structure for one memory window handle,
270 but if the base addresses need to be saved, or if multiple
271 windows are needed, the info should go in the private data
272 structure for this device.
273
274 Note that the memory window base is a physical address, and
275 needs to be mapped to virtual space with ioremap() before it
276 is used.
277 */
278 if ((cfg->mem.nwin > 0) || (cfg_mem->dflt.mem.nwin > 0)) {
279 cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &cfg_mem->dflt.mem;
280 memreq_t map;
281 cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
282 cfg_mem->req.Base = mem->win[0].host_addr;
283 cfg_mem->req.Size = mem->win[0].len;
284 cfg_mem->req.AccessSpeed = 0;
285 if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0)
286 return -ENODEV;
287 map.Page = 0;
288 map.CardOffset = mem->win[0].card_addr;
289 if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
290 return -ENODEV;
291 }
292 /* If we got this far, we're cool! */
293 return 0;
294}
295
296
209static int airo_config(struct pcmcia_device *link) 297static int airo_config(struct pcmcia_device *link)
210{ 298{
211 tuple_t tuple;
212 cisparse_t parse;
213 local_info_t *dev; 299 local_info_t *dev;
300 struct airo_cs_config_data *cfg_mem;
214 int last_fn, last_ret; 301 int last_fn, last_ret;
215 u_char buf[64];
216 win_req_t req;
217 memreq_t map;
218 302
219 dev = link->priv; 303 dev = link->priv;
220 304
221 DEBUG(0, "airo_config(0x%p)\n", link); 305 DEBUG(0, "airo_config(0x%p)\n", link);
222 306
307 cfg_mem = kzalloc(sizeof(struct airo_cs_config_data), GFP_KERNEL);
308 if (!cfg_mem)
309 return -ENOMEM;
310
223 /* 311 /*
224 In this loop, we scan the CIS for configuration table entries, 312 * In this loop, we scan the CIS for configuration table
225 each of which describes a valid card configuration, including 313 * entries, each of which describes a valid card
226 voltage, IO window, memory window, and interrupt settings. 314 * configuration, including voltage, IO window, memory window,
227 315 * and interrupt settings.
228 We make no assumptions about the card to be configured: we use 316 *
229 just the information available in the CIS. In an ideal world, 317 * We make no assumptions about the card to be configured: we
230 this would work for any PCMCIA card, but it requires a complete 318 * use just the information available in the CIS. In an ideal
231 and accurate CIS. In practice, a driver usually "knows" most of 319 * world, this would work for any PCMCIA card, but it requires
232 these things without consulting the CIS, and most client drivers 320 * a complete and accurate CIS. In practice, a driver usually
233 will only use the CIS to fill in implementation-defined details. 321 * "knows" most of these things without consulting the CIS,
322 * and most client drivers will only use the CIS to fill in
323 * implementation-defined details.
324 */
325 last_ret = pcmcia_loop_config(link, airo_cs_config_check, cfg_mem);
326 if (last_ret)
327 goto failed;
328
329 /*
330 Allocate an interrupt line. Note that this does not assign a
331 handler to the interrupt, unless the 'Handler' member of the
332 irq structure is initialized.
234 */ 333 */
235 tuple.Attributes = 0;
236 tuple.TupleData = buf;
237 tuple.TupleDataMax = sizeof(buf);
238 tuple.TupleOffset = 0;
239 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
240 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
241 while (1) {
242 cistpl_cftable_entry_t dflt = { 0 };
243 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
244 if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
245 pcmcia_parse_tuple(link, &tuple, &parse) != 0)
246 goto next_entry;
247
248 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
249 if (cfg->index == 0) goto next_entry;
250 link->conf.ConfigIndex = cfg->index;
251
252 /* Does this card need audio output? */
253 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
254 link->conf.Attributes |= CONF_ENABLE_SPKR;
255 link->conf.Status = CCSR_AUDIO_ENA;
256 }
257
258 /* Use power settings for Vcc and Vpp if present */
259 /* Note that the CIS values need to be rescaled */
260 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
261 link->conf.Vpp =
262 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
263 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
264 link->conf.Vpp =
265 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
266
267 /* Do we need to allocate an interrupt? */
268 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
269 link->conf.Attributes |= CONF_ENABLE_IRQ;
270
271 /* IO window settings */
272 link->io.NumPorts1 = link->io.NumPorts2 = 0;
273 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
274 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
275 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
276 if (!(io->flags & CISTPL_IO_8BIT))
277 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
278 if (!(io->flags & CISTPL_IO_16BIT))
279 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
280 link->io.BasePort1 = io->win[0].base;
281 link->io.NumPorts1 = io->win[0].len;
282 if (io->nwin > 1) {
283 link->io.Attributes2 = link->io.Attributes1;
284 link->io.BasePort2 = io->win[1].base;
285 link->io.NumPorts2 = io->win[1].len;
286 }
287 }
288
289 /* This reserves IO space but doesn't actually enable it */
290 if (pcmcia_request_io(link, &link->io) != 0)
291 goto next_entry;
292
293 /*
294 Now set up a common memory window, if needed. There is room
295 in the struct pcmcia_device structure for one memory window handle,
296 but if the base addresses need to be saved, or if multiple
297 windows are needed, the info should go in the private data
298 structure for this device.
299
300 Note that the memory window base is a physical address, and
301 needs to be mapped to virtual space with ioremap() before it
302 is used.
303 */
304 if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
305 cistpl_mem_t *mem =
306 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
307 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
308 req.Base = mem->win[0].host_addr;
309 req.Size = mem->win[0].len;
310 req.AccessSpeed = 0;
311 if (pcmcia_request_window(&link, &req, &link->win) != 0)
312 goto next_entry;
313 map.Page = 0; map.CardOffset = mem->win[0].card_addr;
314 if (pcmcia_map_mem_page(link->win, &map) != 0)
315 goto next_entry;
316 }
317 /* If we got this far, we're cool! */
318 break;
319
320 next_entry:
321 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
322 }
323
324 /*
325 Allocate an interrupt line. Note that this does not assign a
326 handler to the interrupt, unless the 'Handler' member of the
327 irq structure is initialized.
328 */
329 if (link->conf.Attributes & CONF_ENABLE_IRQ) 334 if (link->conf.Attributes & CONF_ENABLE_IRQ)
330 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); 335 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
331 336
@@ -362,14 +367,17 @@ static int airo_config(struct pcmcia_device *link)
362 printk(" & 0x%04x-0x%04x", link->io.BasePort2, 367 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
363 link->io.BasePort2+link->io.NumPorts2-1); 368 link->io.BasePort2+link->io.NumPorts2-1);
364 if (link->win) 369 if (link->win)
365 printk(", mem 0x%06lx-0x%06lx", req.Base, 370 printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
366 req.Base+req.Size-1); 371 cfg_mem->req.Base+cfg_mem->req.Size-1);
367 printk("\n"); 372 printk("\n");
373 kfree(cfg_mem);
368 return 0; 374 return 0;
369 375
370 cs_failed: 376 cs_failed:
371 cs_error(link, last_fn, last_ret); 377 cs_error(link, last_fn, last_ret);
378 failed:
372 airo_release(link); 379 airo_release(link);
380 kfree(cfg_mem);
373 return -ENODEV; 381 return -ENODEV;
374} /* airo_config */ 382} /* airo_config */
375 383
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 12617cd0b78e..263c36f7ee22 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -224,25 +224,69 @@ static int card_present(void *arg)
224 return 0; 224 return 0;
225} 225}
226 226
227static int atmel_config_check(struct pcmcia_device *p_dev,
228 cistpl_cftable_entry_t *cfg,
229 void *priv_data)
230{
231 cistpl_cftable_entry_t *dflt = priv_data;
232
233 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
234 *dflt = *cfg;
235 if (cfg->index == 0)
236 return -ENODEV;
237 p_dev->conf.ConfigIndex = cfg->index;
238
239 /* Does this card need audio output? */
240 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
241 p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
242 p_dev->conf.Status = CCSR_AUDIO_ENA;
243 }
244
245 /* Use power settings for Vcc and Vpp if present */
246 /* Note that the CIS values need to be rescaled */
247 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
248 p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
249 else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
250 p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
251
252 /* Do we need to allocate an interrupt? */
253 if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
254 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
255
256 /* IO window settings */
257 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
258 if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
259 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
260 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
261 if (!(io->flags & CISTPL_IO_8BIT))
262 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
263 if (!(io->flags & CISTPL_IO_16BIT))
264 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
265 p_dev->io.BasePort1 = io->win[0].base;
266 p_dev->io.NumPorts1 = io->win[0].len;
267 if (io->nwin > 1) {
268 p_dev->io.Attributes2 = p_dev->io.Attributes1;
269 p_dev->io.BasePort2 = io->win[1].base;
270 p_dev->io.NumPorts2 = io->win[1].len;
271 }
272 }
273
274 /* This reserves IO space but doesn't actually enable it */
275 return pcmcia_request_io(p_dev, &p_dev->io);
276}
277
227static int atmel_config(struct pcmcia_device *link) 278static int atmel_config(struct pcmcia_device *link)
228{ 279{
229 tuple_t tuple;
230 cisparse_t parse;
231 local_info_t *dev; 280 local_info_t *dev;
232 int last_fn, last_ret; 281 int last_fn, last_ret;
233 u_char buf[64];
234 struct pcmcia_device_id *did; 282 struct pcmcia_device_id *did;
283 cistpl_cftable_entry_t dflt = { 0 };
235 284
236 dev = link->priv; 285 dev = link->priv;
237 did = handle_to_dev(link).driver_data; 286 did = handle_to_dev(link).driver_data;
238 287
239 DEBUG(0, "atmel_config(0x%p)\n", link); 288 DEBUG(0, "atmel_config(0x%p)\n", link);
240 289
241 tuple.Attributes = 0;
242 tuple.TupleData = buf;
243 tuple.TupleDataMax = sizeof(buf);
244 tuple.TupleOffset = 0;
245
246 /* 290 /*
247 In this loop, we scan the CIS for configuration table entries, 291 In this loop, we scan the CIS for configuration table entries,
248 each of which describes a valid card configuration, including 292 each of which describes a valid card configuration, including
@@ -255,66 +299,8 @@ static int atmel_config(struct pcmcia_device *link)
255 these things without consulting the CIS, and most client drivers 299 these things without consulting the CIS, and most client drivers
256 will only use the CIS to fill in implementation-defined details. 300 will only use the CIS to fill in implementation-defined details.
257 */ 301 */
258 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 302 if (pcmcia_loop_config(link, atmel_config_check, &dflt))
259 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); 303 goto failed;
260 while (1) {
261 cistpl_cftable_entry_t dflt = { 0 };
262 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
263 if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
264 pcmcia_parse_tuple(link, &tuple, &parse) != 0)
265 goto next_entry;
266
267 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
268 if (cfg->index == 0) goto next_entry;
269 link->conf.ConfigIndex = cfg->index;
270
271 /* Does this card need audio output? */
272 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
273 link->conf.Attributes |= CONF_ENABLE_SPKR;
274 link->conf.Status = CCSR_AUDIO_ENA;
275 }
276
277 /* Use power settings for Vcc and Vpp if present */
278 /* Note that the CIS values need to be rescaled */
279 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
280 link->conf.Vpp =
281 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
282 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
283 link->conf.Vpp =
284 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
285
286 /* Do we need to allocate an interrupt? */
287 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
288 link->conf.Attributes |= CONF_ENABLE_IRQ;
289
290 /* IO window settings */
291 link->io.NumPorts1 = link->io.NumPorts2 = 0;
292 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
293 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
294 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
295 if (!(io->flags & CISTPL_IO_8BIT))
296 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
297 if (!(io->flags & CISTPL_IO_16BIT))
298 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
299 link->io.BasePort1 = io->win[0].base;
300 link->io.NumPorts1 = io->win[0].len;
301 if (io->nwin > 1) {
302 link->io.Attributes2 = link->io.Attributes1;
303 link->io.BasePort2 = io->win[1].base;
304 link->io.NumPorts2 = io->win[1].len;
305 }
306 }
307
308 /* This reserves IO space but doesn't actually enable it */
309 if (pcmcia_request_io(link, &link->io) != 0)
310 goto next_entry;
311
312 /* If we got this far, we're cool! */
313 break;
314
315 next_entry:
316 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
317 }
318 304
319 /* 305 /*
320 Allocate an interrupt line. Note that this does not assign a 306 Allocate an interrupt line. Note that this does not assign a
@@ -360,6 +346,7 @@ static int atmel_config(struct pcmcia_device *link)
360 346
361 cs_failed: 347 cs_failed:
362 cs_error(link, last_fn, last_ret); 348 cs_error(link, last_fn, last_ret);
349 failed:
363 atmel_release(link); 350 atmel_release(link);
364 return -ENODEV; 351 return -ENODEV;
365} 352}
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 3b4e55cf33cd..3d914dde5de0 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -532,145 +532,134 @@ static void prism2_detach(struct pcmcia_device *link)
532#define CS_CHECK(fn, ret) \ 532#define CS_CHECK(fn, ret) \
533do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 533do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
534 534
535#define CFG_CHECK2(fn, retf) \
536do { int _ret = (retf); \
537if (_ret != 0) { \
538 PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", _ret); \
539 cs_error(link, fn, _ret); \
540 goto next_entry; \
541} \
542} while (0)
543
544 535
545/* run after a CARD_INSERTION event is received to configure the PCMCIA 536/* run after a CARD_INSERTION event is received to configure the PCMCIA
546 * socket and make the device available to the system */ 537 * socket and make the device available to the system */
538
539struct prism2_config_data {
540 cistpl_cftable_entry_t dflt;
541 config_info_t conf;
542};
543
544static int prism2_config_check(struct pcmcia_device *p_dev,
545 cistpl_cftable_entry_t *cfg,
546 void *priv_data)
547{
548 struct prism2_config_data *cfg_mem = priv_data;
549
550 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
551 cfg_mem->dflt = *cfg;
552 if (cfg->index == 0)
553 return -ENODEV;
554
555 p_dev->conf.ConfigIndex = cfg->index;
556 PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
557 "(default 0x%02X)\n", cfg->index, cfg_mem->dflt.index);
558
559 /* Does this card need audio output? */
560 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
561 p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
562 p_dev->conf.Status = CCSR_AUDIO_ENA;
563 }
564
565 /* Use power settings for Vcc and Vpp if present */
566 /* Note that the CIS values need to be rescaled */
567 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
568 if (cfg_mem->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
569 10000 && !ignore_cis_vcc) {
570 PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping"
571 " this entry\n");
572 return -ENODEV;
573 }
574 } else if (cfg_mem->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
575 if (cfg_mem->conf.Vcc != cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM] /
576 10000 && !ignore_cis_vcc) {
577 PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch "
578 "- skipping this entry\n");
579 return -ENODEV;
580 }
581 }
582
583 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
584 p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
585 else if (cfg_mem->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
586 p_dev->conf.Vpp = cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
587
588 /* Do we need to allocate an interrupt? */
589 if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1)
590 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
591 else if (!(p_dev->conf.Attributes & CONF_ENABLE_IRQ)) {
592 /* At least Compaq WL200 does not have IRQInfo1 set,
593 * but it does not work without interrupts.. */
594 printk(KERN_WARNING "Config has no IRQ info, but trying to "
595 "enable IRQ anyway..\n");
596 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
597 }
598
599 /* IO window settings */
600 PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
601 "cfg_mem->dflt.io.nwin=%d\n",
602 cfg->io.nwin, cfg_mem->dflt.io.nwin);
603 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
604 if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) {
605 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io;
606 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
607 PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, "
608 "io.base=0x%04x, len=%d\n", io->flags,
609 io->win[0].base, io->win[0].len);
610 if (!(io->flags & CISTPL_IO_8BIT))
611 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
612 if (!(io->flags & CISTPL_IO_16BIT))
613 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
614 p_dev->io.IOAddrLines = io->flags &
615 CISTPL_IO_LINES_MASK;
616 p_dev->io.BasePort1 = io->win[0].base;
617 p_dev->io.NumPorts1 = io->win[0].len;
618 if (io->nwin > 1) {
619 p_dev->io.Attributes2 = p_dev->io.Attributes1;
620 p_dev->io.BasePort2 = io->win[1].base;
621 p_dev->io.NumPorts2 = io->win[1].len;
622 }
623 }
624
625 /* This reserves IO space but doesn't actually enable it */
626 return pcmcia_request_io(p_dev, &p_dev->io);
627}
628
547static int prism2_config(struct pcmcia_device *link) 629static int prism2_config(struct pcmcia_device *link)
548{ 630{
549 struct net_device *dev; 631 struct net_device *dev;
550 struct hostap_interface *iface; 632 struct hostap_interface *iface;
633 struct prism2_config_data *cfg_mem;
551 local_info_t *local; 634 local_info_t *local;
552 int ret = 1; 635 int ret = 1;
553 tuple_t tuple;
554 cisparse_t *parse;
555 int last_fn, last_ret; 636 int last_fn, last_ret;
556 u_char buf[64];
557 config_info_t conf;
558 cistpl_cftable_entry_t dflt = { 0 };
559 struct hostap_cs_priv *hw_priv; 637 struct hostap_cs_priv *hw_priv;
560 638
561 PDEBUG(DEBUG_FLOW, "prism2_config()\n"); 639 PDEBUG(DEBUG_FLOW, "prism2_config()\n");
562 640
563 parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); 641 cfg_mem = kzalloc(sizeof(struct prism2_config_data), GFP_KERNEL);
642 if (!cfg_mem)
643 return -ENOMEM;
644
564 hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); 645 hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
565 if (parse == NULL || hw_priv == NULL) { 646 if (hw_priv == NULL) {
566 ret = -ENOMEM; 647 ret = -ENOMEM;
567 goto failed; 648 goto failed;
568 } 649 }
569 650
570 tuple.Attributes = 0;
571 tuple.TupleData = buf;
572 tuple.TupleDataMax = sizeof(buf);
573 tuple.TupleOffset = 0;
574
575 CS_CHECK(GetConfigurationInfo, 651 CS_CHECK(GetConfigurationInfo,
576 pcmcia_get_configuration_info(link, &conf)); 652 pcmcia_get_configuration_info(link, &cfg_mem->conf));
577 653
578 /* Look for an appropriate configuration table entry in the CIS */ 654 /* Look for an appropriate configuration table entry in the CIS */
579 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 655 last_ret = pcmcia_loop_config(link, prism2_config_check, cfg_mem);
580 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); 656 if (last_ret) {
581 for (;;) { 657 if (!ignore_cis_vcc)
582 cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); 658 printk(KERN_ERR "GetNextTuple(): No matching "
583 CFG_CHECK2(GetTupleData, 659 "CIS configuration. Maybe you need the "
584 pcmcia_get_tuple_data(link, &tuple)); 660 "ignore_cis_vcc=1 parameter.\n");
585 CFG_CHECK2(ParseTuple, 661 cs_error(link, RequestIO, last_ret);
586 pcmcia_parse_tuple(link, &tuple, parse)); 662 goto failed;
587
588 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
589 dflt = *cfg;
590 if (cfg->index == 0)
591 goto next_entry;
592 link->conf.ConfigIndex = cfg->index;
593 PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
594 "(default 0x%02X)\n", cfg->index, dflt.index);
595
596 /* Does this card need audio output? */
597 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
598 link->conf.Attributes |= CONF_ENABLE_SPKR;
599 link->conf.Status = CCSR_AUDIO_ENA;
600 }
601
602 /* Use power settings for Vcc and Vpp if present */
603 /* Note that the CIS values need to be rescaled */
604 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
605 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
606 10000 && !ignore_cis_vcc) {
607 PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping"
608 " this entry\n");
609 goto next_entry;
610 }
611 } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
612 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] /
613 10000 && !ignore_cis_vcc) {
614 PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch "
615 "- skipping this entry\n");
616 goto next_entry;
617 }
618 }
619
620 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
621 link->conf.Vpp =
622 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
623 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
624 link->conf.Vpp =
625 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
626
627 /* Do we need to allocate an interrupt? */
628 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
629 link->conf.Attributes |= CONF_ENABLE_IRQ;
630 else if (!(link->conf.Attributes & CONF_ENABLE_IRQ)) {
631 /* At least Compaq WL200 does not have IRQInfo1 set,
632 * but it does not work without interrupts.. */
633 printk("Config has no IRQ info, but trying to enable "
634 "IRQ anyway..\n");
635 link->conf.Attributes |= CONF_ENABLE_IRQ;
636 }
637
638 /* IO window settings */
639 PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
640 "dflt.io.nwin=%d\n",
641 cfg->io.nwin, dflt.io.nwin);
642 link->io.NumPorts1 = link->io.NumPorts2 = 0;
643 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
644 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
645 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
646 PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, "
647 "io.base=0x%04x, len=%d\n", io->flags,
648 io->win[0].base, io->win[0].len);
649 if (!(io->flags & CISTPL_IO_8BIT))
650 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
651 if (!(io->flags & CISTPL_IO_16BIT))
652 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
653 link->io.IOAddrLines = io->flags &
654 CISTPL_IO_LINES_MASK;
655 link->io.BasePort1 = io->win[0].base;
656 link->io.NumPorts1 = io->win[0].len;
657 if (io->nwin > 1) {
658 link->io.Attributes2 = link->io.Attributes1;
659 link->io.BasePort2 = io->win[1].base;
660 link->io.NumPorts2 = io->win[1].len;
661 }
662 }
663
664 /* This reserves IO space but doesn't actually enable it */
665 CFG_CHECK2(RequestIO,
666 pcmcia_request_io(link, &link->io));
667
668 /* This configuration table entry is OK */
669 break;
670
671 next_entry:
672 CS_CHECK(GetNextTuple,
673 pcmcia_get_next_tuple(link, &tuple));
674 } 663 }
675 664
676 /* Need to allocate net_device before requesting IRQ handler */ 665 /* Need to allocate net_device before requesting IRQ handler */
@@ -738,15 +727,15 @@ static int prism2_config(struct pcmcia_device *link)
738 if (ret == 0 && local->ddev) 727 if (ret == 0 && local->ddev)
739 strcpy(hw_priv->node.dev_name, local->ddev->name); 728 strcpy(hw_priv->node.dev_name, local->ddev->name);
740 } 729 }
741 kfree(parse); 730 kfree(cfg_mem);
742 return ret; 731 return ret;
743 732
744 cs_failed: 733 cs_failed:
745 cs_error(link, last_fn, last_ret); 734 cs_error(link, last_fn, last_ret);
746 735
747 failed: 736 failed:
748 kfree(parse);
749 kfree(hw_priv); 737 kfree(hw_priv);
738 kfree(cfg_mem);
750 prism2_release((u_long)link); 739 prism2_release((u_long)link);
751 return ret; 740 return ret;
752} 741}
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
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 98df9bc7836a..8e1951cfc152 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -633,23 +633,96 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
633 * device available to the system. 633 * device available to the system.
634 */ 634 */
635 635
636struct spectrum_cs_config_data {
637 cistpl_cftable_entry_t dflt;
638 config_info_t conf;
639};
640
641static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
642 cistpl_cftable_entry_t *cfg,
643 void *priv_data)
644{
645 struct spectrum_cs_config_data *cfg_mem = priv_data;
646
647 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
648 cfg_mem->dflt = *cfg;
649 if (cfg->index == 0)
650 goto next_entry;
651 p_dev->conf.ConfigIndex = cfg->index;
652
653 /* Use power settings for Vcc and Vpp if present */
654 /* Note that the CIS values need to be rescaled */
655 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
656 if (cfg_mem->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
657 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);
658 if (!ignore_cis_vcc)
659 goto next_entry;
660 }
661 } else if (cfg_mem->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
662 if (cfg_mem->conf.Vcc != cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
663 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);
664 if (!ignore_cis_vcc)
665 goto next_entry;
666 }
667 }
668
669 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
670 p_dev->conf.Vpp =
671 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
672 else if (cfg_mem->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
673 p_dev->conf.Vpp =
674 cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
675
676 /* Do we need to allocate an interrupt? */
677 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
678
679 /* IO window settings */
680 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
681 if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) {
682 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io;
683 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
684 if (!(io->flags & CISTPL_IO_8BIT))
685 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
686 if (!(io->flags & CISTPL_IO_16BIT))
687 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
688 p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
689 p_dev->io.BasePort1 = io->win[0].base;
690 p_dev->io.NumPorts1 = io->win[0].len;
691 if (io->nwin > 1) {
692 p_dev->io.Attributes2 = p_dev->io.Attributes1;
693 p_dev->io.BasePort2 = io->win[1].base;
694 p_dev->io.NumPorts2 = io->win[1].len;
695 }
696
697 /* This reserves IO space but doesn't actually enable it */
698 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
699 goto next_entry;
700 }
701 return 0;
702
703next_entry:
704 pcmcia_disable_device(p_dev);
705 return -ENODEV;
706};
707
636static int 708static int
637spectrum_cs_config(struct pcmcia_device *link) 709spectrum_cs_config(struct pcmcia_device *link)
638{ 710{
711 struct spectrum_cs_config_data *cfg_mem;
639 struct net_device *dev = link->priv; 712 struct net_device *dev = link->priv;
640 struct orinoco_private *priv = netdev_priv(dev); 713 struct orinoco_private *priv = netdev_priv(dev);
641 struct orinoco_pccard *card = priv->card; 714 struct orinoco_pccard *card = priv->card;
642 hermes_t *hw = &priv->hw; 715 hermes_t *hw = &priv->hw;
643 int last_fn, last_ret; 716 int last_fn, last_ret;
644 u_char buf[64];
645 config_info_t conf;
646 tuple_t tuple;
647 cisparse_t parse;
648 void __iomem *mem; 717 void __iomem *mem;
649 718
719 cfg_mem = kzalloc(sizeof(struct spectrum_cs_config_data), GFP_KERNEL);
720 if (!cfg_mem)
721 return -ENOMEM;
722
650 /* Look up the current Vcc */ 723 /* Look up the current Vcc */
651 CS_CHECK(GetConfigurationInfo, 724 CS_CHECK(GetConfigurationInfo,
652 pcmcia_get_configuration_info(link, &conf)); 725 pcmcia_get_configuration_info(link, &cfg_mem->conf));
653 726
654 /* 727 /*
655 * In this loop, we scan the CIS for configuration table 728 * In this loop, we scan the CIS for configuration table
@@ -665,94 +738,14 @@ spectrum_cs_config(struct pcmcia_device *link)
665 * and most client drivers will only use the CIS to fill in 738 * and most client drivers will only use the CIS to fill in
666 * implementation-defined details. 739 * implementation-defined details.
667 */ 740 */
668 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 741 last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, cfg_mem);
669 tuple.Attributes = 0; 742 if (last_ret) {
670 tuple.TupleData = buf; 743 if (!ignore_cis_vcc)
671 tuple.TupleDataMax = sizeof(buf);
672 tuple.TupleOffset = 0;
673 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
674 while (1) {
675 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
676 cistpl_cftable_entry_t dflt = { .index = 0 };
677
678 if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
679 || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
680 goto next_entry;
681
682 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
683 dflt = *cfg;
684 if (cfg->index == 0)
685 goto next_entry;
686 link->conf.ConfigIndex = cfg->index;
687
688 /* Use power settings for Vcc and Vpp if present */
689 /* Note that the CIS values need to be rescaled */
690 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
691 if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
692 DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
693 if (!ignore_cis_vcc)
694 goto next_entry;
695 }
696 } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
697 if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
698 DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
699 if(!ignore_cis_vcc)
700 goto next_entry;
701 }
702 }
703
704 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
705 link->conf.Vpp =
706 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
707 else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
708 link->conf.Vpp =
709 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
710
711 /* Do we need to allocate an interrupt? */
712 link->conf.Attributes |= CONF_ENABLE_IRQ;
713
714 /* IO window settings */
715 link->io.NumPorts1 = link->io.NumPorts2 = 0;
716 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
717 cistpl_io_t *io =
718 (cfg->io.nwin) ? &cfg->io : &dflt.io;
719 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
720 if (!(io->flags & CISTPL_IO_8BIT))
721 link->io.Attributes1 =
722 IO_DATA_PATH_WIDTH_16;
723 if (!(io->flags & CISTPL_IO_16BIT))
724 link->io.Attributes1 =
725 IO_DATA_PATH_WIDTH_8;
726 link->io.IOAddrLines =
727 io->flags & CISTPL_IO_LINES_MASK;
728 link->io.BasePort1 = io->win[0].base;
729 link->io.NumPorts1 = io->win[0].len;
730 if (io->nwin > 1) {
731 link->io.Attributes2 =
732 link->io.Attributes1;
733 link->io.BasePort2 = io->win[1].base;
734 link->io.NumPorts2 = io->win[1].len;
735 }
736
737 /* This reserves IO space but doesn't actually enable it */
738 if (pcmcia_request_io(link, &link->io) != 0)
739 goto next_entry;
740 }
741
742
743 /* If we got this far, we're cool! */
744
745 break;
746
747 next_entry:
748 pcmcia_disable_device(link);
749 last_ret = pcmcia_get_next_tuple(link, &tuple);
750 if (last_ret == CS_NO_MORE_ITEMS) {
751 printk(KERN_ERR PFX "GetNextTuple(): No matching " 744 printk(KERN_ERR PFX "GetNextTuple(): No matching "
752 "CIS configuration. Maybe you need the " 745 "CIS configuration. Maybe you need the "
753 "ignore_cis_vcc=1 parameter.\n"); 746 "ignore_cis_vcc=1 parameter.\n");
754 goto cs_failed; 747 cs_error(link, RequestIO, last_ret);
755 } 748 goto failed;
756 } 749 }
757 750
758 /* 751 /*
@@ -809,6 +802,7 @@ spectrum_cs_config(struct pcmcia_device *link)
809 link->irq.AssignedIRQ, link->io.BasePort1, 802 link->irq.AssignedIRQ, link->io.BasePort1,
810 link->io.BasePort1 + link->io.NumPorts1 - 1); 803 link->io.BasePort1 + link->io.NumPorts1 - 1);
811 804
805 kfree(cfg_mem);
812 return 0; 806 return 0;
813 807
814 cs_failed: 808 cs_failed:
@@ -816,6 +810,7 @@ spectrum_cs_config(struct pcmcia_device *link)
816 810
817 failed: 811 failed:
818 spectrum_cs_release(link); 812 spectrum_cs_release(link);
813 kfree(cfg_mem);
819 return -ENODEV; 814 return -ENODEV;
820} /* spectrum_cs_config */ 815} /* spectrum_cs_config */
821 816