aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/airo_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/airo_cs.c')
-rw-r--r--drivers/net/wireless/airo_cs.c230
1 files changed, 119 insertions, 111 deletions
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index f12355398fe7..4fbe811bebfc 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -206,126 +206,131 @@ static void airo_detach(struct pcmcia_device *link)
206#define CS_CHECK(fn, ret) \ 206#define CS_CHECK(fn, ret) \
207do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) 207do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
208 208
209struct airo_cs_config_data {
210 cistpl_cftable_entry_t dflt;
211 win_req_t req;
212};
213
214static int airo_cs_config_check(struct pcmcia_device *p_dev,
215 cistpl_cftable_entry_t *cfg,
216 void *priv_data)
217{
218 struct airo_cs_config_data *cfg_mem = priv_data;
219
220 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
221 cfg_mem->dflt = *cfg;
222
223 if (cfg->index == 0)
224 return -ENODEV;
225
226 p_dev->conf.ConfigIndex = cfg->index;
227
228 /* Does this card need audio output? */
229 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
230 p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
231 p_dev->conf.Status = CCSR_AUDIO_ENA;
232 }
233
234 /* Use power settings for Vcc and Vpp if present */
235 /* Note that the CIS values need to be rescaled */
236 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
237 p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
238 else if (cfg_mem->dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
239 p_dev->conf.Vpp = cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
240
241 /* Do we need to allocate an interrupt? */
242 if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1)
243 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
244
245 /* IO window settings */
246 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
247 if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) {
248 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io;
249 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
250 if (!(io->flags & CISTPL_IO_8BIT))
251 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
252 if (!(io->flags & CISTPL_IO_16BIT))
253 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
254 p_dev->io.BasePort1 = io->win[0].base;
255 p_dev->io.NumPorts1 = io->win[0].len;
256 if (io->nwin > 1) {
257 p_dev->io.Attributes2 = p_dev->io.Attributes1;
258 p_dev->io.BasePort2 = io->win[1].base;
259 p_dev->io.NumPorts2 = io->win[1].len;
260 }
261 }
262
263 /* This reserves IO space but doesn't actually enable it */
264 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
265 return -ENODEV;
266
267 /*
268 Now set up a common memory window, if needed. There is room
269 in the struct pcmcia_device structure for one memory window handle,
270 but if the base addresses need to be saved, or if multiple
271 windows are needed, the info should go in the private data
272 structure for this device.
273
274 Note that the memory window base is a physical address, and
275 needs to be mapped to virtual space with ioremap() before it
276 is used.
277 */
278 if ((cfg->mem.nwin > 0) || (cfg_mem->dflt.mem.nwin > 0)) {
279 cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &cfg_mem->dflt.mem;
280 memreq_t map;
281 cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
282 cfg_mem->req.Base = mem->win[0].host_addr;
283 cfg_mem->req.Size = mem->win[0].len;
284 cfg_mem->req.AccessSpeed = 0;
285 if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0)
286 return -ENODEV;
287 map.Page = 0;
288 map.CardOffset = mem->win[0].card_addr;
289 if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
290 return -ENODEV;
291 }
292 /* If we got this far, we're cool! */
293 return 0;
294}
295
296
209static int airo_config(struct pcmcia_device *link) 297static int airo_config(struct pcmcia_device *link)
210{ 298{
211 tuple_t tuple;
212 cisparse_t parse;
213 local_info_t *dev; 299 local_info_t *dev;
300 struct airo_cs_config_data *cfg_mem;
214 int last_fn, last_ret; 301 int last_fn, last_ret;
215 u_char buf[64];
216 win_req_t req;
217 memreq_t map;
218 302
219 dev = link->priv; 303 dev = link->priv;
220 304
221 DEBUG(0, "airo_config(0x%p)\n", link); 305 DEBUG(0, "airo_config(0x%p)\n", link);
222 306
307 cfg_mem = kzalloc(sizeof(struct airo_cs_config_data), GFP_KERNEL);
308 if (!cfg_mem)
309 return -ENOMEM;
310
223 /* 311 /*
224 In this loop, we scan the CIS for configuration table entries, 312 * In this loop, we scan the CIS for configuration table
225 each of which describes a valid card configuration, including 313 * entries, each of which describes a valid card
226 voltage, IO window, memory window, and interrupt settings. 314 * configuration, including voltage, IO window, memory window,
227 315 * and interrupt settings.
228 We make no assumptions about the card to be configured: we use 316 *
229 just the information available in the CIS. In an ideal world, 317 * We make no assumptions about the card to be configured: we
230 this would work for any PCMCIA card, but it requires a complete 318 * use just the information available in the CIS. In an ideal
231 and accurate CIS. In practice, a driver usually "knows" most of 319 * world, this would work for any PCMCIA card, but it requires
232 these things without consulting the CIS, and most client drivers 320 * a complete and accurate CIS. In practice, a driver usually
233 will only use the CIS to fill in implementation-defined details. 321 * "knows" most of these things without consulting the CIS,
322 * and most client drivers will only use the CIS to fill in
323 * implementation-defined details.
324 */
325 last_ret = pcmcia_loop_config(link, airo_cs_config_check, cfg_mem);
326 if (last_ret)
327 goto failed;
328
329 /*
330 Allocate an interrupt line. Note that this does not assign a
331 handler to the interrupt, unless the 'Handler' member of the
332 irq structure is initialized.
234 */ 333 */
235 tuple.Attributes = 0;
236 tuple.TupleData = buf;
237 tuple.TupleDataMax = sizeof(buf);
238 tuple.TupleOffset = 0;
239 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
240 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
241 while (1) {
242 cistpl_cftable_entry_t dflt = { 0 };
243 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
244 if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
245 pcmcia_parse_tuple(link, &tuple, &parse) != 0)
246 goto next_entry;
247
248 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
249 if (cfg->index == 0) goto next_entry;
250 link->conf.ConfigIndex = cfg->index;
251
252 /* Does this card need audio output? */
253 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
254 link->conf.Attributes |= CONF_ENABLE_SPKR;
255 link->conf.Status = CCSR_AUDIO_ENA;
256 }
257
258 /* Use power settings for Vcc and Vpp if present */
259 /* Note that the CIS values need to be rescaled */
260 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
261 link->conf.Vpp =
262 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
263 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
264 link->conf.Vpp =
265 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
266
267 /* Do we need to allocate an interrupt? */
268 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
269 link->conf.Attributes |= CONF_ENABLE_IRQ;
270
271 /* IO window settings */
272 link->io.NumPorts1 = link->io.NumPorts2 = 0;
273 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
274 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
275 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
276 if (!(io->flags & CISTPL_IO_8BIT))
277 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
278 if (!(io->flags & CISTPL_IO_16BIT))
279 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
280 link->io.BasePort1 = io->win[0].base;
281 link->io.NumPorts1 = io->win[0].len;
282 if (io->nwin > 1) {
283 link->io.Attributes2 = link->io.Attributes1;
284 link->io.BasePort2 = io->win[1].base;
285 link->io.NumPorts2 = io->win[1].len;
286 }
287 }
288
289 /* This reserves IO space but doesn't actually enable it */
290 if (pcmcia_request_io(link, &link->io) != 0)
291 goto next_entry;
292
293 /*
294 Now set up a common memory window, if needed. There is room
295 in the struct pcmcia_device structure for one memory window handle,
296 but if the base addresses need to be saved, or if multiple
297 windows are needed, the info should go in the private data
298 structure for this device.
299
300 Note that the memory window base is a physical address, and
301 needs to be mapped to virtual space with ioremap() before it
302 is used.
303 */
304 if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
305 cistpl_mem_t *mem =
306 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
307 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
308 req.Base = mem->win[0].host_addr;
309 req.Size = mem->win[0].len;
310 req.AccessSpeed = 0;
311 if (pcmcia_request_window(&link, &req, &link->win) != 0)
312 goto next_entry;
313 map.Page = 0; map.CardOffset = mem->win[0].card_addr;
314 if (pcmcia_map_mem_page(link->win, &map) != 0)
315 goto next_entry;
316 }
317 /* If we got this far, we're cool! */
318 break;
319
320 next_entry:
321 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
322 }
323
324 /*
325 Allocate an interrupt line. Note that this does not assign a
326 handler to the interrupt, unless the 'Handler' member of the
327 irq structure is initialized.
328 */
329 if (link->conf.Attributes & CONF_ENABLE_IRQ) 334 if (link->conf.Attributes & CONF_ENABLE_IRQ)
330 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); 335 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
331 336
@@ -362,14 +367,17 @@ static int airo_config(struct pcmcia_device *link)
362 printk(" & 0x%04x-0x%04x", link->io.BasePort2, 367 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
363 link->io.BasePort2+link->io.NumPorts2-1); 368 link->io.BasePort2+link->io.NumPorts2-1);
364 if (link->win) 369 if (link->win)
365 printk(", mem 0x%06lx-0x%06lx", req.Base, 370 printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
366 req.Base+req.Size-1); 371 cfg_mem->req.Base+cfg_mem->req.Size-1);
367 printk("\n"); 372 printk("\n");
373 kfree(cfg_mem);
368 return 0; 374 return 0;
369 375
370 cs_failed: 376 cs_failed:
371 cs_error(link, last_fn, last_ret); 377 cs_error(link, last_fn, last_ret);
378 failed:
372 airo_release(link); 379 airo_release(link);
380 kfree(cfg_mem);
373 return -ENODEV; 381 return -ENODEV;
374} /* airo_config */ 382} /* airo_config */
375 383