diff options
Diffstat (limited to 'drivers/char/pcmcia/cm4040_cs.c')
-rw-r--r-- | drivers/char/pcmcia/cm4040_cs.c | 151 |
1 files changed, 44 insertions, 107 deletions
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 4c698d908ffa..46eb371bf17e 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -65,7 +65,6 @@ static char *version = | |||
65 | #define POLL_PERIOD msecs_to_jiffies(10) | 65 | #define POLL_PERIOD msecs_to_jiffies(10) |
66 | 66 | ||
67 | static void reader_release(dev_link_t *link); | 67 | static void reader_release(dev_link_t *link); |
68 | static void reader_detach(dev_link_t *link); | ||
69 | 68 | ||
70 | static int major; | 69 | static int major; |
71 | 70 | ||
@@ -86,7 +85,6 @@ struct reader_dev { | |||
86 | struct timer_list poll_timer; | 85 | struct timer_list poll_timer; |
87 | }; | 86 | }; |
88 | 87 | ||
89 | static dev_info_t dev_info = MODULE_NAME; | ||
90 | static dev_link_t *dev_table[CM_MAX_DEV]; | 88 | static dev_link_t *dev_table[CM_MAX_DEV]; |
91 | 89 | ||
92 | #ifndef PCMCIA_DEBUG | 90 | #ifndef PCMCIA_DEBUG |
@@ -629,65 +627,26 @@ cs_release: | |||
629 | link->state &= ~DEV_CONFIG_PENDING; | 627 | link->state &= ~DEV_CONFIG_PENDING; |
630 | } | 628 | } |
631 | 629 | ||
632 | static int reader_event(event_t event, int priority, | 630 | static int reader_suspend(struct pcmcia_device *p_dev) |
633 | event_callback_args_t *args) | ||
634 | { | 631 | { |
635 | dev_link_t *link; | 632 | dev_link_t *link = dev_to_instance(p_dev); |
636 | struct reader_dev *dev; | ||
637 | int devno; | ||
638 | 633 | ||
639 | link = args->client_data; | 634 | link->state |= DEV_SUSPEND; |
640 | dev = link->priv; | 635 | if (link->state & DEV_CONFIG) |
641 | DEBUGP(3, dev, "-> reader_event\n"); | 636 | pcmcia_release_configuration(link->handle); |
642 | for (devno = 0; devno < CM_MAX_DEV; devno++) { | ||
643 | if (dev_table[devno] == link) | ||
644 | break; | ||
645 | } | ||
646 | if (devno == CM_MAX_DEV) | ||
647 | return CS_BAD_ADAPTER; | ||
648 | 637 | ||
649 | switch (event) { | 638 | return 0; |
650 | case CS_EVENT_CARD_INSERTION: | 639 | } |
651 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | 640 | |
652 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 641 | static int reader_resume(struct pcmcia_device *p_dev) |
653 | reader_config(link, devno); | 642 | { |
654 | break; | 643 | dev_link_t *link = dev_to_instance(p_dev); |
655 | case CS_EVENT_CARD_REMOVAL: | 644 | |
656 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | 645 | link->state &= ~DEV_SUSPEND; |
657 | link->state &= ~DEV_PRESENT; | 646 | if (link->state & DEV_CONFIG) |
658 | break; | 647 | pcmcia_request_configuration(link->handle, &link->conf); |
659 | case CS_EVENT_PM_SUSPEND: | 648 | |
660 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | 649 | return 0; |
661 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | ||
662 | link->state |= DEV_SUSPEND; | ||
663 | |||
664 | case CS_EVENT_RESET_PHYSICAL: | ||
665 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
666 | if (link->state & DEV_CONFIG) { | ||
667 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
668 | pcmcia_release_configuration(link->handle); | ||
669 | } | ||
670 | break; | ||
671 | case CS_EVENT_PM_RESUME: | ||
672 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
673 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
674 | link->state &= ~DEV_SUSPEND; | ||
675 | |||
676 | case CS_EVENT_CARD_RESET: | ||
677 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
678 | if ((link->state & DEV_CONFIG)) { | ||
679 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
680 | pcmcia_request_configuration(link->handle, | ||
681 | &link->conf); | ||
682 | } | ||
683 | break; | ||
684 | default: | ||
685 | DEBUGP(5, dev, "reader_event: unknown event %.2x\n", | ||
686 | event); | ||
687 | break; | ||
688 | } | ||
689 | DEBUGP(3, dev, "<- reader_event\n"); | ||
690 | return CS_SUCCESS; | ||
691 | } | 650 | } |
692 | 651 | ||
693 | static void reader_release(dev_link_t *link) | 652 | static void reader_release(dev_link_t *link) |
@@ -697,11 +656,10 @@ static void reader_release(dev_link_t *link) | |||
697 | pcmcia_release_io(link->handle, &link->io); | 656 | pcmcia_release_io(link->handle, &link->io); |
698 | } | 657 | } |
699 | 658 | ||
700 | static dev_link_t *reader_attach(void) | 659 | static int reader_attach(struct pcmcia_device *p_dev) |
701 | { | 660 | { |
702 | struct reader_dev *dev; | 661 | struct reader_dev *dev; |
703 | dev_link_t *link; | 662 | dev_link_t *link; |
704 | client_reg_t client_reg; | ||
705 | int i; | 663 | int i; |
706 | 664 | ||
707 | for (i = 0; i < CM_MAX_DEV; i++) { | 665 | for (i = 0; i < CM_MAX_DEV; i++) { |
@@ -710,11 +668,11 @@ static dev_link_t *reader_attach(void) | |||
710 | } | 668 | } |
711 | 669 | ||
712 | if (i == CM_MAX_DEV) | 670 | if (i == CM_MAX_DEV) |
713 | return NULL; | 671 | return -ENODEV; |
714 | 672 | ||
715 | dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL); | 673 | dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL); |
716 | if (dev == NULL) | 674 | if (dev == NULL) |
717 | return NULL; | 675 | return -ENOMEM; |
718 | 676 | ||
719 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; | 677 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; |
720 | dev->buffer_status = 0; | 678 | dev->buffer_status = 0; |
@@ -725,20 +683,6 @@ static dev_link_t *reader_attach(void) | |||
725 | link->conf.IntType = INT_MEMORY_AND_IO; | 683 | link->conf.IntType = INT_MEMORY_AND_IO; |
726 | dev_table[i] = link; | 684 | dev_table[i] = link; |
727 | 685 | ||
728 | client_reg.dev_info = &dev_info; | ||
729 | client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; | ||
730 | client_reg.EventMask= | ||
731 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
732 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
733 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
734 | client_reg.Version = 0x0210; | ||
735 | client_reg.event_callback_args.client_data = link; | ||
736 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
737 | if (i) { | ||
738 | cs_error(link->handle, RegisterClient, i); | ||
739 | reader_detach(link); | ||
740 | return NULL; | ||
741 | } | ||
742 | init_waitqueue_head(&dev->devq); | 686 | init_waitqueue_head(&dev->devq); |
743 | init_waitqueue_head(&dev->poll_wait); | 687 | init_waitqueue_head(&dev->poll_wait); |
744 | init_waitqueue_head(&dev->read_wait); | 688 | init_waitqueue_head(&dev->read_wait); |
@@ -746,39 +690,37 @@ static dev_link_t *reader_attach(void) | |||
746 | init_timer(&dev->poll_timer); | 690 | init_timer(&dev->poll_timer); |
747 | dev->poll_timer.function = &cm4040_do_poll; | 691 | dev->poll_timer.function = &cm4040_do_poll; |
748 | 692 | ||
749 | return link; | 693 | link->handle = p_dev; |
750 | } | 694 | p_dev->instance = link; |
751 | |||
752 | static void reader_detach_by_devno(int devno, dev_link_t *link) | ||
753 | { | ||
754 | struct reader_dev *dev = link->priv; | ||
755 | 695 | ||
756 | if (link->state & DEV_CONFIG) { | 696 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
757 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | 697 | reader_config(link, i); |
758 | reader_release(link); | ||
759 | } | ||
760 | 698 | ||
761 | pcmcia_deregister_client(link->handle); | 699 | return 0; |
762 | dev_table[devno] = NULL; | ||
763 | DEBUGP(5, dev, "freeing dev=%p\n", dev); | ||
764 | cm4040_stop_poll(dev); | ||
765 | kfree(dev); | ||
766 | return; | ||
767 | } | 700 | } |
768 | 701 | ||
769 | static void reader_detach(dev_link_t *link) | 702 | static void reader_detach(struct pcmcia_device *p_dev) |
770 | { | 703 | { |
771 | int i; | 704 | dev_link_t *link = dev_to_instance(p_dev); |
705 | struct reader_dev *dev = link->priv; | ||
706 | int devno; | ||
772 | 707 | ||
773 | /* find device */ | 708 | /* find device */ |
774 | for (i = 0; i < CM_MAX_DEV; i++) { | 709 | for (devno = 0; devno < CM_MAX_DEV; devno++) { |
775 | if (dev_table[i] == link) | 710 | if (dev_table[devno] == link) |
776 | break; | 711 | break; |
777 | } | 712 | } |
778 | if (i == CM_MAX_DEV) | 713 | if (devno == CM_MAX_DEV) |
779 | return; | 714 | return; |
780 | 715 | ||
781 | reader_detach_by_devno(i, link); | 716 | link->state &= ~DEV_PRESENT; |
717 | |||
718 | if (link->state & DEV_CONFIG) | ||
719 | reader_release(link); | ||
720 | |||
721 | dev_table[devno] = NULL; | ||
722 | kfree(dev); | ||
723 | |||
782 | return; | 724 | return; |
783 | } | 725 | } |
784 | 726 | ||
@@ -804,9 +746,10 @@ static struct pcmcia_driver reader_driver = { | |||
804 | .drv = { | 746 | .drv = { |
805 | .name = "cm4040_cs", | 747 | .name = "cm4040_cs", |
806 | }, | 748 | }, |
807 | .attach = reader_attach, | 749 | .probe = reader_attach, |
808 | .detach = reader_detach, | 750 | .remove = reader_detach, |
809 | .event = reader_event, | 751 | .suspend = reader_suspend, |
752 | .resume = reader_resume, | ||
810 | .id_table = cm4040_ids, | 753 | .id_table = cm4040_ids, |
811 | }; | 754 | }; |
812 | 755 | ||
@@ -825,14 +768,8 @@ static int __init cm4040_init(void) | |||
825 | 768 | ||
826 | static void __exit cm4040_exit(void) | 769 | static void __exit cm4040_exit(void) |
827 | { | 770 | { |
828 | int i; | ||
829 | |||
830 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | 771 | printk(KERN_INFO MODULE_NAME ": unloading\n"); |
831 | pcmcia_unregister_driver(&reader_driver); | 772 | pcmcia_unregister_driver(&reader_driver); |
832 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
833 | if (dev_table[i]) | ||
834 | reader_detach_by_devno(i, dev_table[i]); | ||
835 | } | ||
836 | unregister_chrdev(major, DEVICE_NAME); | 773 | unregister_chrdev(major, DEVICE_NAME); |
837 | } | 774 | } |
838 | 775 | ||