]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/char/pcmcia/cm4000_cs.c
[PATCH] pcmcia: embed dev_link_t into struct pcmcia_device
[mirror_ubuntu-artful-kernel.git] / drivers / char / pcmcia / cm4000_cs.c
index 05e93054c98cd57967200bf5fc19215672d430f1..3e6d6e0bb6ee8d6666af08807c6f7cd28f7261fa 100644 (file)
   *
   * (C) 2000,2001,2002,2003,2004 Omnikey AG
   *
-  * (C) 2005 Harald Welte <laforge@gnumonks.org>
+  * (C) 2005-2006 Harald Welte <laforge@gnumonks.org>
   *    - Adhere to Kernel CodingStyle
   *    - Port to 2.6.13 "new" style PCMCIA
   *    - Check for copy_{from,to}_user return values
   *    - Use nonseekable_open()
+  *    - add class interface for udev device creation
   *
   * All rights reserved. Licensed under dual BSD/GPL license.
   */
@@ -45,7 +46,7 @@
 /* #define ATR_CSUM */
 
 #ifdef PCMCIA_DEBUG
-#define reader_to_dev(x)       (&handle_to_dev(x->link.handle))
+#define reader_to_dev(x)       (&handle_to_dev(x->p_dev->handle))
 static int pc_debug = PCMCIA_DEBUG;
 module_param(pc_debug, int, 0600);
 #define DEBUGP(n, rdr, x, args...) do {                                \
@@ -56,7 +57,7 @@ module_param(pc_debug, int, 0600);
 #else
 #define DEBUGP(n, rdr, x, args...)
 #endif
-static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte";
+static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
 
 #define        T_1SEC          (HZ)
 #define        T_10MSEC        msecs_to_jiffies(10)
@@ -66,7 +67,6 @@ static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte";
 #define        T_100MSEC       msecs_to_jiffies(100)
 #define        T_500MSEC       msecs_to_jiffies(500)
 
-static void cm4000_detach(dev_link_t *link);
 static void cm4000_release(dev_link_t *link);
 
 static int major;              /* major number we get from the kernel */
