Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / net / wan / cosa.c
index 00d0b75..1f95b48 100644 (file)
 \f
 /* ---------- Headers, macros, data structures ---------- */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fs.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -93,6 +91,7 @@
 #include <linux/netdevice.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
+#include <linux/device.h>
 
 #undef COSA_SLOW_IO    /* for testing purposes only */
 #undef REALLY_SLOW_IO
@@ -155,7 +154,7 @@ struct cosa_data {
        unsigned short startaddr;       /* Firmware start address */
        unsigned short busmaster;       /* Use busmastering? */
        int nchannels;                  /* # of channels on this card */
-       int driver_status;              /* For communicating with firware */
+       int driver_status;              /* For communicating with firmware */
        int firmware_status;            /* Downloaded, reseted, etc. */
        long int rxbitmap, txbitmap;    /* Bitmap of channels who are willing to send/receive data */
        long int rxtx;                  /* RX or TX in progress? */
@@ -233,12 +232,15 @@ static int dma[MAX_CARDS+1];
 /* IRQ can be safely autoprobed */
 static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, };
 
+/* for class stuff*/
+static struct class *cosa_class;
+
 #ifdef MODULE
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
+module_param_array(io, int, NULL, 0);
 MODULE_PARM_DESC(io, "The I/O bases of the COSA or SRP cards");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
+module_param_array(irq, int, NULL, 0);
 MODULE_PARM_DESC(irq, "The IRQ lines of the COSA or SRP cards");
-MODULE_PARM(dma, "1-" __MODULE_STRING(MAX_CARDS) "i");
+module_param_array(dma, int, NULL, 0);
 MODULE_PARM_DESC(dma, "The DMA channels of the COSA or SRP cards");
 
 MODULE_AUTHOR("Jan \"Yenya\" Kasprzak, <kas@fi.muni.cz>");
@@ -297,9 +299,9 @@ static char *chrdev_setup_rx(struct channel_data *channel, int size);
 static int chrdev_rx_done(struct channel_data *channel);
 static int chrdev_tx_done(struct channel_data *channel, int size);
 static ssize_t cosa_read(struct file *file,
-       char *buf, size_t count, loff_t *ppos);
+       char __user *buf, size_t count, loff_t *ppos);
 static ssize_t cosa_write(struct file *file,
-       const char *buf, size_t count, loff_t *ppos);
+       const char __user *buf, size_t count, loff_t *ppos);
 static unsigned int cosa_poll(struct file *file, poll_table *poll);
 static int cosa_open(struct inode *inode, struct file *file);
 static int cosa_release(struct inode *inode, struct file *file);
@@ -326,13 +328,13 @@ static struct file_operations cosa_fops = {
 /* Ioctls */
 static int cosa_start(struct cosa_data *cosa, int address);
 static int cosa_reset(struct cosa_data *cosa);
-static int cosa_download(struct cosa_data *cosa, unsigned long a);
-static int cosa_readmem(struct cosa_data *cosa, unsigned long a);
+static int cosa_download(struct cosa_data *cosa, void __user *a);
+static int cosa_readmem(struct cosa_data *cosa, void __user *a);
 
 /* COSA/SRP ROM monitor */
-static int download(struct cosa_data *cosa, const char *data, int addr, int len);
+static int download(struct cosa_data *cosa, const char __user *data, int addr, int len);
 static int startmicrocode(struct cosa_data *cosa, int address);
-static int readmem(struct cosa_data *cosa, char *data, int addr, int len);
+static int readmem(struct cosa_data *cosa, char __user *data, int addr, int len);
 static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id);
 
 /* Auxilliary functions */
@@ -359,7 +361,7 @@ static void debug_status_out(struct cosa_data *cosa, int status);
 
 static int __init cosa_init(void)
 {
-       int i;
+       int i, err = 0;
 
        printk(KERN_INFO "cosa v1.08 (c) 1997-2000 Jan Kasprzak <kas@fi.muni.cz>\n");
 #ifdef CONFIG_SMP
@@ -369,12 +371,14 @@ static int __init cosa_init(void)
                if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
                        printk(KERN_WARNING "cosa: unable to get major %d\n",
                                cosa_major);
-                       return -EIO;
+                       err = -EIO;
+                       goto out;
                }
        } else {
                if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
                        printk(KERN_WARNING "cosa: unable to register chardev\n");
-                       return -EIO;
+                       err = -EIO;
+                       goto out;
                }
        }
        for (i=0; i<MAX_CARDS; i++)
@@ -384,15 +388,25 @@ static int __init cosa_init(void)
        if (!nr_cards) {
                printk(KERN_WARNING "cosa: no devices found.\n");
                unregister_chrdev(cosa_major, "cosa");
-               return -ENODEV;
+               err = -ENODEV;
+               goto out;
+       }
+       cosa_class = class_create(THIS_MODULE, "cosa");
+       if (IS_ERR(cosa_class)) {
+               err = PTR_ERR(cosa_class);
+               goto out_chrdev;
        }
