diff options
author | H Hartley Sweeten <hsweeten@visionengravers.com> | 2013-01-30 17:23:27 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-01-31 04:40:41 -0500 |
commit | 2bdaef1afc15ae675a1d26e19d2b77bde215ef4a (patch) | |
tree | 2cf778a2cff894093589e3095a12e7b5d8d941a3 | |
parent | 1f021e1f3b187586e457b4584d0e5f0f5ca5fa15 (diff) |
staging: comedi: cb_das16_cs: convert to auto attach
Convert this pcmcia driver to the comedi auto attach mechanism.
This allows getting rid of the "hack" needed to pass the pcmcia_device
pointer from the pcmcia_driver to the comedi_driver.
Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/comedi/drivers/cb_das16_cs.c | 115 |
1 files changed, 49 insertions, 66 deletions
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index e253fc03cefa..efff05954133 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c | |||
@@ -40,9 +40,10 @@ Status: experimental | |||
40 | 40 | ||
41 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include "../comedidev.h" | ||
44 | #include <linux/delay.h> | 43 | #include <linux/delay.h> |
45 | 44 | ||
45 | #include "../comedidev.h" | ||
46 | |||
46 | #include <pcmcia/cistpl.h> | 47 | #include <pcmcia/cistpl.h> |
47 | #include <pcmcia/ds.h> | 48 | #include <pcmcia/ds.h> |
48 | 49 | ||
@@ -89,8 +90,6 @@ struct das16cs_private { | |||
89 | unsigned short status2; | 90 | unsigned short status2; |
90 | }; | 91 | }; |
91 | 92 | ||
92 | static struct pcmcia_device *cur_dev; | ||
93 | |||
94 | static const struct comedi_lrange das16cs_ai_range = { | 93 | static const struct comedi_lrange das16cs_ai_range = { |
95 | 4, { | 94 | 4, { |
96 | BIP_RANGE(10), | 95 | BIP_RANGE(10), |
@@ -383,45 +382,62 @@ static int das16cs_dio_insn_config(struct comedi_device *dev, | |||
383 | return insn->n; | 382 | return insn->n; |
384 | } | 383 | } |
385 | 384 | ||
386 | static const struct das16cs_board *das16cs_probe(struct comedi_device *dev, | 385 | static const void *das16cs_find_boardinfo(struct comedi_device *dev, |
387 | struct pcmcia_device *link) | 386 | struct pcmcia_device *link) |
388 | { | 387 | { |
388 | const struct das16cs_board *board; | ||
389 | int i; | 389 | int i; |
390 | 390 | ||
391 | for (i = 0; i < ARRAY_SIZE(das16cs_boards); i++) { | 391 | for (i = 0; i < ARRAY_SIZE(das16cs_boards); i++) { |
392 | if (das16cs_boards[i].device_id == link->card_id) | 392 | board = &das16cs_boards[i]; |
393 | return das16cs_boards + i; | 393 | if (board->device_id == link->card_id) |
394 | return board; | ||
394 | } | 395 | } |
395 | 396 | ||
396 | dev_dbg(dev->class_dev, "unknown board!\n"); | ||
397 | |||
398 | return NULL; | 397 | return NULL; |
399 | } | 398 | } |
400 | 399 | ||
401 | static int das16cs_attach(struct comedi_device *dev, | 400 | static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev, |
402 | struct comedi_devconfig *it) | 401 | void *priv_data) |
402 | { | ||
403 | if (p_dev->config_index == 0) | ||
404 | return -EINVAL; | ||
405 | |||
406 | return pcmcia_request_io(p_dev); | ||
407 | } | ||
408 | |||
409 | static int das16cs_auto_attach(struct comedi_device *dev, | ||
410 | unsigned long context) | ||
403 | { | 411 | { |
404 | const struct das16cs_board *thisboard; | 412 | struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); |
413 | const struct das16cs_board *board; | ||
405 | struct das16cs_private *devpriv; | 414 | struct das16cs_private *devpriv; |
406 | struct pcmcia_device *link; | ||
407 | struct comedi_subdevice *s; | 415 | struct comedi_subdevice *s; |
408 | int ret; | 416 | int ret; |
409 | 417 | ||
410 | link = cur_dev; /* XXX hack */ | 418 | board = das16cs_find_boardinfo(dev, link); |
411 | if (!link) | 419 | if (!board) |
412 | return -EIO; | 420 | return -ENODEV; |
421 | dev->board_ptr = board; | ||
422 | dev->board_name = board->name; | ||
413 | 423 | ||
414 | dev->board_ptr = das16cs_probe(dev, link); | 424 | /* Do we need to allocate an interrupt? */ |
415 | if (!dev->board_ptr) | 425 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
416 | return -EIO; | ||
417 | thisboard = comedi_board(dev); | ||
418 | 426 | ||
419 | dev->board_name = thisboard->name; | 427 | ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL); |
428 | if (ret) | ||
429 | return ret; | ||
430 | |||
431 | if (!link->irq) | ||
432 | return -EINVAL; | ||
420 | 433 | ||
434 | ret = pcmcia_enable_device(link); | ||
435 | if (ret) | ||
436 | return ret; | ||
421 | dev->iobase = link->resource[0]->start; | 437 | dev->iobase = link->resource[0]->start; |
422 | 438 | ||
423 | ret = request_irq(link->irq, das16cs_interrupt, | 439 | ret = request_irq(link->irq, das16cs_interrupt, IRQF_SHARED, |
424 | IRQF_SHARED, "cb_das16_cs", dev); | 440 | dev->board_name, dev); |
425 | if (ret < 0) | 441 | if (ret < 0) |
426 | return ret; | 442 | return ret; |
427 | dev->irq = link->irq; | 443 | dev->irq = link->irq; |
@@ -450,10 +466,10 @@ static int das16cs_attach(struct comedi_device *dev, | |||
450 | 466 | ||
451 | s = &dev->subdevices[1]; | 467 | s = &dev->subdevices[1]; |
452 | /* analog output subdevice */ | 468 | /* analog output subdevice */ |
453 | if (thisboard->n_ao_chans) { | 469 | if (board->n_ao_chans) { |
454 | s->type = COMEDI_SUBD_AO; | 470 | s->type = COMEDI_SUBD_AO; |
455 | s->subdev_flags = SDF_WRITABLE; | 471 | s->subdev_flags = SDF_WRITABLE; |
456 | s->n_chan = thisboard->n_ao_chans; | 472 | s->n_chan = board->n_ao_chans; |
457 | s->maxdata = 0xffff; | 473 | s->maxdata = 0xffff; |
458 | s->range_table = &range_bipolar10; | 474 | s->range_table = &range_bipolar10; |
459 | s->insn_write = &das16cs_ao_winsn; | 475 | s->insn_write = &das16cs_ao_winsn; |
@@ -481,56 +497,24 @@ static int das16cs_attach(struct comedi_device *dev, | |||
481 | 497 | ||
482 | static void das16cs_detach(struct comedi_device *dev) | 498 | static void das16cs_detach(struct comedi_device *dev) |
483 | { | 499 | { |
500 | struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); | ||
501 | |||
484 | if (dev->irq) | 502 | if (dev->irq) |
485 | free_irq(dev->irq, dev); | 503 | free_irq(dev->irq, dev); |
504 | if (dev->iobase) | ||
505 | pcmcia_disable_device(link); | ||
486 | } | 506 | } |
487 | 507 | ||
488 | static struct comedi_driver driver_das16cs = { | 508 | static struct comedi_driver driver_das16cs = { |
489 | .driver_name = "cb_das16_cs", | 509 | .driver_name = "cb_das16_cs", |
490 | .module = THIS_MODULE, | 510 | .module = THIS_MODULE, |
491 | .attach = das16cs_attach, | 511 | .auto_attach = das16cs_auto_attach, |
492 | .detach = das16cs_detach, | 512 | .detach = das16cs_detach, |
493 | }; | 513 | }; |
494 | 514 | ||
495 | static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev, | ||
496 | void *priv_data) | ||
497 | { | ||
498 | if (p_dev->config_index == 0) | ||
499 | return -EINVAL; | ||
500 | |||
501 | return pcmcia_request_io(p_dev); | ||
502 | } | ||
503 | |||
504 | static int das16cs_pcmcia_attach(struct pcmcia_device *link) | 515 | static int das16cs_pcmcia_attach(struct pcmcia_device *link) |
505 | { | 516 | { |
506 | int ret; | 517 | return comedi_pcmcia_auto_config(link, &driver_das16cs); |
507 | |||
508 | /* Do we need to allocate an interrupt? */ | ||
509 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | ||
510 | |||
511 | ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL); | ||
512 | if (ret) | ||
513 | goto failed; | ||
514 | |||
515 | if (!link->irq) | ||
516 | goto failed; | ||
517 | |||
518 | ret = pcmcia_enable_device(link); | ||
519 | if (ret) | ||
520 | goto failed; | ||
521 | |||
522 | cur_dev = link; | ||
523 | return 0; | ||
524 | |||
525 | failed: | ||
526 | pcmcia_disable_device(link); | ||
527 | return ret; | ||
528 | } | ||
529 | |||
530 | static void das16cs_pcmcia_detach(struct pcmcia_device *link) | ||
531 | { | ||
532 | pcmcia_disable_device(link); | ||
533 | cur_dev = NULL; | ||
534 | } | 518 | } |
535 | 519 | ||
536 | static const struct pcmcia_device_id das16cs_id_table[] = { | 520 | static const struct pcmcia_device_id das16cs_id_table[] = { |
@@ -543,11 +527,10 @@ MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table); | |||
543 | static struct pcmcia_driver das16cs_driver = { | 527 | static struct pcmcia_driver das16cs_driver = { |
544 | .name = "cb_das16_cs", | 528 | .name = "cb_das16_cs", |
545 | .owner = THIS_MODULE, | 529 | .owner = THIS_MODULE, |
546 | .probe = das16cs_pcmcia_attach, | ||
547 | .remove = das16cs_pcmcia_detach, | ||
548 | .id_table = das16cs_id_table, | 530 | .id_table = das16cs_id_table, |
531 | .probe = das16cs_pcmcia_attach, | ||
532 | .remove = comedi_pcmcia_auto_unconfig, | ||
549 | }; | 533 | }; |
550 | |||
551 | module_comedi_pcmcia_driver(driver_das16cs, das16cs_driver); | 534 | module_comedi_pcmcia_driver(driver_das16cs, das16cs_driver); |
552 | 535 | ||
553 | MODULE_AUTHOR("David A. Schleef <ds@schleef.org>"); | 536 | MODULE_AUTHOR("David A. Schleef <ds@schleef.org>"); |