diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/airo_cs.c | 222 | ||||
-rw-r--r-- | drivers/net/wireless/atmel_cs.c | 119 | ||||
-rw-r--r-- | drivers/net/wireless/hostap/hostap_cs.c | 213 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco_cs.c | 163 | ||||
-rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 162 |
5 files changed, 392 insertions, 487 deletions
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index f12355398fe..fac1526e49a 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c | |||
@@ -206,126 +206,123 @@ 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 | static int airo_cs_config_check(struct pcmcia_device *p_dev, | ||
210 | cistpl_cftable_entry_t *cfg, | ||
211 | cistpl_cftable_entry_t *dflt, | ||
212 | unsigned int vcc, | ||
213 | void *priv_data) | ||
214 | { | ||
215 | win_req_t *req = priv_data; | ||
216 | |||
217 | if (cfg->index == 0) | ||
218 | return -ENODEV; | ||
219 | |||
220 | /* Does this card need audio output? */ | ||
221 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
222 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
223 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
224 | } | ||
225 | |||
226 | /* Use power settings for Vcc and Vpp if present */ | ||
227 | /* Note that the CIS values need to be rescaled */ | ||
228 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
229 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
230 | else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
231 | p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
232 | |||
233 | /* Do we need to allocate an interrupt? */ | ||
234 | if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) | ||
235 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
236 | |||
237 | /* IO window settings */ | ||
238 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
239 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
240 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
241 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
242 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
243 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
244 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
245 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
246 | p_dev->io.BasePort1 = io->win[0].base; | ||
247 | p_dev->io.NumPorts1 = io->win[0].len; | ||
248 | if (io->nwin > 1) { | ||
249 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
250 | p_dev->io.BasePort2 = io->win[1].base; | ||
251 | p_dev->io.NumPorts2 = io->win[1].len; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | /* This reserves IO space but doesn't actually enable it */ | ||
256 | if (pcmcia_request_io(p_dev, &p_dev->io) != 0) | ||
257 | return -ENODEV; | ||
258 | |||
259 | /* | ||
260 | Now set up a common memory window, if needed. There is room | ||
261 | in the struct pcmcia_device structure for one memory window handle, | ||
262 | but if the base addresses need to be saved, or if multiple | ||
263 | windows are needed, the info should go in the private data | ||
264 | structure for this device. | ||
265 | |||
266 | Note that the memory window base is a physical address, and | ||
267 | needs to be mapped to virtual space with ioremap() before it | ||
268 | is used. | ||
269 | */ | ||
270 | if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { | ||
271 | cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; | ||
272 | memreq_t map; | ||
273 | req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; | ||
274 | req->Base = mem->win[0].host_addr; | ||
275 | req->Size = mem->win[0].len; | ||
276 | req->AccessSpeed = 0; | ||
277 | if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0) | ||
278 | return -ENODEV; | ||
279 | map.Page = 0; | ||
280 | map.CardOffset = mem->win[0].card_addr; | ||
281 | if (pcmcia_map_mem_page(p_dev->win, &map) != 0) | ||
282 | return -ENODEV; | ||
283 | } | ||
284 | /* If we got this far, we're cool! */ | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | |||
209 | static int airo_config(struct pcmcia_device *link) | 289 | static int airo_config(struct pcmcia_device *link) |
210 | { | 290 | { |
211 | tuple_t tuple; | ||
212 | cisparse_t parse; | ||
213 | local_info_t *dev; | 291 | local_info_t *dev; |
292 | win_req_t *req; | ||
214 | int last_fn, last_ret; | 293 | int last_fn, last_ret; |
215 | u_char buf[64]; | ||
216 | win_req_t req; | ||
217 | memreq_t map; | ||
218 | 294 | ||
219 | dev = link->priv; | 295 | dev = link->priv; |
220 | 296 | ||
221 | DEBUG(0, "airo_config(0x%p)\n", link); | 297 | DEBUG(0, "airo_config(0x%p)\n", link); |
222 | 298 | ||
299 | req = kzalloc(sizeof(win_req_t), GFP_KERNEL); | ||
300 | if (!req) | ||
301 | return -ENOMEM; | ||
302 | |||
303 | /* | ||
304 | * In this loop, we scan the CIS for configuration table | ||
305 | * entries, each of which describes a valid card | ||
306 | * configuration, including voltage, IO window, memory window, | ||
307 | * and interrupt settings. | ||
308 | * | ||
309 | * We make no assumptions about the card to be configured: we | ||
310 | * use just the information available in the CIS. In an ideal | ||
311 | * world, this would work for any PCMCIA card, but it requires | ||
312 | * a complete and accurate CIS. In practice, a driver usually | ||
313 | * "knows" most of these things without consulting the CIS, | ||
314 | * and most client drivers will only use the CIS to fill in | ||
315 | * implementation-defined details. | ||
316 | */ | ||
317 | last_ret = pcmcia_loop_config(link, airo_cs_config_check, req); | ||
318 | if (last_ret) | ||
319 | goto failed; | ||
320 | |||
223 | /* | 321 | /* |
224 | In this loop, we scan the CIS for configuration table entries, | 322 | Allocate an interrupt line. Note that this does not assign a |
225 | each of which describes a valid card configuration, including | 323 | handler to the interrupt, unless the 'Handler' member of the |
226 | voltage, IO window, memory window, and interrupt settings. | 324 | irq structure is initialized. |
227 | |||
228 | We make no assumptions about the card to be configured: we use | ||
229 | just the information available in the CIS. In an ideal world, | ||
230 | this would work for any PCMCIA card, but it requires a complete | ||
231 | and accurate CIS. In practice, a driver usually "knows" most of | ||
232 | these things without consulting the CIS, and most client drivers | ||
233 | will only use the CIS to fill in implementation-defined details. | ||
234 | */ | 325 | */ |
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) | 326 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
330 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); | 327 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
331 | 328 | ||
@@ -362,14 +359,17 @@ static int airo_config(struct pcmcia_device *link) | |||
362 | printk(" & 0x%04x-0x%04x", link->io.BasePort2, | 359 | printk(" & 0x%04x-0x%04x", link->io.BasePort2, |
363 | link->io.BasePort2+link->io.NumPorts2-1); | 360 | link->io.BasePort2+link->io.NumPorts2-1); |
364 | if (link->win) | 361 | if (link->win) |
365 | printk(", mem 0x%06lx-0x%06lx", req.Base, | 362 | printk(", mem 0x%06lx-0x%06lx", req->Base, |
366 | req.Base+req.Size-1); | 363 | req->Base+req->Size-1); |
367 | printk("\n"); | 364 | printk("\n"); |
365 | kfree(req); | ||
368 | return 0; | 366 | return 0; |
369 | 367 | ||
370 | cs_failed: | 368 | cs_failed: |
371 | cs_error(link, last_fn, last_ret); | 369 | cs_error(link, last_fn, last_ret); |
370 | failed: | ||
372 | airo_release(link); | 371 | airo_release(link); |
372 | kfree(req); | ||
373 | return -ENODEV; | 373 | return -ENODEV; |
374 | } /* airo_config */ | 374 | } /* airo_config */ |
375 | 375 | ||
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 12617cd0b78..4830d51900a 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c | |||
@@ -224,13 +224,58 @@ 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 | cistpl_cftable_entry_t *dflt, | ||
230 | unsigned int vcc, | ||
231 | void *priv_data) | ||
232 | { | ||
233 | if (cfg->index == 0) | ||
234 | return -ENODEV; | ||
235 | |||
236 | /* Does this card need audio output? */ | ||
237 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
238 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
239 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
240 | } | ||
241 | |||
242 | /* Use power settings for Vcc and Vpp if present */ | ||
243 | /* Note that the CIS values need to be rescaled */ | ||
244 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
245 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
246 | else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
247 | p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
248 | |||
249 | /* Do we need to allocate an interrupt? */ | ||
250 | if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) | ||
251 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
252 | |||
253 | /* IO window settings */ | ||
254 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
255 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
256 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
257 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
258 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
259 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
260 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
261 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
262 | p_dev->io.BasePort1 = io->win[0].base; | ||
263 | p_dev->io.NumPorts1 = io->win[0].len; | ||
264 | if (io->nwin > 1) { | ||
265 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
266 | p_dev->io.BasePort2 = io->win[1].base; | ||
267 | p_dev->io.NumPorts2 = io->win[1].len; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | /* This reserves IO space but doesn't actually enable it */ | ||
272 | return pcmcia_request_io(p_dev, &p_dev->io); | ||
273 | } | ||
274 | |||
227 | static int atmel_config(struct pcmcia_device *link) | 275 | static int atmel_config(struct pcmcia_device *link) |
228 | { | 276 | { |
229 | tuple_t tuple; | ||
230 | cisparse_t parse; | ||
231 | local_info_t *dev; | 277 | local_info_t *dev; |
232 | int last_fn, last_ret; | 278 | int last_fn, last_ret; |
233 | u_char buf[64]; | ||
234 | struct pcmcia_device_id *did; | 279 | struct pcmcia_device_id *did; |
235 | 280 | ||
236 | dev = link->priv; | 281 | dev = link->priv; |
@@ -238,11 +283,6 @@ static int atmel_config(struct pcmcia_device *link) | |||
238 | 283 | ||
239 | DEBUG(0, "atmel_config(0x%p)\n", link); | 284 | DEBUG(0, "atmel_config(0x%p)\n", link); |
240 | 285 | ||
241 | tuple.Attributes = 0; | ||
242 | tuple.TupleData = buf; | ||
243 | tuple.TupleDataMax = sizeof(buf); | ||
244 | tuple.TupleOffset = 0; | ||
245 | |||
246 | /* | 286 | /* |
247 | In this loop, we scan the CIS for configuration table entries, | 287 | In this loop, we scan the CIS for configuration table entries, |
248 | each of which describes a valid card configuration, including | 288 | each of which describes a valid card configuration, including |
@@ -255,66 +295,8 @@ static int atmel_config(struct pcmcia_device *link) | |||
255 | these things without consulting the CIS, and most client drivers | 295 | these things without consulting the CIS, and most client drivers |
256 | will only use the CIS to fill in implementation-defined details. | 296 | will only use the CIS to fill in implementation-defined details. |
257 | */ | 297 | */ |
258 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 298 | if (pcmcia_loop_config(link, atmel_config_check, NULL)) |
259 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 299 | 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 | 300 | ||
319 | /* | 301 | /* |
320 | Allocate an interrupt line. Note that this does not assign a | 302 | Allocate an interrupt line. Note that this does not assign a |
@@ -360,6 +342,7 @@ static int atmel_config(struct pcmcia_device *link) | |||
360 | 342 | ||
361 | cs_failed: | 343 | cs_failed: |
362 | cs_error(link, last_fn, last_ret); | 344 | cs_error(link, last_fn, last_ret); |
345 | failed: | ||
363 | atmel_release(link); | 346 | atmel_release(link); |
364 | return -ENODEV; | 347 | return -ENODEV; |
365 | } | 348 | } |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 3b4e55cf33c..c768d42d517 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -532,145 +532,118 @@ 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 | static int prism2_config_check(struct pcmcia_device *p_dev, | ||
540 | cistpl_cftable_entry_t *cfg, | ||
541 | cistpl_cftable_entry_t *dflt, | ||
542 | unsigned int vcc, | ||
543 | void *priv_data) | ||
544 | { | ||
545 | if (cfg->index == 0) | ||
546 | return -ENODEV; | ||
547 | |||
548 | PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " | ||
549 | "(default 0x%02X)\n", cfg->index, dflt->index); | ||
550 | |||
551 | /* Does this card need audio output? */ | ||
552 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
553 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
554 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
555 | } | ||
556 | |||
557 | /* Use power settings for Vcc and Vpp if present */ | ||
558 | /* Note that the CIS values need to be rescaled */ | ||
559 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
560 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / | ||
561 | 10000 && !ignore_cis_vcc) { | ||
562 | PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping" | ||
563 | " this entry\n"); | ||
564 | return -ENODEV; | ||
565 | } | ||
566 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
567 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / | ||
568 | 10000 && !ignore_cis_vcc) { | ||
569 | PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch " | ||
570 | "- skipping this entry\n"); | ||
571 | return -ENODEV; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
576 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
577 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
578 | p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
579 | |||
580 | /* Do we need to allocate an interrupt? */ | ||
581 | if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) | ||
582 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
583 | else if (!(p_dev->conf.Attributes & CONF_ENABLE_IRQ)) { | ||
584 | /* At least Compaq WL200 does not have IRQInfo1 set, | ||
585 | * but it does not work without interrupts.. */ | ||
586 | printk(KERN_WARNING "Config has no IRQ info, but trying to " | ||
587 | "enable IRQ anyway..\n"); | ||
588 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
589 | } | ||
590 | |||
591 | /* IO window settings */ | ||
592 | PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " | ||
593 | "dflt->io.nwin=%d\n", | ||
594 | cfg->io.nwin, dflt->io.nwin); | ||
595 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
596 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
597 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
598 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
599 | PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " | ||
600 | "io.base=0x%04x, len=%d\n", io->flags, | ||
601 | io->win[0].base, io->win[0].len); | ||
602 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
603 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
604 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
605 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
606 | p_dev->io.IOAddrLines = io->flags & | ||
607 | CISTPL_IO_LINES_MASK; | ||
608 | p_dev->io.BasePort1 = io->win[0].base; | ||
609 | p_dev->io.NumPorts1 = io->win[0].len; | ||
610 | if (io->nwin > 1) { | ||
611 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
612 | p_dev->io.BasePort2 = io->win[1].base; | ||
613 | p_dev->io.NumPorts2 = io->win[1].len; | ||
614 | } | ||
615 | } | ||
616 | |||
617 | /* This reserves IO space but doesn't actually enable it */ | ||
618 | return pcmcia_request_io(p_dev, &p_dev->io); | ||
619 | } | ||
620 | |||
547 | static int prism2_config(struct pcmcia_device *link) | 621 | static int prism2_config(struct pcmcia_device *link) |
548 | { | 622 | { |
549 | struct net_device *dev; | 623 | struct net_device *dev; |
550 | struct hostap_interface *iface; | 624 | struct hostap_interface *iface; |
551 | local_info_t *local; | 625 | local_info_t *local; |
552 | int ret = 1; | 626 | int ret = 1; |
553 | tuple_t tuple; | ||
554 | cisparse_t *parse; | ||
555 | int last_fn, last_ret; | 627 | 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; | 628 | struct hostap_cs_priv *hw_priv; |
560 | 629 | ||
561 | PDEBUG(DEBUG_FLOW, "prism2_config()\n"); | 630 | PDEBUG(DEBUG_FLOW, "prism2_config()\n"); |
562 | 631 | ||
563 | parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); | ||
564 | hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); | 632 | hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); |
565 | if (parse == NULL || hw_priv == NULL) { | 633 | if (hw_priv == NULL) { |
566 | ret = -ENOMEM; | 634 | ret = -ENOMEM; |
567 | goto failed; | 635 | goto failed; |
568 | } | 636 | } |
569 | 637 | ||
570 | tuple.Attributes = 0; | ||
571 | tuple.TupleData = buf; | ||
572 | tuple.TupleDataMax = sizeof(buf); | ||
573 | tuple.TupleOffset = 0; | ||
574 | |||
575 | CS_CHECK(GetConfigurationInfo, | ||
576 | pcmcia_get_configuration_info(link, &conf)); | ||
577 | |||
578 | /* Look for an appropriate configuration table entry in the CIS */ | 638 | /* Look for an appropriate configuration table entry in the CIS */ |
579 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 639 | last_ret = pcmcia_loop_config(link, prism2_config_check, NULL); |
580 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 640 | if (last_ret) { |
581 | for (;;) { | 641 | if (!ignore_cis_vcc) |
582 | cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); | 642 | printk(KERN_ERR "GetNextTuple(): No matching " |
583 | CFG_CHECK2(GetTupleData, | 643 | "CIS configuration. Maybe you need the " |
584 | pcmcia_get_tuple_data(link, &tuple)); | 644 | "ignore_cis_vcc=1 parameter.\n"); |
585 | CFG_CHECK2(ParseTuple, | 645 | cs_error(link, RequestIO, last_ret); |
586 | pcmcia_parse_tuple(link, &tuple, parse)); | 646 | 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 | } | 647 | } |
675 | 648 | ||
676 | /* Need to allocate net_device before requesting IRQ handler */ | 649 | /* Need to allocate net_device before requesting IRQ handler */ |
@@ -738,14 +711,12 @@ static int prism2_config(struct pcmcia_device *link) | |||
738 | if (ret == 0 && local->ddev) | 711 | if (ret == 0 && local->ddev) |
739 | strcpy(hw_priv->node.dev_name, local->ddev->name); | 712 | strcpy(hw_priv->node.dev_name, local->ddev->name); |
740 | } | 713 | } |
741 | kfree(parse); | ||
742 | return ret; | 714 | return ret; |
743 | 715 | ||
744 | cs_failed: | 716 | cs_failed: |
745 | cs_error(link, last_fn, last_ret); | 717 | cs_error(link, last_fn, last_ret); |
746 | 718 | ||
747 | failed: | 719 | failed: |
748 | kfree(parse); | ||
749 | kfree(hw_priv); | 720 | kfree(hw_priv); |
750 | prism2_release((u_long)link); | 721 | prism2_release((u_long)link); |
751 | return ret; | 722 | return ret; |
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 1c216e015f6..c7b57d9d499 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -164,6 +164,70 @@ 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 | static int orinoco_cs_config_check(struct pcmcia_device *p_dev, | ||
168 | cistpl_cftable_entry_t *cfg, | ||
169 | cistpl_cftable_entry_t *dflt, | ||
170 | unsigned int vcc, | ||
171 | void *priv_data) | ||
172 | { | ||
173 | if (cfg->index == 0) | ||
174 | goto next_entry; | ||
175 | |||
176 | /* Use power settings for Vcc and Vpp if present */ | ||
177 | /* Note that the CIS values need to be rescaled */ | ||
178 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
179 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
180 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
181 | if (!ignore_cis_vcc) | ||
182 | goto next_entry; | ||
183 | } | ||
184 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
185 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
186 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
187 | if (!ignore_cis_vcc) | ||
188 | goto next_entry; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
193 | p_dev->conf.Vpp = | ||
194 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
195 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
196 | p_dev->conf.Vpp = | ||
197 | dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
198 | |||
199 | /* Do we need to allocate an interrupt? */ | ||
200 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
201 | |||
202 | /* IO window settings */ | ||
203 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
204 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
205 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
206 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
207 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
208 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
209 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
210 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
211 | p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
212 | p_dev->io.BasePort1 = io->win[0].base; | ||
213 | p_dev->io.NumPorts1 = io->win[0].len; | ||
214 | if (io->nwin > 1) { | ||
215 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
216 | p_dev->io.BasePort2 = io->win[1].base; | ||
217 | p_dev->io.NumPorts2 = io->win[1].len; | ||
218 | } | ||
219 | |||
220 | /* This reserves IO space but doesn't actually enable it */ | ||
221 | if (pcmcia_request_io(p_dev, &p_dev->io) != 0) | ||
222 | goto next_entry; | ||
223 | } | ||
224 | return 0; | ||
225 | |||
226 | next_entry: | ||
227 | pcmcia_disable_device(p_dev); | ||
228 | return -ENODEV; | ||
229 | }; | ||
230 | |||
167 | static int | 231 | static int |
168 | orinoco_cs_config(struct pcmcia_device *link) | 232 | orinoco_cs_config(struct pcmcia_device *link) |
169 | { | 233 | { |
@@ -172,16 +236,8 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
172 | struct orinoco_pccard *card = priv->card; | 236 | struct orinoco_pccard *card = priv->card; |
173 | hermes_t *hw = &priv->hw; | 237 | hermes_t *hw = &priv->hw; |
174 | int last_fn, last_ret; | 238 | 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; | 239 | void __iomem *mem; |
180 | 240 | ||
181 | /* Look up the current Vcc */ | ||
182 | CS_CHECK(GetConfigurationInfo, | ||
183 | pcmcia_get_configuration_info(link, &conf)); | ||
184 | |||
185 | /* | 241 | /* |
186 | * In this loop, we scan the CIS for configuration table | 242 | * In this loop, we scan the CIS for configuration table |
187 | * entries, each of which describes a valid card | 243 | * entries, each of which describes a valid card |
@@ -196,94 +252,14 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
196 | * and most client drivers will only use the CIS to fill in | 252 | * and most client drivers will only use the CIS to fill in |
197 | * implementation-defined details. | 253 | * implementation-defined details. |
198 | */ | 254 | */ |
199 | tuple.Attributes = 0; | 255 | last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL); |
200 | tuple.TupleData = buf; | 256 | if (last_ret) { |
201 | tuple.TupleDataMax = sizeof(buf); | 257 | 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 " | 258 | printk(KERN_ERR PFX "GetNextTuple(): No matching " |
283 | "CIS configuration. Maybe you need the " | 259 | "CIS configuration. Maybe you need the " |
284 | "ignore_cis_vcc=1 parameter.\n"); | 260 | "ignore_cis_vcc=1 parameter.\n"); |
285 | goto cs_failed; | 261 | cs_error(link, RequestIO, last_ret); |
286 | } | 262 | goto failed; |
287 | } | 263 | } |
288 | 264 | ||
289 | /* | 265 | /* |
@@ -334,7 +310,6 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
334 | "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id, | 310 | "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id, |
335 | link->irq.AssignedIRQ, link->io.BasePort1, | 311 | link->irq.AssignedIRQ, link->io.BasePort1, |
336 | link->io.BasePort1 + link->io.NumPorts1 - 1); | 312 | link->io.BasePort1 + link->io.NumPorts1 - 1); |
337 | |||
338 | return 0; | 313 | return 0; |
339 | 314 | ||
340 | cs_failed: | 315 | cs_failed: |
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 98df9bc7836..d7e9d9c3042 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -633,6 +633,70 @@ 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 | static int spectrum_cs_config_check(struct pcmcia_device *p_dev, | ||
637 | cistpl_cftable_entry_t *cfg, | ||
638 | cistpl_cftable_entry_t *dflt, | ||
639 | unsigned int vcc, | ||
640 | void *priv_data) | ||
641 | { | ||
642 | if (cfg->index == 0) | ||
643 | goto next_entry; | ||
644 | |||
645 | /* Use power settings for Vcc and Vpp if present */ | ||
646 | /* Note that the CIS values need to be rescaled */ | ||
647 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
648 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
649 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
650 | if (!ignore_cis_vcc) | ||
651 | goto next_entry; | ||
652 | } | ||
653 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
654 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
655 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
656 | if (!ignore_cis_vcc) | ||
657 | goto next_entry; | ||
658 | } | ||
659 | } | ||
660 | |||
661 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
662 | p_dev->conf.Vpp = | ||
663 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
664 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
665 | p_dev->conf.Vpp = | ||
666 | dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
667 | |||
668 | /* Do we need to allocate an interrupt? */ | ||
669 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
670 | |||
671 | /* IO window settings */ | ||
672 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
673 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
674 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
675 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
676 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
677 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
678 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
679 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
680 | p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
681 | p_dev->io.BasePort1 = io->win[0].base; | ||
682 | p_dev->io.NumPorts1 = io->win[0].len; | ||
683 | if (io->nwin > 1) { | ||
684 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
685 | p_dev->io.BasePort2 = io->win[1].base; | ||
686 | p_dev->io.NumPorts2 = io->win[1].len; | ||
687 | } | ||
688 | |||
689 | /* This reserves IO space but doesn't actually enable it */ | ||
690 | if (pcmcia_request_io(p_dev, &p_dev->io) != 0) | ||
691 | goto next_entry; | ||
692 | } | ||
693 | return 0; | ||
694 | |||
695 | next_entry: | ||
696 | pcmcia_disable_device(p_dev); | ||
697 | return -ENODEV; | ||
698 | }; | ||
699 | |||
636 | static int | 700 | static int |
637 | spectrum_cs_config(struct pcmcia_device *link) | 701 | spectrum_cs_config(struct pcmcia_device *link) |
638 | { | 702 | { |
@@ -641,16 +705,8 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
641 | struct orinoco_pccard *card = priv->card; | 705 | struct orinoco_pccard *card = priv->card; |
642 | hermes_t *hw = &priv->hw; | 706 | hermes_t *hw = &priv->hw; |
643 | int last_fn, last_ret; | 707 | 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; | 708 | void __iomem *mem; |
649 | 709 | ||
650 | /* Look up the current Vcc */ | ||
651 | CS_CHECK(GetConfigurationInfo, | ||
652 | pcmcia_get_configuration_info(link, &conf)); | ||
653 | |||
654 | /* | 710 | /* |
655 | * In this loop, we scan the CIS for configuration table | 711 | * In this loop, we scan the CIS for configuration table |
656 | * entries, each of which describes a valid card | 712 | * entries, each of which describes a valid card |
@@ -665,94 +721,14 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
665 | * and most client drivers will only use the CIS to fill in | 721 | * and most client drivers will only use the CIS to fill in |
666 | * implementation-defined details. | 722 | * implementation-defined details. |
667 | */ | 723 | */ |
668 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 724 | last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL); |
669 | tuple.Attributes = 0; | 725 | if (last_ret) { |
670 | tuple.TupleData = buf; | 726 | 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 " | 727 | printk(KERN_ERR PFX "GetNextTuple(): No matching " |
752 | "CIS configuration. Maybe you need the " | 728 | "CIS configuration. Maybe you need the " |
753 | "ignore_cis_vcc=1 parameter.\n"); | 729 | "ignore_cis_vcc=1 parameter.\n"); |
754 | goto cs_failed; | 730 | cs_error(link, RequestIO, last_ret); |
755 | } | 731 | goto failed; |
756 | } | 732 | } |
757 | 733 | ||
758 | /* | 734 | /* |