@@ -106,7 +106,7 @@ static int major;           /* major number we get from the kernel */
 #define REG_STOPBITS(x)                (x + 7)
 
 struct cm4000_dev {
-       dev_link_t link;                /* pcmcia link */
+       struct pcmcia_device *p_dev;
        dev_node_t node;                /* OS node (major,minor) */
 
        unsigned char atr[MAX_ATR];
@@ -156,8 +156,8 @@ struct cm4000_dev {
                /*sbuf*/ 512*sizeof(char) -                     \
                /*queue*/ 4*sizeof(wait_queue_head_t))
 
-static dev_info_t dev_info = MODULE_NAME;
 static dev_link_t *dev_table[CM4000_MAX_DEV];
+static struct class *cmm_class;
 
 /* This table doesn't use spaces after the comma between fields and thus
  * violates CodingStyle.  However, I don't really think wrapping it around will
@@ -454,7 +454,7 @@ static struct card_fixup card_fixups[] = {
 static void set_cardparameter(struct cm4000_dev *dev)
 {
        int i;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
        u_int8_t stopbits = 0x02; /* ISO default */
 
        DEBUGP(3, dev, "-> set_cardparameter\n");
@@ -487,7 +487,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
        unsigned short num_bytes_read;
        unsigned char pts_reply[4];
        ssize_t rc;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
 
        rc = 0;
 
@@ -699,7 +699,7 @@ static void terminate_monitor(struct cm4000_dev *dev)
 static void monitor_card(unsigned long p)
 {
        struct cm4000_dev *dev = (struct cm4000_dev *) p;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
        unsigned short s;
        struct ptsreq ptsreq;
        int i, atrc;
@@ -962,7 +962,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
                        loff_t *ppos)
 {
        struct cm4000_dev *dev = filp->private_data;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
        ssize_t rc;
        int i, j, k;
 
@@ -971,7 +971,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
        if (count == 0)         /* according to manpage */
                return 0;
 
-       if ((dev->link.state & DEV_PRESENT) == 0 ||     /* socket removed */
+       if ((dev->p_dev->state & DEV_PRESENT) == 0 ||   /* socket removed */
            test_bit(IS_CMM_ABSENT, &dev->flags))
                return -ENODEV;
 
@@ -1083,7 +1083,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
                         size_t count, loff_t *ppos)
 {
        struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
        unsigned short s;
        unsigned char tmp;
        unsigned char infolen;
@@ -1108,7 +1108,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
 
        sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0;
 
-       if ((dev->link.state & DEV_PRESENT) == 0 ||     /* socket removed */
+       if ((dev->p_dev->state & DEV_PRESENT) == 0 ||   /* socket removed */
            test_bit(IS_CMM_ABSENT, &dev->flags))
                return -ENODEV;
 
@@ -1440,7 +1440,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                     unsigned long arg)
 {
        struct cm4000_dev *dev = filp->private_data;
-       ioaddr_t iobase = dev->link.io.BasePort1;
+       ioaddr_t iobase = dev->p_dev->io.BasePort1;
        dev_link_t *link;
        int size;
        int rc;
@@ -1765,7 +1765,6 @@ static void cm4000_config(dev_link_t * link, int devno)
        struct cm4000_dev *dev;
        tuple_t tuple;
        cisparse_t parse;
-       config_info_t conf;
        u_char buf[64];
        int fail_fn, fail_rc;
        int rc;
@@ -1790,16 +1789,10 @@ static void cm4000_config(dev_link_t * link, int devno)
                fail_fn = ParseTuple;
                goto cs_failed;
        }
-       if ((fail_rc =
-            pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) {
-               fail_fn = GetConfigurationInfo;
-               goto cs_failed;
-       }
 
        link->state |= DEV_CONFIG;
        link->conf.ConfigBase = parse.config.base;
        link->conf.Present = parse.config.rmask[0];
-       link->conf.Vcc = conf.Vcc;
 
        link->io.BasePort2 = 0;
        link->io.NumPorts2 = 0;
@@ -1851,7 +1844,7 @@ static void cm4000_config(dev_link_t * link, int devno)
        dev->node.major = major;
        dev->node.minor = devno;
        dev->node.next = NULL;
-       link->dev = &dev->node;
+       link->dev_node = &dev->node;
        link->state &= ~DEV_CONFIG_PENDING;
 
        return;
@@ -1864,53 +1857,12 @@ cs_release:
        link->state &= ~DEV_CONFIG_PENDING;
 }
 
-static int cm4000_event(event_t event, int priority,
-                       event_callback_args_t *args)
-{
-       dev_link_t *link;
-       struct cm4000_dev *dev;
-       int devno;
-
-       link = args->client_data;
-       dev = link->priv;
-
-       DEBUGP(3, dev, "-> cm4000_event\n");
-       for (devno = 0; devno < CM4000_MAX_DEV; devno++)
-               if (dev_table[devno] == link)
-                       break;
-
-       if (devno == CM4000_MAX_DEV)
-               return CS_BAD_ADAPTER;
-
-       switch (event) {
-       case CS_EVENT_CARD_INSERTION:
-               DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n");
-               link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-               cm4000_config(link, devno);
-               break;
-       case CS_EVENT_CARD_REMOVAL:
-               DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
-               link->state &= ~DEV_PRESENT;
-               stop_monitor(dev);
-               break;
-       default:
-               DEBUGP(5, dev, "unknown event %.2x\n", event);
-               break;
-       }
-       DEBUGP(3, dev, "<- cm4000_event\n");
-       return CS_SUCCESS;
-}
-
 static int cm4000_suspend(struct pcmcia_device *p_dev)
 {
        dev_link_t *link = dev_to_instance(p_dev);
        struct cm4000_dev *dev;
 
        dev = link->priv;
-
-       link->state |= DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_release_configuration(link->handle);
        stop_monitor(dev);
 
        return 0;
@@ -1922,11 +1874,6 @@ static int cm4000_resume(struct pcmcia_device *p_dev)
        struct cm4000_dev *dev;
 
        dev = link->priv;
-
-       link->state &= ~DEV_SUSPEND;
-       if (link->state & DEV_CONFIG)
-               pcmcia_request_configuration(link->handle, &link->conf);
-
        if (link->open)
                start_monitor(dev);
 
@@ -1936,16 +1883,14 @@ static int cm4000_resume(struct pcmcia_device *p_dev)
 static void cm4000_release(dev_link_t *link)
 {
        cmm_cm4000_release(link->priv); /* delay release until device closed */
-       pcmcia_release_configuration(link->handle);
-       pcmcia_release_io(link->handle, &link->io);
+       pcmcia_disable_device(link->handle);
 }
 
-static dev_link_t *cm4000_attach(void)
+static int cm4000_attach(struct pcmcia_device *p_dev)
 {
        struct cm4000_dev *dev;
-       dev_link_t *link;
-       client_reg_t client_reg;
        int i;
+       dev_link_t *link = dev_to_instance(p_dev);
 
        for (i = 0; i < CM4000_MAX_DEV; i++)
                if (dev_table[i] == NULL)
@@ -1953,76 +1898,57 @@ static dev_link_t *cm4000_attach(void)
 
        if (i == CM4000_MAX_DEV) {
                printk(KERN_NOTICE MODULE_NAME ": all devices in use\n");
-               return NULL;
+               return -ENODEV;
        }
 
        /* create a new cm4000_cs device */
        dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL);
        if (dev == NULL)
-               return NULL;
+               return -ENOMEM;
 
-       link = &dev->link;
+       dev->p_dev = p_dev;
        link->priv = dev;
        link->conf.IntType = INT_MEMORY_AND_IO;
        dev_table[i] = link;
 
-       /* register with card services */
-       client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-           CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-           CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-           CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.Version = 0x0210;
-       client_reg.event_callback_args.client_data = link;
-
-       i = pcmcia_register_client(&link->handle, &client_reg);
-       if (i) {
-               cs_error(link->handle, RegisterClient, i);
-               cm4000_detach(link);
-               return NULL;
-       }
-
        init_waitqueue_head(&dev->devq);
        init_waitqueue_head(&dev->ioq);
        init_waitqueue_head(&dev->atrq);
        init_waitqueue_head(&dev->readq);
 
-       return link;
+       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+       cm4000_config(link, i);
+
+       class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
+                           "cmm%d", i);
+
+       return 0;
 }
 
-static void cm4000_detach_by_devno(int devno, dev_link_t * link)
+static void cm4000_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        struct cm4000_dev *dev = link->priv;
+       int devno;
 
-       DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno);
+       /* find device */
+       for (devno = 0; devno < CM4000_MAX_DEV; devno++)
+               if (dev_table[devno] == link)
+                       break;
+       if (devno == CM4000_MAX_DEV)
+               return;
 
-       if (link->state & DEV_CONFIG) {
-               DEBUGP(5, dev, "device still configured (try to release it)\n");
-               cm4000_release(link);
-       }
+       link->state &= ~DEV_PRESENT;
+       stop_monitor(dev);
 
-       if (link->handle) {
-               pcmcia_deregister_client(link->handle);
-       }
+       if (link->state & DEV_CONFIG)
+               cm4000_release(link);
 
        dev_table[devno] = NULL;
-       kfree(dev);
-       return;
-}
-
-static void cm4000_detach(dev_link_t * link)
-{
-       int i;
+       kfree(dev);
 
-       /* find device */
-       for (i = 0; i < CM4000_MAX_DEV; i++)
-               if (dev_table[i] == link)
-                       break;
+       class_device_destroy(cmm_class, MKDEV(major, devno));
 
-       if (i == CM4000_MAX_DEV)
-               return;
-
-       cm4000_detach_by_devno(i, link);
        return;
 }
 
