diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2008-08-02 08:28:43 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2008-08-22 19:21:28 -0400 |
commit | b54bf94bf91e4ca2a489eb02bca0424ddb55242a (patch) | |
tree | 4a5383d29173e24dd1fe71ce3ee4d010e60f391c /drivers/net/wireless | |
parent | 5fcd4da0090828bd34a1956cb322a483c6bf163c (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.c | 230 | ||||
-rw-r--r-- | drivers/net/wireless/atmel_cs.c | 123 | ||||
-rw-r--r-- | drivers/net/wireless/hostap/hostap_cs.c | 227 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco_cs.c | 176 | ||||
-rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 175 |
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) \ |
207 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 207 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
208 | 208 | ||
209 | struct airo_cs_config_data { | ||
210 | cistpl_cftable_entry_t dflt; | ||
211 | win_req_t req; | ||
212 | }; | ||
213 | |||
214 | static 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 | |||
209 | static int airo_config(struct pcmcia_device *link) | 297 | static 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 | ||
227 | static 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 | |||
227 | static int atmel_config(struct pcmcia_device *link) | 278 | static 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) \ |
533 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 533 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
534 | 534 | ||
535 | #define CFG_CHECK2(fn, retf) \ | ||
536 | do { int _ret = (retf); \ | ||
537 | if (_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 | |||
539 | struct prism2_config_data { | ||
540 | cistpl_cftable_entry_t dflt; | ||
541 | config_info_t conf; | ||
542 | }; | ||
543 | |||
544 | static 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 | |||
547 | static int prism2_config(struct pcmcia_device *link) | 629 | static 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 | ||
167 | struct orinoco_cs_config_data { | ||
168 | cistpl_cftable_entry_t dflt; | ||
169 | config_info_t conf; | ||
170 | }; | ||
171 | |||
172 | static 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 | |||
234 | next_entry: | ||
235 | pcmcia_disable_device(p_dev); | ||
236 | return -ENODEV; | ||
237 | }; | ||
238 | |||
167 | static int | 239 | static int |
168 | orinoco_cs_config(struct pcmcia_device *link) | 240 | orinoco_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 | ||
636 | struct spectrum_cs_config_data { | ||
637 | cistpl_cftable_entry_t dflt; | ||
638 | config_info_t conf; | ||
639 | }; | ||
640 | |||
641 | static 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 | |||
703 | next_entry: | ||
704 | pcmcia_disable_device(p_dev); | ||
705 | return -ENODEV; | ||
706 | }; | ||
707 | |||
636 | static int | 708 | static int |
637 | spectrum_cs_config(struct pcmcia_device *link) | 709 | spectrum_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 | ||