diff options
Diffstat (limited to 'drivers/isdn/hisax/sedlbauer_cs.c')
-rw-r--r-- | drivers/isdn/hisax/sedlbauer_cs.c | 208 |
1 files changed, 102 insertions, 106 deletions
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 439cb530def8..0f80b5667ea1 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c | |||
@@ -217,101 +217,68 @@ static void sedlbauer_detach(struct pcmcia_device *link) | |||
217 | #define CS_CHECK(fn, ret) \ | 217 | #define CS_CHECK(fn, ret) \ |
218 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 218 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
219 | 219 | ||
220 | static int sedlbauer_config(struct pcmcia_device *link) | 220 | struct sedlbauer_config_data { |
221 | { | 221 | cistpl_cftable_entry_t dflt; |
222 | local_info_t *dev = link->priv; | 222 | config_info_t conf; |
223 | tuple_t tuple; | 223 | win_req_t req; |
224 | cisparse_t parse; | 224 | }; |
225 | int last_fn, last_ret; | ||
226 | u8 buf[64]; | ||
227 | config_info_t conf; | ||
228 | win_req_t req; | ||
229 | memreq_t map; | ||
230 | IsdnCard_t icard; | ||
231 | |||
232 | DEBUG(0, "sedlbauer_config(0x%p)\n", link); | ||
233 | |||
234 | tuple.Attributes = 0; | ||
235 | tuple.TupleData = buf; | ||
236 | tuple.TupleDataMax = sizeof(buf); | ||
237 | tuple.TupleOffset = 0; | ||
238 | 225 | ||
239 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); | 226 | static int sedlbauer_config_check(struct pcmcia_device *p_dev, |
227 | cistpl_cftable_entry_t *cfg, | ||
228 | void *priv_data) | ||
229 | { | ||
230 | struct sedlbauer_config_data *cfg_mem = priv_data; | ||
240 | 231 | ||
241 | /* | 232 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) |
242 | In this loop, we scan the CIS for configuration table entries, | 233 | cfg_mem->dflt = *cfg; |
243 | each of which describes a valid card configuration, including | 234 | if (cfg->index == 0) |
244 | voltage, IO window, memory window, and interrupt settings. | 235 | return -ENODEV; |
236 | p_dev->conf.ConfigIndex = cfg->index; | ||
245 | 237 | ||
246 | We make no assumptions about the card to be configured: we use | ||
247 | just the information available in the CIS. In an ideal world, | ||
248 | this would work for any PCMCIA card, but it requires a complete | ||
249 | and accurate CIS. In practice, a driver usually "knows" most of | ||
250 | these things without consulting the CIS, and most client drivers | ||
251 | will only use the CIS to fill in implementation-defined details. | ||
252 | */ | ||
253 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
254 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
255 | while (1) { | ||
256 | cistpl_cftable_entry_t dflt = { 0 }; | ||
257 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | ||
258 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || | ||
259 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) | ||
260 | goto next_entry; | ||
261 | |||
262 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; | ||
263 | if (cfg->index == 0) goto next_entry; | ||
264 | link->conf.ConfigIndex = cfg->index; | ||
265 | |||
266 | /* Does this card need audio output? */ | 238 | /* Does this card need audio output? */ |
267 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | 239 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { |
268 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 240 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; |
269 | link->conf.Status = CCSR_AUDIO_ENA; | 241 | p_dev->conf.Status = CCSR_AUDIO_ENA; |
270 | } | 242 | } |
271 | 243 | ||
272 | /* Use power settings for Vcc and Vpp if present */ | 244 | /* Use power settings for Vcc and Vpp if present */ |
273 | /* Note that the CIS values need to be rescaled */ | 245 | /* Note that the CIS values need to be rescaled */ |
274 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { | 246 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { |
275 | if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) | 247 | if (cfg_mem->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) |
276 | goto next_entry; | 248 | return -ENODEV; |
277 | } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { | 249 | } else if (cfg_mem->dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { |
278 | if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) | 250 | if (cfg_mem->conf.Vcc != cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM]/10000) |
279 | goto next_entry; | 251 | return -ENODEV; |
280 | } | 252 | } |
281 | 253 | ||
282 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | 254 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) |
283 | link->conf.Vpp = | 255 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; |
284 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | 256 | else if (cfg_mem->dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) |
285 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) | 257 | p_dev->conf.Vpp = cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; |
286 | link->conf.Vpp = | 258 | |
287 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
288 | |||
289 | /* Do we need to allocate an interrupt? */ | 259 | /* Do we need to allocate an interrupt? */ |
290 | if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) | 260 | if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1) |
291 | link->conf.Attributes |= CONF_ENABLE_IRQ; | 261 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; |
292 | 262 | ||
293 | /* IO window settings */ | 263 | /* IO window settings */ |
294 | link->io.NumPorts1 = link->io.NumPorts2 = 0; | 264 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; |
295 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | 265 | if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) { |
296 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; | 266 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io; |
297 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | 267 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; |
298 | if (!(io->flags & CISTPL_IO_8BIT)) | 268 | if (!(io->flags & CISTPL_IO_8BIT)) |
299 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | 269 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; |
300 | if (!(io->flags & CISTPL_IO_16BIT)) | 270 | if (!(io->flags & CISTPL_IO_16BIT)) |
301 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 271 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
302 | /* new in dummy.cs 2001/01/28 MN | 272 | p_dev->io.BasePort1 = io->win[0].base; |
303 | link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | 273 | p_dev->io.NumPorts1 = io->win[0].len; |
304 | */ | 274 | if (io->nwin > 1) { |
305 | link->io.BasePort1 = io->win[0].base; | 275 | p_dev->io.Attributes2 = p_dev->io.Attributes1; |
306 | link->io.NumPorts1 = io->win[0].len; | 276 | p_dev->io.BasePort2 = io->win[1].base; |
307 | if (io->nwin > 1) { | 277 | p_dev->io.NumPorts2 = io->win[1].len; |
308 | link->io.Attributes2 = link->io.Attributes1; | 278 | } |
309 | link->io.BasePort2 = io->win[1].base; | 279 | /* This reserves IO space but doesn't actually enable it */ |
310 | link->io.NumPorts2 = io->win[1].len; | 280 | if (pcmcia_request_io(p_dev, &p_dev->io) != 0) |
311 | } | 281 | return -ENODEV; |
312 | /* This reserves IO space but doesn't actually enable it */ | ||
313 | if (pcmcia_request_io(link, &link->io) != 0) | ||
314 | goto next_entry; | ||
315 | } | 282 | } |
316 | 283 | ||
317 | /* | 284 | /* |
@@ -325,30 +292,58 @@ static int sedlbauer_config(struct pcmcia_device *link) | |||
325 | needs to be mapped to virtual space with ioremap() before it | 292 | needs to be mapped to virtual space with ioremap() before it |
326 | is used. | 293 | is used. |
327 | */ | 294 | */ |
328 | if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { | 295 | if ((cfg->mem.nwin > 0) || (cfg_mem->dflt.mem.nwin > 0)) { |
329 | cistpl_mem_t *mem = | 296 | cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &cfg_mem->dflt.mem; |
330 | (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; | 297 | memreq_t map; |
331 | req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; | 298 | cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; |
332 | req.Attributes |= WIN_ENABLE; | 299 | cfg_mem->req.Attributes |= WIN_ENABLE; |
333 | req.Base = mem->win[0].host_addr; | 300 | cfg_mem->req.Base = mem->win[0].host_addr; |
334 | req.Size = mem->win[0].len; | 301 | cfg_mem->req.Size = mem->win[0].len; |
335 | /* new in dummy.cs 2001/01/28 MN | 302 | cfg_mem->req.AccessSpeed = 0; |
336 | if (req.Size < 0x1000) | 303 | if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0) |
337 | req.Size = 0x1000; | 304 | return -ENODEV; |
338 | */ | 305 | map.Page = 0; |
339 | req.AccessSpeed = 0; | 306 | map.CardOffset = mem->win[0].card_addr; |
340 | if (pcmcia_request_window(&link, &req, &link->win) != 0) | 307 | if (pcmcia_map_mem_page(p_dev->win, &map) != 0) |
341 | goto next_entry; | 308 | return -ENODEV; |
342 | map.Page = 0; map.CardOffset = mem->win[0].card_addr; | ||
343 | if (pcmcia_map_mem_page(link->win, &map) != 0) | ||
344 | goto next_entry; | ||
345 | } | 309 | } |
346 | /* If we got this far, we're cool! */ | 310 | return 0; |
347 | break; | 311 | } |
348 | 312 | ||
349 | next_entry: | 313 | |
350 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); | 314 | |
351 | } | 315 | static int sedlbauer_config(struct pcmcia_device *link) |
316 | { | ||
317 | local_info_t *dev = link->priv; | ||
318 | struct sedlbauer_config_data *cfg_mem; | ||
319 | int last_fn, last_ret; | ||
320 | IsdnCard_t icard; | ||
321 | |||
322 | DEBUG(0, "sedlbauer_config(0x%p)\n", link); | ||
323 | |||
324 | cfg_mem = kzalloc(sizeof(struct sedlbauer_config_data), GFP_KERNEL); | ||
325 | if (!cfg_mem) | ||
326 | return -ENOMEM; | ||
327 | |||
328 | /* Look up the current Vcc */ | ||
329 | CS_CHECK(GetConfigurationInfo, | ||
330 | pcmcia_get_configuration_info(link, &cfg_mem->conf)); | ||
331 | |||
332 | /* | ||
333 | In this loop, we scan the CIS for configuration table entries, | ||
334 | each of which describes a valid card configuration, including | ||
335 | voltage, IO window, memory window, and interrupt settings. | ||
336 | |||
337 | We make no assumptions about the card to be configured: we use | ||
338 | just the information available in the CIS. In an ideal world, | ||
339 | this would work for any PCMCIA card, but it requires a complete | ||
340 | and accurate CIS. In practice, a driver usually "knows" most of | ||
341 | these things without consulting the CIS, and most client drivers | ||
342 | will only use the CIS to fill in implementation-defined details. | ||
343 | */ | ||
344 | last_ret = pcmcia_loop_config(link, sedlbauer_config_check, cfg_mem); | ||
345 | if (last_ret) | ||
346 | goto failed; | ||
352 | 347 | ||
353 | /* | 348 | /* |
354 | Allocate an interrupt line. Note that this does not assign a | 349 | Allocate an interrupt line. Note that this does not assign a |
@@ -387,8 +382,8 @@ static int sedlbauer_config(struct pcmcia_device *link) | |||
387 | printk(" & 0x%04x-0x%04x", link->io.BasePort2, | 382 | printk(" & 0x%04x-0x%04x", link->io.BasePort2, |
388 | link->io.BasePort2+link->io.NumPorts2-1); | 383 | link->io.BasePort2+link->io.NumPorts2-1); |
389 | if (link->win) | 384 | if (link->win) |
390 | printk(", mem 0x%06lx-0x%06lx", req.Base, | 385 | printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base, |
391 | req.Base+req.Size-1); | 386 | cfg_mem->req.Base+cfg_mem->req.Size-1); |
392 | printk("\n"); | 387 | printk("\n"); |
393 | 388 | ||
394 | icard.para[0] = link->irq.AssignedIRQ; | 389 | icard.para[0] = link->irq.AssignedIRQ; |
@@ -409,6 +404,7 @@ static int sedlbauer_config(struct pcmcia_device *link) | |||
409 | 404 | ||
410 | cs_failed: | 405 | cs_failed: |
411 | cs_error(link, last_fn, last_ret); | 406 | cs_error(link, last_fn, last_ret); |
407 | failed: | ||
412 | sedlbauer_release(link); | 408 | sedlbauer_release(link); |
413 | return -ENODEV; | 409 | return -ENODEV; |
414 | 410 | ||