@@ -2047,18 +1973,27 @@ static struct pcmcia_driver cm4000_driver = {
        .drv      = {
                .name = "cm4000_cs",
                },
-       .attach   = cm4000_attach,
-       .detach   = cm4000_detach,
+       .probe    = cm4000_attach,
+       .remove   = cm4000_detach,
        .suspend  = cm4000_suspend,
        .resume   = cm4000_resume,
-       .event    = cm4000_event,
        .id_table = cm4000_ids,
 };
 
 static int __init cmm_init(void)
 {
+       int rc;
+
        printk(KERN_INFO "%s\n", version);
-       pcmcia_register_driver(&cm4000_driver);
+
+       cmm_class = class_create(THIS_MODULE, "cardman_4000");
+       if (!cmm_class)
+               return -1;
+
+       rc = pcmcia_register_driver(&cm4000_driver);
+       if (rc < 0)
+               return rc;
+
        major = register_chrdev(0, DEVICE_NAME, &cm4000_fops);
        if (major < 0) {
                printk(KERN_WARNING MODULE_NAME
@@ -2071,14 +2006,10 @@ static int __init cmm_init(void)
 
 static void __exit cmm_exit(void)
 {
-       int i;
-
        printk(KERN_INFO MODULE_NAME ": unloading\n");
        pcmcia_unregister_driver(&cm4000_driver);
-       for (i = 0; i < CM4000_MAX_DEV; i++)
-               if (dev_table[i])
-                       cm4000_detach_by_devno(i, dev_table[i]);
        unregister_chrdev(major, DEVICE_NAME);
+       class_destroy(cmm_class);
 };
 
 module_init(cmm_init);