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