Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
[pandora-kernel.git] / drivers / char / synclink_gt.c
index 2f07b08..792c79c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $
+ * $Id: synclink_gt.c,v 4.36 2006/08/28 20:47:14 paulkf Exp $
  *
  * Device driver for Microgate SyncLink GT serial adapters.
  *
 
 #include "linux/synclink.h"
 
-#ifdef CONFIG_HDLC_MODULE
-#define CONFIG_HDLC 1
+#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE))
+#define SYNCLINK_GENERIC_HDLC 1
+#else
+#define SYNCLINK_GENERIC_HDLC 0
 #endif
 
 /*
  * module identification
  */
 static char *driver_name     = "SyncLink GT";
-static char *driver_version  = "$Revision: 4.25 $";
+static char *driver_version  = "$Revision: 4.36 $";
 static char *tty_driver_name = "synclink_gt";
 static char *tty_dev_prefix  = "ttySLG";
 MODULE_LICENSE("GPL");
 #define MGSL_MAGIC 0x5401
-#define MAX_DEVICES 12
+#define MAX_DEVICES 32
 
 static struct pci_device_id pci_table[] = {
        {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
@@ -149,7 +151,7 @@ static struct tty_driver *serial_driver;
 static int  open(struct tty_struct *tty, struct file * filp);
 static void close(struct tty_struct *tty, struct file * filp);
 static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct termios *old_termios);
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
 
 static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
 static void put_char(struct tty_struct *tty, unsigned char ch);
@@ -171,7 +173,7 @@ static void set_break(struct tty_struct *tty, int break_state);
 /*
  * generic HDLC support and callbacks
  */
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 #define dev_to_port(D) (dev_to_hdlc(D)->priv)
 static void hdlcdev_tx_done(struct slgt_info *info);
 static void hdlcdev_rx(struct slgt_info *info, char *buf, int size);
@@ -359,7 +361,7 @@ struct slgt_info {
        int netcount;
        int dosyncppp;
        spinlock_t netlock;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        struct net_device *netdev;
 #endif
 
@@ -461,7 +463,7 @@ static int  adapter_test(struct slgt_info *info);
 static void reset_adapter(struct slgt_info *info);
 static void reset_port(struct slgt_info *info);
 static void async_mode(struct slgt_info *info);
-static void hdlc_mode(struct slgt_info *info);
+static void sync_mode(struct slgt_info *info);
 
 static void rx_stop(struct slgt_info *info);
 static void rx_start(struct slgt_info *info);
@@ -485,13 +487,13 @@ static void enable_loopback(struct slgt_info *info);
 static void set_rate(struct slgt_info *info, u32 data_rate);
 
 static int  bh_action(struct slgt_info *info);
-static void bh_handler(void* context);
+static void bh_handler(struct work_struct *work);
 static void bh_transmit(struct slgt_info *info);
 static void isr_serial(struct slgt_info *info);
 static void isr_rdma(struct slgt_info *info);
 static void isr_txeom(struct slgt_info *info, unsigned short status);
 static void isr_tdma(struct slgt_info *info);
-static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t slgt_interrupt(int irq, void *dev_id);
 
 static int  alloc_dma_bufs(struct slgt_info *info);
 static void free_dma_bufs(struct slgt_info *info);
@@ -814,7 +816,7 @@ static void hangup(struct tty_struct *tty)
        wake_up_interruptible(&info->open_wait);
 }
 
-static void set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct slgt_info *info = tty->driver_data;
        unsigned long flags;
@@ -881,7 +883,9 @@ static int write(struct tty_struct *tty,
        if (!count)
                goto cleanup;
 
-       if (info->params.mode == MGSL_MODE_RAW) {
+       if (info->params.mode == MGSL_MODE_RAW ||
+           info->params.mode == MGSL_MODE_MONOSYNC ||
+           info->params.mode == MGSL_MODE_BISYNC) {
                unsigned int bufs_needed = (count/DMABUFSIZE);
                unsigned int bufs_free = free_tbuf_count(info);
                if (count % DMABUFSIZE)
@@ -1352,7 +1356,7 @@ static void set_break(struct tty_struct *tty, int break_state)
        spin_unlock_irqrestore(&info->lock,flags);
 }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 
 /**
  * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
@@ -1876,9 +1880,9 @@ static int bh_action(struct slgt_info *info)
 /*
  * perform bottom half processing
  */
-static void bh_handler(void* context)
+static void bh_handler(struct work_struct *work)
 {
-       struct slgt_info *info = context;
+       struct slgt_info *info = container_of(work, struct slgt_info, task);
        int action;
 
        if (!info)
@@ -1897,6 +1901,8 @@ static void bh_handler(void* context)
                                while(rx_get_frame(info));
                                break;
                        case MGSL_MODE_RAW:
+                       case MGSL_MODE_MONOSYNC:
+                       case MGSL_MODE_BISYNC:
                                while(rx_get_buf(info));
                                break;
                        }
@@ -1998,7 +2004,7 @@ static void dcd_change(struct slgt_info *info)
        } else {
                info->input_signal_events.dcd_down++;
        }
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount) {
                if (info->signals & SerialSignal_DCD)
                        netif_carrier_on(info->netdev);
@@ -2176,7 +2182,7 @@ static void isr_txeom(struct slgt_info *info, unsigned short status)
                        set_signals(info);
                }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                if (info->netcount)
                        hdlcdev_tx_done(info);
                else
@@ -2213,9 +2219,8 @@ static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int
  *
  *     irq     interrupt number
  *     dev_id  device ID supplied during interrupt registration
- *     regs    interrupted processor context
  */
-static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t slgt_interrupt(int irq, void *dev_id)
 {
        struct slgt_info *info;
        unsigned int gsr;
@@ -2362,10 +2367,9 @@ static void program_hw(struct slgt_info *info)
        rx_stop(info);
        tx_stop(info);
 
-       if (info->params.mode == MGSL_MODE_HDLC ||
-           info->params.mode == MGSL_MODE_RAW ||
+       if (info->params.mode != MGSL_MODE_ASYNC ||
            info->netcount)
-               hdlc_mode(info);
+               sync_mode(info);
        else
                async_mode(info);
 
@@ -2564,6 +2568,10 @@ static int rx_enable(struct slgt_info *info, int enable)
        if (enable) {
                if (!info->rx_enabled)
                        rx_start(info);
+               else if (enable == 2) {
+                       /* force hunt mode (write 1 to RCR[3]) */
+                       wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3);
+               }
        } else {
                if (info->rx_enabled)
                        rx_stop(info);
@@ -3300,7 +3308,7 @@ static void add_device(struct slgt_info *info)
                devstr, info->device_name, info->phys_reg_addr,
                info->irq_level, info->max_frame_size);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        hdlcdev_init(info);
 #endif
 }
@@ -3320,7 +3328,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
        } else {
                memset(info, 0, sizeof(struct slgt_info));
                info->magic = MGSL_MAGIC;
-               INIT_WORK(&info->task, bh_handler, info);
+               INIT_WORK(&info->task, bh_handler);
                info->max_frame_size = 4096;
                info->raw_rx_size = DMABUFSIZE;
                info->close_delay = 5*HZ/10;
@@ -3434,7 +3442,7 @@ static void __devexit remove_one(struct pci_dev *dev)
 {
 }
 
-static struct tty_operations ops = {
+static const struct tty_operations ops = {
        .open = open,
        .close = close,
        .write = write,
@@ -3482,7 +3490,7 @@ static void slgt_cleanup(void)
        /* release devices */
        info = slgt_device_list;
        while(info) {
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                hdlcdev_exit(info);
 #endif
                free_dma_bufs(info);
@@ -3516,6 +3524,7 @@ static int __init slgt_init(void)
 
        if (!slgt_device_list) {
                printk("%s no devices found\n",driver_name);
+               pci_unregister_driver(&pci_driver);
                return -ENODEV;
        }
 
@@ -3537,6 +3546,8 @@ static int __init slgt_init(void)
        serial_driver->init_termios = tty_std_termios;
        serial_driver->init_termios.c_cflag =
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       serial_driver->init_termios.c_ispeed = 9600;
+       serial_driver->init_termios.c_ospeed = 9600;
        serial_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(serial_driver, &ops);
        if ((rc = tty_register_driver(serial_driver)) < 0) {
@@ -3748,7 +3759,7 @@ static void tx_start(struct slgt_info *info)
 {
        if (!info->tx_enabled) {
                wr_reg16(info, TCR,
-                       (unsigned short)(rd_reg16(info, TCR) | BIT1));
+                        (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2));
                info->tx_enabled = TRUE;
        }
 
@@ -3775,13 +3786,18 @@ static void tx_start(struct slgt_info *info)
                                tdma_reset(info);
                                /* set 1st descriptor address */
                                wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
-                               if (info->params.mode == MGSL_MODE_RAW)
+                               switch(info->params.mode) {
+                               case MGSL_MODE_RAW:
+                               case MGSL_MODE_MONOSYNC:
+                               case MGSL_MODE_BISYNC:
                                        wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
-                               else
+                                       break;
+                               default:
                                        wr_reg32(info, TDCSR, BIT0); /* DMA enable */
+                               }
                        }
 
-                       if (info->params.mode != MGSL_MODE_RAW) {
+                       if (info->params.mode == MGSL_MODE_HDLC) {
                                info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
                                add_timer(&info->tx_timer);
                        }
@@ -3814,7 +3830,6 @@ static void tx_stop(struct slgt_info *info)
        /* reset and disable transmitter */
        val = rd_reg16(info, TCR) & ~BIT1;          /* clear enable bit */
        wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
-       wr_reg16(info, TCR, val);                  /* clear reset */
 
        slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
 
@@ -3982,7 +3997,7 @@ static void async_mode(struct slgt_info *info)
                enable_loopback(info);
 }
 
-static void hdlc_mode(struct slgt_info *info)
+static void sync_mode(struct slgt_info *info)
 {
        unsigned short val;
 
@@ -3992,7 +4007,7 @@ static void hdlc_mode(struct slgt_info *info)
 
        /* TCR (tx control)
         *
-        * 15..13  mode, 000=HDLC 001=raw sync
+        * 15..13  mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
         * 12..10  encoding
         * 09      CRC enable
         * 08      CRC32
@@ -4006,8 +4021,11 @@ static void hdlc_mode(struct slgt_info *info)
         */
        val = 0;
 
-       if (info->params.mode == MGSL_MODE_RAW)
-               val |= BIT13;
+       switch(info->params.mode) {
+       case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
+       case MGSL_MODE_BISYNC:   val |= BIT15; break;
+       case MGSL_MODE_RAW:      val |= BIT13; break;
+       }
        if (info->if_mode & MGSL_INTERFACE_RTS_EN)
                val |= BIT7;
 
@@ -4058,7 +4076,7 @@ static void hdlc_mode(struct slgt_info *info)
 
        /* RCR (rx control)
         *
-        * 15..13  mode, 000=HDLC 001=raw sync
+        * 15..13  mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
         * 12..10  encoding
         * 09      CRC enable
         * 08      CRC32
@@ -4069,8 +4087,11 @@ static void hdlc_mode(struct slgt_info *info)
         */
        val = 0;
 
-       if (info->params.mode == MGSL_MODE_RAW)
-               val |= BIT13;
+       switch(info->params.mode) {
+       case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
+       case MGSL_MODE_BISYNC:   val |= BIT15; break;
+       case MGSL_MODE_RAW:      val |= BIT13; break;
+       }
 
        switch(info->params.encoding)
        {
@@ -4309,10 +4330,15 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last
        while(!done) {
                /* reset current buffer for reuse */
                info->rbufs[i].status = 0;
-               if (info->params.mode == MGSL_MODE_RAW)
+               switch(info->params.mode) {
+               case MGSL_MODE_RAW:
+               case MGSL_MODE_MONOSYNC:
+               case MGSL_MODE_BISYNC:
                        set_desc_count(info->rbufs[i], info->raw_rx_size);
-               else
+                       break;
+               default:
                        set_desc_count(info->rbufs[i], DMABUFSIZE);
+               }
 
                if (i == last)
                        done = 1;
@@ -4412,7 +4438,7 @@ check_again:
                        framesize = 0;
        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (framesize == 0) {
                struct net_device_stats *stats = hdlc_stats(info->netdev);
                stats->rx_errors++;
@@ -4455,7 +4481,7 @@ check_again:
                                framesize++;
                        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                        if (info->netcount)
                                hdlcdev_rx(info,info->tmp_rbuf, framesize);
                        else
@@ -4477,13 +4503,24 @@ cleanup:
 static int rx_get_buf(struct slgt_info *info)
 {
        unsigned int i = info->rbuf_current;
+       unsigned int count;
 
        if (!desc_complete(info->rbufs[i]))
                return 0;
-       DBGDATA(info, info->rbufs[i].buf, desc_count(info->rbufs[i]), "rx");
-       DBGINFO(("rx_get_buf size=%d\n", desc_count(info->rbufs[i])));
-       ldisc_receive_buf(info->tty, info->rbufs[i].buf,
-                         info->flag_buf, desc_count(info->rbufs[i]));
+       count = desc_count(info->rbufs[i]);
+       switch(info->params.mode) {
+       case MGSL_MODE_MONOSYNC:
+       case MGSL_MODE_BISYNC:
+               /* ignore residue in byte synchronous modes */
+               if (desc_residue(info->rbufs[i]))
+                       count--;
+               break;
+       }
+       DBGDATA(info, info->rbufs[i].buf, count, "rx");
+       DBGINFO(("rx_get_buf size=%d\n", count));
+       if (count)
+               ldisc_receive_buf(info->tty, info->rbufs[i].buf,
+                                 info->flag_buf, count);
        free_rbufs(info, i, i);
        return 1;
 }
@@ -4549,8 +4586,13 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
                size -= count;
                buf  += count;
 
-               if (!size && info->params.mode != MGSL_MODE_RAW)
-                       set_desc_eof(*d, 1); /* HDLC: set EOF of last desc */
+               /*
+                * set EOF bit for last buffer of HDLC frame or
+                * for every buffer in raw mode
+                */
+               if ((!size && info->params.mode == MGSL_MODE_HDLC) ||
+                   info->params.mode == MGSL_MODE_RAW)
+                       set_desc_eof(*d, 1);
                else
                        set_desc_eof(*d, 0);
 
@@ -4742,7 +4784,7 @@ static void tx_timeout(unsigned long context)
        info->tx_count = 0;
        spin_unlock_irqrestore(&info->lock,flags);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount)
                hdlcdev_tx_done(info);
        else
@@ -4762,6 +4804,6 @@ static void rx_timeout(unsigned long context)
        spin_lock_irqsave(&info->lock, flags);
        info->pending_bh |= BH_RECEIVE;
        spin_unlock_irqrestore(&info->lock, flags);
-       bh_handler(info);
+       bh_handler(&info->task);
 }