-       devfs_mk_dir("cosa");
        for (i=0; i<nr_cards; i++) {
-               devfs_mk_cdev(MKDEV(cosa_major, i),
-                               S_IFCHR|S_IRUSR|S_IWUSR,
-                               "cosa/%d", i);
+               class_device_create(cosa_class, NULL, MKDEV(cosa_major, i),
+                               NULL, "cosa%d", i);
        }
-       return 0;
+       err = 0;
+       goto out;
+       
+out_chrdev:
+       unregister_chrdev(cosa_major, "cosa");
+out:
+       return err;
 }
 module_init(cosa_init);
 
@@ -403,8 +417,8 @@ static void __exit cosa_exit(void)
        printk(KERN_INFO "Unloading the cosa module\n");
 
        for (i=0; i<nr_cards; i++)
-               devfs_remove("cosa/%d", i);
-       devfs_remove("cosa");
+               class_device_destroy(cosa_class, MKDEV(cosa_major, i));
+       class_destroy(cosa_class);
        for (cosa=cosa_cards; nr_cards--; cosa++) {
                /* Clean up the per-channel data */
                for (i=0; i<cosa->nchannels; i++) {
@@ -516,7 +530,7 @@ static int cosa_probe(int base, int irq, int dma)
                 * FIXME: When this code is not used as module, we should
                 * probably call udelay() instead of the interruptible sleep.
                 */
-               current->state = TASK_INTERRUPTIBLE;
+               set_current_state(TASK_INTERRUPTIBLE);
                cosa_putstatus(cosa, SR_TX_INT_ENA);
                schedule_timeout(30);
                irq = probe_irq_off(irqs);
@@ -615,11 +629,11 @@ static void sppp_channel_init(struct channel_data *chan)
                return;
        }
        chan->pppdev.dev = d;
-       sppp_attach(&chan->pppdev);
        d->base_addr = chan->cosa->datareg;
        d->irq = chan->cosa->irq;
        d->dma = chan->cosa->dma;
        d->priv = chan;
+       sppp_attach(&chan->pppdev);
        if (register_netdev(d)) {
                printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
                sppp_detach(d);
@@ -702,7 +716,7 @@ static void cosa_sppp_timeout(struct net_device *dev)
        cosa_kick(chan->cosa);
        if (chan->tx_skb) {
                dev_kfree_skb(chan->tx_skb);
-               chan->tx_skb = 0;
+               chan->tx_skb = NULL;
        }
        netif_wake_queue(dev);
 }
@@ -718,11 +732,11 @@ static int cosa_sppp_close(struct net_device *d)
        spin_lock_irqsave(&chan->cosa->lock, flags);
        if (chan->rx_skb) {
                kfree_skb(chan->rx_skb);
-               chan->rx_skb = 0;
+               chan->rx_skb = NULL;
        }
        if (chan->tx_skb) {
                kfree_skb(chan->tx_skb);
-               chan->tx_skb = 0;
+               chan->tx_skb = NULL;
        }
        chan->usage=0;
        chan->cosa->usage--;
@@ -764,7 +778,7 @@ static int sppp_rx_done(struct channel_data *chan)
        chan->stats.rx_packets++;
        chan->stats.rx_bytes += chan->cosa->rxsize;
        netif_rx(chan->rx_skb);
-       chan->rx_skb = 0;
+       chan->rx_skb = NULL;
        chan->pppdev.dev->last_rx = jiffies;
        return 0;
 }
@@ -780,7 +794,7 @@ static int sppp_tx_done(struct channel_data *chan, int size)
                return 1;
        }
        dev_kfree_skb_irq(chan->tx_skb);
-       chan->tx_skb = 0;
+       chan->tx_skb = NULL;
        chan->stats.tx_packets++;
        chan->stats.tx_bytes += size;
        netif_wake_queue(chan->pppdev.dev);
@@ -803,7 +817,7 @@ static void chardev_channel_init(struct channel_data *chan)
 }
 
 static ssize_t cosa_read(struct file *file,
-       char *buf, size_t count, loff_t *ppos)
+       char __user *buf, size_t count, loff_t *ppos)
 {
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
@@ -878,7 +892,7 @@ static int chrdev_rx_done(struct channel_data *chan)
 
 
 static ssize_t cosa_write(struct file *file,
-       const char *buf, size_t count, loff_t *ppos)
+       const char __user *buf, size_t count, loff_t *ppos)
 {
        DECLARE_WAITQUEUE(wait, current);
        struct channel_data *chan = file->private_data;
@@ -1039,7 +1053,7 @@ static inline int cosa_reset(struct cosa_data *cosa)
 }
 
 /* High-level function to download data into COSA memory. Calls download() */
-static inline int cosa_download(struct cosa_data *cosa, unsigned long arg)
+static inline int cosa_download(struct cosa_data *cosa, void __user *arg)
 {
        struct cosa_download d;
        int i;
@@ -1053,7 +1067,7 @@ static inline int cosa_download(struct cosa_data *cosa, unsigned long arg)
                return -EPERM;
        }
        
-       if (copy_from_user(&d, (void __user *) arg, sizeof(d)))
+       if (copy_from_user(&d, arg, sizeof(d)))
                return -EFAULT;
 
        if (d.addr < 0 || d.addr > COSA_MAX_FIRMWARE_SIZE)
@@ -1078,7 +1092,7 @@ static inline int cosa_download(struct cosa_data *cosa, unsigned long arg)
 }
 
 /* High-level function to read COSA memory. Calls readmem() */
-static inline int cosa_readmem(struct cosa_data *cosa, unsigned long arg)
+static inline int cosa_readmem(struct cosa_data *cosa, void __user *arg)
 {
        struct cosa_download d;
        int i;
@@ -1093,7 +1107,7 @@ static inline int cosa_readmem(struct cosa_data *cosa, unsigned long arg)
                return -EPERM;
        }
 
-       if (copy_from_user(&d, (void __user *) arg, sizeof(d)))
+       if (copy_from_user(&d, arg, sizeof(d)))
                return -EFAULT;
 
        /* If something fails, force the user to reset the card */
@@ -1140,7 +1154,7 @@ static inline int cosa_start(struct cosa_data *cosa, int address)
 }
                
 /* Buffer of size at least COSA_MAX_ID_STRING is expected */
-static inline int cosa_getidstr(struct cosa_data *cosa, char *string)
+static inline int cosa_getidstr(struct cosa_data *cosa, char __user *string)
 {
        int l = strlen(cosa->id_string)+1;
        if (copy_to_user(string, cosa->id_string, l))
@@ -1149,7 +1163,7 @@ static inline int cosa_getidstr(struct cosa_data *cosa, char *string)
 }
 
 /* Buffer of size at least COSA_MAX_ID_STRING is expected */
-static inline int cosa_gettype(struct cosa_data *cosa, char *string)
+static inline int cosa_gettype(struct cosa_data *cosa, char __user *string)
 {
        int l = strlen(cosa->type)+1;
        if (copy_to_user(string, cosa->type, l))
@@ -1160,6 +1174,7 @@ static inline int cosa_gettype(struct cosa_data *cosa, char *string)
 static int cosa_ioctl_common(struct cosa_data *cosa,
        struct channel_data *channel, unsigned int cmd, unsigned long arg)
 {
+       void __user *argp = (void __user *)arg;
        switch(cmd) {
        case COSAIORSET:        /* Reset the device */
                if (!capable(CAP_NET_ADMIN))
@@ -1173,15 +1188,15 @@ static int cosa_ioctl_common(struct cosa_data *cosa,
                if (!capable(CAP_SYS_RAWIO))
                        return -EACCES;
                
-               return cosa_download(cosa, arg);
+               return cosa_download(cosa, argp);
        case COSAIORMEM:
                if (!capable(CAP_SYS_RAWIO))
                        return -EACCES;
-               return cosa_readmem(cosa, arg);
+               return cosa_readmem(cosa, argp);
        case COSAIORTYPE:
-               return cosa_gettype(cosa, (char *)arg);
+               return cosa_gettype(cosa, argp);
        case COSAIORIDSTR:
-               return cosa_getidstr(cosa, (char *)arg);
+               return cosa_getidstr(cosa, argp);
        case COSAIONRCARDS:
                return nr_cards;
        case COSAIONRCHANS:
@@ -1407,7 +1422,7 @@ static int cosa_dma_able(struct channel_data *chan, char *buf, int len)
  * by a single space. Monitor has to reply with a space. Now the download
  * begins. After the download monitor replies with "\r\n." (CR LF dot).
  */
-static int download(struct cosa_data *cosa, const char *microcode, int length, int address)
+static int download(struct cosa_data *cosa, const char __user *microcode, int length, int address)
 {
        int i;
 
@@ -1481,7 +1496,7 @@ static int startmicrocode(struct cosa_data *cosa, int address)
  * This routine is not needed during the normal operation and serves
  * for debugging purposes only.
  */
-static int readmem(struct cosa_data *cosa, char *microcode, int length, int address)
+static int readmem(struct cosa_data *cosa, char __user *microcode, int length, int address)
 {
        if (put_wait_data(cosa, 'r') == -1) return -1;
        if ((get_wait_data(cosa)) != 'r') return -2;
@@ -1536,8 +1551,7 @@ static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring)
        cosa_getdata8(cosa);
        cosa_putstatus(cosa, SR_RST);
 #ifdef MODULE
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(HZ/2);
+       msleep(500);
 #else
        udelay(5*100000);
 #endif
@@ -1590,8 +1604,7 @@ static int get_wait_data(struct cosa_data *cosa)
                        return r;
                }
                /* sleep if not ready to read */
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1);
+               schedule_timeout_interruptible(1);
        }
        printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
                cosa_getstatus(cosa));
@@ -1617,8 +1630,7 @@ static int put_wait_data(struct cosa_data *cosa, int data)
                }
 #if 0
                /* sleep if not ready to read */
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1);
+               schedule_timeout_interruptible(1);
 #endif
        }
        printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",